11package com .clickhouse .jdbc .internal ;
22
33import com .clickhouse .client .api .sql .SQLUtils ;
4- import com .clickhouse .jdbc .internal .parser .ClickHouseLexer ;
5- import com .clickhouse .jdbc .internal .parser .ClickHouseParser ;
6- import com .clickhouse .jdbc .internal .parser .ClickHouseParserBaseListener ;
4+ import com .clickhouse .data .ClickHouseUtils ;
5+ import com .clickhouse .jdbc .internal .parser .antlr4 .ClickHouseLexer ;
6+ import com .clickhouse .jdbc .internal .parser .antlr4 .ClickHouseParser ;
7+ import com .clickhouse .jdbc .internal .parser .antlr4 .ClickHouseParserBaseListener ;
78import org .antlr .v4 .runtime .BaseErrorListener ;
89import org .antlr .v4 .runtime .CharStream ;
910import org .antlr .v4 .runtime .CharStreams ;
@@ -28,7 +29,7 @@ public abstract class SqlParserFacade {
2829
2930 public abstract ParsedPreparedStatement parsePreparedStatement (String sql );
3031
31- static final class ANTLR4Parser extends SqlParserFacade {
32+ private static class ANTLR4Parser extends SqlParserFacade {
3233
3334 @ Override
3435 public ParsedStatement parsedStatement (String sql ) {
@@ -41,10 +42,11 @@ public ParsedStatement parsedStatement(String sql) {
4142 public ParsedPreparedStatement parsePreparedStatement (String sql ) {
4243 ParsedPreparedStatement stmt = new ParsedPreparedStatement ();
4344 parseSQL (sql , new ParsedPreparedStatementListener (stmt ));
45+ parseParameters (sql , stmt );
4446 return stmt ;
4547 }
4648
47- private ClickHouseParser parseSQL (String sql , ClickHouseParserBaseListener listener ) {
49+ protected ClickHouseParser parseSQL (String sql , ClickHouseParserBaseListener listener ) {
4850 CharStream charStream = CharStreams .fromString (sql );
4951 ClickHouseLexer lexer = new ClickHouseLexer (charStream );
5052 ClickHouseParser parser = new ClickHouseParser (new CommonTokenStream (lexer ));
@@ -112,9 +114,9 @@ public void enterSetRoleStmt(ClickHouseParser.SetRoleStmtContext ctx) {
112114 }
113115 }
114116
115- private static final class ParsedPreparedStatementListener extends ClickHouseParserBaseListener {
117+ protected static class ParsedPreparedStatementListener extends ClickHouseParserBaseListener {
116118
117- private final ParsedPreparedStatement parsedStatement ;
119+ protected final ParsedPreparedStatement parsedStatement ;
118120
119121 public ParsedPreparedStatementListener (ParsedPreparedStatement parsedStatement ) {
120122 this .parsedStatement = parsedStatement ;
@@ -147,21 +149,11 @@ public void enterSetRoleStmt(ClickHouseParser.SetRoleStmtContext ctx) {
147149 }
148150 }
149151
150- @ Override
151- public void enterColumnExprParam (ClickHouseParser .ColumnExprParamContext ctx ) {
152- parsedStatement .appendParameter (ctx .start .getStartIndex ());
153- }
154-
155152 @ Override
156153 public void enterColumnExprPrecedence3 (ClickHouseParser .ColumnExprPrecedence3Context ctx ) {
157154 super .enterColumnExprPrecedence3 (ctx );
158155 }
159156
160- @ Override
161- public void enterCteUnboundColParam (ClickHouseParser .CteUnboundColParamContext ctx ) {
162- parsedStatement .appendParameter (ctx .start .getStartIndex ());
163- }
164-
165157 @ Override
166158 public void visitErrorNode (ErrorNode node ) {
167159 parsedStatement .setHasErrors (true );
@@ -178,24 +170,6 @@ public void enterAssignmentValuesList(ClickHouseParser.AssignmentValuesListConte
178170 parsedStatement .setAssignValuesListStopPosition (ctx .getStop ().getStopIndex ());
179171 }
180172
181- @ Override
182- public void enterInsertParameter (ClickHouseParser .InsertParameterContext ctx ) {
183- parsedStatement .appendParameter (ctx .start .getStartIndex ());
184- }
185-
186- @ Override
187- public void enterFromClause (ClickHouseParser .FromClauseContext ctx ) {
188- if (ctx .JDBC_PARAM_PLACEHOLDER () != null ) {
189- parsedStatement .appendParameter (ctx .JDBC_PARAM_PLACEHOLDER ().getSymbol ().getStartIndex ());
190- }
191- }
192-
193- @ Override
194- public void enterViewParam (ClickHouseParser .ViewParamContext ctx ) {
195- if (ctx .JDBC_PARAM_PLACEHOLDER () != null ) {
196- parsedStatement .appendParameter (ctx .JDBC_PARAM_PLACEHOLDER ().getSymbol ().getStartIndex ());
197- }
198- }
199173
200174 @ Override
201175 public void enterTableExprIdentifier (ClickHouseParser .TableExprIdentifierContext ctx ) {
@@ -241,22 +215,96 @@ public void exitInsertParameterFuncExpr(ClickHouseParser.InsertParameterFuncExpr
241215 }
242216 }
243217
218+ private static class ANTLR4AndParamsParser extends ANTLR4Parser {
219+
220+ @ Override
221+ public ParsedPreparedStatement parsePreparedStatement (String sql ) {
222+ ParsedPreparedStatement stmt = new ParsedPreparedStatement ();
223+ parseSQL (sql , new ParseStatementAndParamsListener (stmt ));
224+ return stmt ;
225+ }
226+
227+ private static class ParseStatementAndParamsListener extends ParsedPreparedStatementListener {
228+
229+ public ParseStatementAndParamsListener (ParsedPreparedStatement parsedStatement ) {
230+ super (parsedStatement );
231+ }
232+
233+ @ Override
234+ public void enterColumnExprParam (ClickHouseParser .ColumnExprParamContext ctx ) {
235+ parsedStatement .appendParameter (ctx .start .getStartIndex ());
236+ }
237+
238+
239+ @ Override
240+ public void enterCteUnboundColParam (ClickHouseParser .CteUnboundColParamContext ctx ) {
241+ parsedStatement .appendParameter (ctx .start .getStartIndex ());
242+ }
243+
244+ @ Override
245+ public void enterInsertParameter (ClickHouseParser .InsertParameterContext ctx ) {
246+ parsedStatement .appendParameter (ctx .start .getStartIndex ());
247+ }
248+
249+ @ Override
250+ public void enterFromClause (ClickHouseParser .FromClauseContext ctx ) {
251+ if (ctx .JDBC_PARAM_PLACEHOLDER () != null ) {
252+ parsedStatement .appendParameter (ctx .JDBC_PARAM_PLACEHOLDER ().getSymbol ().getStartIndex ());
253+ }
254+ }
255+
256+ @ Override
257+ public void enterViewParam (ClickHouseParser .ViewParamContext ctx ) {
258+ if (ctx .JDBC_PARAM_PLACEHOLDER () != null ) {
259+ parsedStatement .appendParameter (ctx .JDBC_PARAM_PLACEHOLDER ().getSymbol ().getStartIndex ());
260+ }
261+ }
262+ }
263+ }
264+
265+ private static void parseParameters (String originalQuery , ParsedPreparedStatement stmt ) {
266+ int len = originalQuery .length ();
267+ for (int i = 0 ; i < len ; i ++) {
268+ char ch = originalQuery .charAt (i );
269+ if (ClickHouseUtils .isQuote (ch )) {
270+ i = ClickHouseUtils .skipQuotedString (originalQuery , i , len , ch ) - 1 ;
271+ } else if (ch == '?' ) {
272+ int idx = ClickHouseUtils .skipContentsUntil (originalQuery , i + 2 , len , '?' , ':' );
273+ if (idx < len && originalQuery .charAt (idx - 1 ) == ':' && originalQuery .charAt (idx ) != ':'
274+ && originalQuery .charAt (idx - 2 ) != ':' ) {
275+ i = idx - 1 ;
276+ } else {
277+ stmt .appendParameter (i );
278+ }
279+ } else if (ch == ';' ) {
280+ continue ;
281+ } else if (i + 1 < len ) {
282+ char nextCh = originalQuery .charAt (i + 1 );
283+ if (ch == '-' && nextCh == ch ) {
284+ i = ClickHouseUtils .skipSingleLineComment (originalQuery , i + 2 , len ) - 1 ;
285+ } else if (ch == '/' && nextCh == '*' ) {
286+ i = ClickHouseUtils .skipMultiLineComment (originalQuery , i + 2 , len ) - 1 ;
287+ }
288+ }
289+ }
290+ }
291+
292+
244293 public enum SQLParser {
245294 /**
246295 * JavaCC used to determine sql type (SELECT, INSERT, etc.) and extract some information
247296 * Separate procedure parses sql for `?` parameter placeholders.
248297 */
249- JAVACC_PARAMS_PARSER ,
298+ JAVACC ,
250299
251300 /**
252- * ANTLR4 used to determine sql type (SELECT, INSERT, etc.) and extract some information
253- * Separate procedure parses sql for `?` parameter placeholders.
301+ * ANTLR4 used to determine sql type (SELECT, INSERT, etc.) and extract some information and parameters
254302 */
255303 ANTLR4_PARAMS_PARSER ,
256304
257305 /**
258- * ANTLR4 used to determine sql type (SELECT, INSERT, etc.), extract some information
259- * and determine parameter positions .
306+ * ANTLR4 used to determine sql type (SELECT, INSERT, etc.), extract some information.
307+ * Separate procedure parses sql for `?` parameter placeholders .
260308 */
261309 ANTLR4
262310 }
@@ -265,10 +313,10 @@ public static SqlParserFacade getParser(String name) throws SQLException {
265313 try {
266314 SQLParser parserSelection = SQLParser .valueOf (name );
267315 switch (parserSelection ) {
268- case JAVACC_PARAMS_PARSER :
316+ case JAVACC :
269317 return null ;
270318 case ANTLR4_PARAMS_PARSER :
271- return null ;
319+ return new ANTLR4AndParamsParser () ;
272320 case ANTLR4 :
273321 return new ANTLR4Parser ();
274322 }
0 commit comments