@@ -5,7 +5,9 @@ using namespace std;
55
66namespace {
77
8- string convertFunctionByType (const std::string& typeName) {
8+ string processEscapeSequencesImpl (const StringView seq, Lexer& lex);
9+
10+ string convertFunctionByType (const StringView& typeName) {
911 if (typeName == " SQL_BIGINT" ) {
1012 return " toInt64" ;
1113 }
@@ -16,29 +18,53 @@ string convertFunctionByType(const std::string& typeName) {
1618}
1719
1820string processFunction (const StringView seq, Lexer& lex) {
19- if (!lex.Match (Token::CONVERT)) {
20- return seq.to_string ();
21- }
22- if (!lex.Match (Token::LPARENT)) {
23- return seq.to_string ();
24- }
21+ const Token fn (lex.Consume ());
2522
26- Token num = lex.Consume ();
27- if (num.type != Token::NUMBER) {
28- return seq.to_string ();
29- }
30- if (!lex.Match (Token::COMMA)) {
31- return seq.to_string ();
32- }
33- Token type = lex.Consume ();
34- if (type.type != Token::IDENT) {
35- return seq.to_string ();
36- }
23+ if (fn.type == Token::CONVERT) {
24+ if (!lex.Match (Token::LPARENT)) {
25+ return seq.to_string ();
26+ }
27+
28+ Token num = lex.Consume ();
29+ if (num.type != Token::NUMBER) {
30+ return seq.to_string ();
31+ }
32+ if (!lex.Match (Token::COMMA)) {
33+ return seq.to_string ();
34+ }
35+ Token type = lex.Consume ();
36+ if (type.type != Token::IDENT) {
37+ return seq.to_string ();
38+ }
3739
38- string func = convertFunctionByType (type.literal .to_string ());
40+ string func = convertFunctionByType (type.literal .to_string ());
3941
40- if (!func.empty ()) {
41- return func + " (" + num.literal .to_string () + " )" ;
42+ if (!func.empty ()) {
43+ if (!lex.Match (Token::RPARENT)) {
44+ return seq.to_string ();
45+ }
46+ return func + " (" + num.literal .to_string () + " )" ;
47+ }
48+
49+ } else if (fn.type == Token::CONCAT) {
50+ string result = " concat" ;
51+
52+ while (true ) {
53+ const Token tok (lex.Peek ());
54+
55+ if (tok.type == Token::RCURLY) {
56+ break ;
57+ } else if (tok.type == Token::LCURLY) {
58+ result += processEscapeSequencesImpl (seq, lex);
59+ } else if (tok.type == Token::EOS || tok.type == Token::INVALID) {
60+ break ;
61+ } else {
62+ result += tok.literal .to_string ();
63+ lex.Consume ();
64+ }
65+ }
66+
67+ return result;
4268 }
4369
4470 return seq.to_string ();
@@ -49,7 +75,7 @@ string processDate(const StringView seq, Lexer& lex) {
4975 if (data.isInvalid ()) {
5076 return seq.to_string ();
5177 } else {
52- return string (" toDate(' " ) + data.literal .to_string () + " ' )" ;
78+ return string (" toDate(" ) + data.literal .to_string () + " )" ;
5379 }
5480}
5581
@@ -58,29 +84,47 @@ string processDateTime(const StringView seq, Lexer& lex) {
5884 if (data.isInvalid ()) {
5985 return seq.to_string ();
6086 } else {
61- return string (" toDateTime(' " ) + data.literal .to_string () + " ' )" ;
87+ return string (" toDateTime(" ) + data.literal .to_string () + " )" ;
6288 }
6389}
6490
65- string processEscapeSequences (const StringView seq) {
66- Lexer lex (seq) ;
91+ string processEscapeSequencesImpl (const StringView seq, Lexer& lex ) {
92+ string result ;
6793
68- Token cmd = lex.Consume ();
69- switch (cmd.type ) {
70- case Token::FN:
71- return processFunction (seq, lex);
72- case Token::D:
73- return processDate (seq, lex);
74- case Token::TS:
75- return processDateTime (seq, lex);
76-
77- // Unimplemented
78- case Token::T:
79- default :
80- break ;
94+ if (!lex.Match (Token::LCURLY)) {
95+ return seq.to_string ();
8196 }
8297
83- return seq.to_string ();
98+ while (true ) {
99+ const Token tok (lex.Consume ());
100+
101+ switch (tok.type ) {
102+ case Token::FN:
103+ result += processFunction (seq, lex);
104+ break ;
105+
106+ case Token::D:
107+ result += processDate (seq, lex);
108+ break ;
109+ case Token::TS:
110+ result += processDateTime (seq, lex);
111+ break ;
112+
113+ // End of escape sequence
114+ case Token::RCURLY:
115+ return result;
116+
117+ // Unimplemented
118+ case Token::T:
119+ default :
120+ return seq.to_string ();
121+ }
122+ };
123+ }
124+
125+ string processEscapeSequences (const StringView seq) {
126+ Lexer lex (seq);
127+ return processEscapeSequencesImpl (seq, lex);
84128}
85129
86130} // namespace
@@ -95,12 +139,12 @@ std::string replaceEscapeSequences(const std::string & query)
95139
96140 while (p != end) {
97141 switch (*p) {
98- case ' {' : // TODO {fn
142+ case ' {' :
99143 if (level == 0 ) {
100144 if (st < p) {
101145 ret += std::string (st, p);
102146 }
103- st = p + 1 ;
147+ st = p;
104148 }
105149 level++;
106150 break ;
@@ -111,7 +155,7 @@ std::string replaceEscapeSequences(const std::string & query)
111155 return query;
112156 }
113157 if (--level == 0 ) {
114- ret += processEscapeSequences (StringView (st, p));
158+ ret += processEscapeSequences (StringView (st, p + 1 ));
115159 st = p + 1 ;
116160 }
117161 break ;
0 commit comments