0
votes

I got a below program, I can parse the pattern like convert(a.ACCOUNT_ID, string) to the expression, but I want to replace this pattern with CAST(a.ACCOUNT_ID AS VARCHAR). I can do parse the result expression and replace the strings with the one above but there are expressions like this hence I don't want to do that way.. Is there any way that I can do a pattern replace? Like if I find a pattern as convert(a.ACCOUNT_ID, string) then replace it with CAST(a.ACCOUNT_ID AS VARCHAR)

import scala.util.parsing.combinator._
import scala.util.parsing.combinator.lexical._
import scala.util.parsing.combinator.syntactical._
import scala.util.parsing.combinator.token._
import scala.util.parsing.input.CharSequenceReader


trait QParser  extends RegexParsers with JavaTokenParsers  {
  def knownFunction: Parser[Any] = ident ~ "(" ~ ident ~ ("." ~ ident <~ "," ~ ident ~ ")")

  def parse(inputString: String): Any = synchronized {
    phrase(knownFunction)(new CharSequenceReader(inputString)) match {
      case Success(result, _) => result
      case Failure(msg,_) => throw new DataTypeException(msg)
      case Error(msg,_) => throw new DataTypeException(msg)
    }
  }

 class DataTypeException(message: String) extends Exception(message)

}

object Parser extends QParser {
  def main(args: Array[String]) {
     println(parse("convert(a.ACCOUNT_ID, string)"));
  }
}

Output: (((convert~()~a)~(.~ACCOUNT_ID))

1
What do you mean when you say that you want to "replace" convert(a.ACCOUNT_ID, string) with CAST(a.ACCOUNT_ID AS VARCHAR)? That you want to parse it into the same representation? In that case it should be noted that you're not current parsing CAST(a.ACCOUNT_ID AS VARCHAR) at all. - sepp2k
Say I have a long sql string with some pattern convert(ident.ident, ident) ex. "select convert(a.ACCOUNT_ID, string) from dual". I want to convert it to "select cast(a.ACCOUNT_ID AS VARCHAR) from dual" - Sathish
I see. I suppose I was confused because currently your parser don't produce strings as their result and I did not realize that that was the intention. - sepp2k

1 Answers

2
votes

I am not exactly sure what you mean with "there are expressions like this hence I don't want to do that way", but you can transform the result of your parser function using the ^^ operator.

A transformation function for your parser could be :

def knownFunction: Parser[String] = 
  ident ~ "(" ~ ident ~ "." ~ ident ~ "," ~ ident ~ ")" ^^ {
    case func ~ "(" ~ obj ~ "." ~ value ~ "," ~ castType ~ ")" =>
      val sqlFunc = Map("convert" -> "CAST")
      val sqlType = Map("string" -> "VARCHAR")
      s"${sqlFunc(func)}($obj.$value AS ${sqlType(castType)})"
  }

Using this updated function, the output of your application would be :

CAST(a.ACCOUNT_ID AS VARCHAR)

More information about the Scala Combinator Parsing can be found in a chapter of Programming in Scala, 1ed.