44import com .clickhouse .data .Tuple ;
55import com .clickhouse .jdbc .internal .ExceptionUtils ;
66import com .clickhouse .jdbc .internal .JdbcUtils ;
7+ import com .clickhouse .jdbc .internal .StatementParser ;
78import com .clickhouse .jdbc .metadata .ParameterMetaDataImpl ;
89import com .clickhouse .jdbc .metadata .ResultSetMetaDataImpl ;
910import org .slf4j .Logger ;
@@ -67,7 +68,7 @@ public class PreparedStatementImpl extends StatementImpl implements PreparedStat
6768 private final String originalSql ;
6869 private final String [] sqlSegments ;
6970 private final Object [] parameters ;
70- private final StatementType statementType ;
71+ private final StatementParser . StatementType statementType ;
7172
7273 // insert
7374 private String [] valueSegments ;
@@ -84,15 +85,15 @@ public class PreparedStatementImpl extends StatementImpl implements PreparedStat
8485
8586 private static final Pattern VALUES_PARAMETER_SPLIT = Pattern .compile ("\\ ?(?=(?:[^']*'[^']*')*[^']*$)" );
8687
87- public PreparedStatementImpl (ConnectionImpl connection , String sql , StatementType statementType ) throws SQLException {
88+ public PreparedStatementImpl (ConnectionImpl connection , String sql , StatementParser . ParsedStatement parsedStatement ) throws SQLException {
8889 super (connection );
8990 this .isPoolable = true ; // PreparedStatement is poolable by default
9091 this .originalSql = sql .trim ();
9192 //Split the sql string into an array of strings around question mark tokens
92- this .sqlSegments = splitStatement ( originalSql );
93- this .statementType = statementType ;
93+ this .sqlSegments = parsedStatement . getSqlSegments ( );
94+ this .statementType = parsedStatement . getType () ;
9495
95- if (this .statementType == StatementType .INSERT ) {
96+ if (this .statementType == StatementParser . StatementType .INSERT ) {
9697 insertIntoSQL = originalSql .substring (0 , originalSql .indexOf ("VALUES" ) + 6 );
9798 valueSegments = originalSql .substring (originalSql .indexOf ("VALUES" ) + 6 ).split ("\\ ?" );
9899 }
@@ -257,7 +258,7 @@ public boolean execute() throws SQLException {
257258 @ Override
258259 public void addBatch () throws SQLException {
259260 checkClosed ();
260- if (statementType == StatementType .INSERT ) {
261+ if (statementType == StatementParser . StatementType .INSERT ) {
261262 // adding values to the end of big INSERT statement.
262263 addBatch (compileSql (valueSegments ));
263264 } else {
@@ -268,7 +269,7 @@ public void addBatch() throws SQLException {
268269 @ Override
269270 public int [] executeBatch () throws SQLException {
270271 checkClosed ();
271- if (statementType == StatementType .INSERT && !batch .isEmpty ()) {
272+ if (statementType == StatementParser . StatementType .INSERT && !batch .isEmpty ()) {
272273 // write insert into as batch to avoid multiple requests
273274 StringBuilder sb = new StringBuilder ();
274275 sb .append (insertIntoSQL ).append (" " );
@@ -343,7 +344,7 @@ public ResultSetMetaData getMetaData() throws SQLException {
343344
344345 if (resultSetMetaData == null && currentResultSet == null ) {
345346 // before execution
346- if (statementType == StatementType .SELECT ) {
347+ if (statementType == StatementParser . StatementType .SELECT ) {
347348 try {
348349 // Replace '?' with NULL to make SQL valid for DESCRIBE
349350 String sql = JdbcUtils .replaceQuestionMarks (originalSql , JdbcUtils .NULL );
@@ -689,74 +690,7 @@ private static String encodeObject(Object x) throws SQLException {
689690 }
690691 }
691692
692-
693693 private static String escapeString (String x ) {
694694 return x .replace ("\\ " , "\\ \\ " ).replace ("'" , "\\ '" );//Escape single quotes
695695 }
696-
697- private static String [] splitStatement (String sql ) {
698- List <String > segments = new ArrayList <>();
699- char [] chars = sql .toCharArray ();
700- int segmentStart = 0 ;
701- for (int i = 0 ; i < chars .length ; i ++) {
702- char c = chars [i ];
703- if (c == '\'' || c == '"' || c == '`' ) {
704- // string literal or identifier
705- i = skip (chars , i + 1 , c , true );
706- } else if (c == '/' && lookahead (chars , i ) == '*' ) {
707- // block comment
708- int end = sql .indexOf ("*/" , i );
709- if (end == -1 ) {
710- // missing comment end
711- break ;
712- }
713- i = end + 1 ;
714- } else if (c == '#' || (c == '-' && lookahead (chars , i ) == '-' )) {
715- // line comment
716- i = skip (chars , i + 1 , '\n' , false );
717- } else if (c == '?' ) {
718- // question mark
719- segments .add (sql .substring (segmentStart , i ));
720- segmentStart = i + 1 ;
721- }
722- }
723- if (segmentStart < chars .length ) {
724- segments .add (sql .substring (segmentStart ));
725- } else {
726- // add empty segment in case question mark was last char of sql
727- segments .add ("" );
728- }
729- return segments .toArray (new String [0 ]);
730- }
731-
732- private static int skip (char [] chars , int from , char until , boolean escape ) {
733- for (int i = from ; i < chars .length ; i ++) {
734- char curr = chars [i ];
735- if (escape ) {
736- char next = lookahead (chars , i );
737- if ((curr == '\\' && (next == '\\' || next == until )) || (curr == until && next == until )) {
738- // should skip:
739- // 1) double \\ (backslash escaped with backslash)
740- // 2) \[until] ([until] char, escaped with backslash)
741- // 3) [until][until] ([until] char, escaped with [until])
742- i ++;
743- continue ;
744- }
745- }
746-
747- if (curr == until ) {
748- return i ;
749- }
750- }
751- return chars .length ;
752- }
753-
754- private static char lookahead (char [] chars , int pos ) {
755- pos = pos + 1 ;
756- if (pos >= chars .length ) {
757- return '\0' ;
758- }
759- return chars [pos ];
760- }
761-
762696}
0 commit comments