@@ -20,6 +20,7 @@ public class YdbQueryParser {
20
20
private final boolean isDetectJdbcParameters ;
21
21
22
22
private final List <QueryStatement > statements = new ArrayList <>();
23
+ private final YqlBatcher batcher = new YqlBatcher ();
23
24
24
25
public YdbQueryParser (boolean isDetectQueryType , boolean isDetectJdbcParameters ) {
25
26
this .isDetectQueryType = isDetectQueryType ;
@@ -30,6 +31,10 @@ public List<QueryStatement> getStatements() {
30
31
return this .statements ;
31
32
}
32
33
34
+ public YqlBatcher getYqlBatcher () {
35
+ return this .batcher ;
36
+ }
37
+
33
38
public QueryType detectQueryType () throws SQLException {
34
39
QueryType type = null ;
35
40
for (QueryStatement st : statements ) {
@@ -53,6 +58,7 @@ public QueryType detectQueryType() throws SQLException {
53
58
@ SuppressWarnings ("MethodLength" )
54
59
public String parseSQL (String origin ) throws SQLException {
55
60
this .statements .clear ();
61
+ this .batcher .clear ();
56
62
57
63
int fragmentStart = 0 ;
58
64
@@ -73,20 +79,22 @@ public String parseSQL(String origin) throws SQLException {
73
79
char ch = chars [i ];
74
80
boolean isInsideKeyword = false ;
75
81
switch (ch ) {
76
- case '(' :
77
- parenLevel ++;
78
- break ;
79
-
80
- case ')' :
81
- parenLevel --;
82
- break ;
83
-
84
82
case '\'' : // single-quotes
85
- i = parseSingleQuotes (chars , i );
83
+ int singleQuitesEnd = parseSingleQuotes (chars , i );
84
+ batcher .readSingleQuoteLiteral (chars , i , singleQuitesEnd - i + 1 );
85
+ i = singleQuitesEnd ;
86
86
break ;
87
87
88
88
case '"' : // double-quotes
89
- i = parseDoubleQuotes (chars , i );
89
+ int doubleQuitesEnd = parseDoubleQuotes (chars , i );
90
+ batcher .readDoubleQuoteLiteral (chars , i , doubleQuitesEnd - i + 1 );
91
+ i = doubleQuitesEnd ;
92
+ break ;
93
+
94
+ case '`' : // backtick-quotes
95
+ int backstickQuitesEnd = parseBacktickQuotes (chars , i );
96
+ batcher .readIdentifier (chars , i , backstickQuitesEnd - i + 1 );
97
+ i = backstickQuitesEnd ;
90
98
break ;
91
99
92
100
case '-' : // possibly -- style comment
@@ -101,6 +109,7 @@ public String parseSQL(String origin) throws SQLException {
101
109
parsed .append (chars , fragmentStart , i - fragmentStart );
102
110
if (i + 1 < chars .length && chars [i + 1 ] == '?' ) /* replace ?? with ? */ {
103
111
parsed .append ('?' );
112
+ batcher .readIdentifier (chars , i , 1 );
104
113
i ++; // make sure the coming ? is not treated as a bind
105
114
} else {
106
115
String binded = argNameGenerator .createArgName (origin );
@@ -110,6 +119,8 @@ public String parseSQL(String origin) throws SQLException {
110
119
: null ;
111
120
currStatement .addParameter (binded , type );
112
121
parsed .append (binded );
122
+
123
+ batcher .readParameter ();
113
124
}
114
125
fragmentStart = i + 1 ;
115
126
}
@@ -129,8 +140,11 @@ public String parseSQL(String origin) throws SQLException {
129
140
130
141
if (keywordStart >= 0 && (!isInsideKeyword || (i == chars .length - 1 ))) {
131
142
lastKeywordIsOffsetLimit = false ;
143
+ int keywordLength = isInsideKeyword ? i - keywordStart - 1 : i - keywordStart ;
132
144
133
145
if (currStatement != null ) {
146
+ batcher .readIdentifier (chars , keywordStart , keywordLength );
147
+
134
148
// Detect RETURNING keyword
135
149
if (parenLevel == 0 && parseReturningKeyword (chars , keywordStart )) {
136
150
currStatement .setHasReturning (true );
@@ -147,11 +161,17 @@ public String parseSQL(String origin) throws SQLException {
147
161
if (parseSelectKeyword (chars , keywordStart )) {
148
162
currStatement = new QueryStatement (QueryType .DATA_QUERY , QueryCmd .SELECT );
149
163
}
164
+
150
165
// starts with INSERT, UPSERT
151
- if (parseInsertKeyword (chars , keywordStart )
152
- || parseUpsertKeyword (chars , keywordStart )) {
166
+ if (parseInsertKeyword (chars , keywordStart )) {
153
167
currStatement = new QueryStatement (QueryType .DATA_QUERY , QueryCmd .INSERT_UPSERT );
168
+ batcher .readInsert ();
154
169
}
170
+ if (parseUpsertKeyword (chars , keywordStart )) {
171
+ currStatement = new QueryStatement (QueryType .DATA_QUERY , QueryCmd .INSERT_UPSERT );
172
+ batcher .readUpsert ();
173
+ }
174
+
155
175
// starts with UPDATE, REPLACE, DELETE
156
176
if (parseUpdateKeyword (chars , keywordStart )
157
177
|| parseDeleteKeyword (chars , keywordStart )
@@ -165,6 +185,7 @@ public String parseSQL(String origin) throws SQLException {
165
185
|| parseDropKeyword (chars , keywordStart )) {
166
186
currStatement = new QueryStatement (QueryType .SCHEME_QUERY , QueryCmd .CREATE_ALTER_DROP );
167
187
}
188
+
168
189
if (isDetectQueryType ) {
169
190
// Detect scan expression - starts with SCAN
170
191
if (parseScanKeyword (chars , keywordStart )) {
@@ -186,21 +207,33 @@ public String parseSQL(String origin) throws SQLException {
186
207
detectJdbcArgs = currStatement .getType () != QueryType .SCHEME_QUERY
187
208
&& currStatement .getType () != QueryType .UNKNOWN
188
209
&& isDetectJdbcParameters ;
189
-
190
- if (parseAlterKeyword (chars , i )
191
- || parseCreateKeyword (chars , i )
192
- || parseDropKeyword (chars , i )) {
193
- currStatement = new QueryStatement (QueryType .SCHEME_QUERY , QueryCmd .CREATE_ALTER_DROP );
194
- statements .add (currStatement );
195
- }
196
210
}
197
211
198
212
keywordStart = -1 ;
199
213
}
200
214
201
- if (ch == ';' && parenLevel == 0 ) {
202
- currStatement = null ;
203
- detectJdbcArgs = false ;
215
+ switch (ch ) {
216
+ case '(' :
217
+ parenLevel ++;
218
+ batcher .readOpenParen ();
219
+ break ;
220
+ case ')' :
221
+ parenLevel --;
222
+ batcher .readCloseParen ();
223
+ break ;
224
+ case ',' :
225
+ batcher .readComma ();
226
+ break ;
227
+ case ';' :
228
+ batcher .readSemiColon ();
229
+ if (parenLevel == 0 ) {
230
+ currStatement = null ;
231
+ detectJdbcArgs = false ;
232
+ }
233
+ break ;
234
+ default :
235
+ // nothing
236
+ break ;
204
237
}
205
238
}
206
239
@@ -250,6 +283,14 @@ private static int parseDoubleQuotes(final char[] query, int offset) {
250
283
return offset ;
251
284
}
252
285
286
+ @ SuppressWarnings ("EmptyBlock" )
287
+ private static int parseBacktickQuotes (final char [] query , int offset ) {
288
+ while (++offset < query .length && query [offset ] != '`' ) {
289
+ // do nothing
290
+ }
291
+ return offset ;
292
+ }
293
+
253
294
private static int parseLineComment (final char [] query , int offset ) {
254
295
if (offset + 1 < query .length && query [offset + 1 ] == '-' ) {
255
296
while (offset + 1 < query .length ) {
0 commit comments