@@ -157,6 +157,34 @@ public static Object[][] testPreparedStatementInsertSQLDP() {
157157 };
158158 }
159159
160+ @ Test (dataProvider = "testValuesListPositionsDP" )
161+ public void testValuesListPositions (String sql , boolean positionsExpected ) {
162+ ParsedPreparedStatement parsed = parser .parsePreparedStatement (sql );
163+ assertTrue (parsed .isInsert (), "Should be of insert type" );
164+
165+ int start = parsed .getAssignValuesListStartPosition ();
166+ int stop = parsed .getAssignValuesListStopPosition ();
167+ if (parsed .getAssignValuesGroups () == 1 && start > -1 && stop > -1 ) {
168+ assertTrue (stop > start , "Values list should stop after it starts, but got [" + start + ", " + stop + "]" );
169+ assertTrue (stop < sql .length (), "Values list should stop within the statement, but got " + stop
170+ + " for a statement of " + sql .length () + " characters" );
171+ assertEquals (sql .charAt (start ), '(' , "Values list should start with an opening parenthesis" );
172+ assertEquals (sql .charAt (stop ), ')' , "Values list should end with a closing parenthesis" );
173+
174+ int [] paramPositions = parsed .getParamPositions ();
175+ for (int i = 0 ; i < parsed .getArgCount (); i ++) {
176+ assertTrue (paramPositions [i ] > start && paramPositions [i ] < stop , "Parameter " + (i + 1 )
177+ + " at position " + paramPositions [i ] + " should be inside the values list '"
178+ + sql .substring (start , stop + 1 ) + "'" );
179+ }
180+ }
181+
182+ if (javaCcBackend ) {
183+ assertEquals (start > -1 && stop > -1 , positionsExpected ,
184+ "Values list positions should " + (positionsExpected ? "" : "not " ) + "be reported" );
185+ }
186+ }
187+
160188 @ Test (dataProvider = "testInsertWithUnsupportedValuesListDP" )
161189 public void testInsertWithUnsupportedValuesList (String sql ) {
162190 ParsedPreparedStatement parsed = parser .parsePreparedStatement (sql );
@@ -241,6 +269,31 @@ public void testValuesListOfUnsupportedSyntax(String sql, boolean parseable, int
241269 }
242270 }
243271
272+ @ DataProvider
273+ public static Object [][] testValuesListPositionsDP () {
274+ return new Object [][] {
275+ { "INSERT INTO t (a, b) VALUES (1, ?)" , true },
276+ { "INSERT INTO t (a, b) VALUES (1, ?);" , true },
277+ { "INSERT INTO t (a, b) VALUES ('a)b', ?)" , true },
278+ { "INSERT INTO t (a, b) VALUES (1 /* ) */, ?)" , true },
279+ { "INSERT INTO t (a, b) VALUES (1 -- )\n , ?)" , true },
280+ { "INSERT INTO t (a, b) VALUES (1 // )\n , ?)" , true },
281+ { "INSERT INTO t (a, b) VALUES (1 # )\n , ?)" , true },
282+ { "INSERT INTO t (a, b) VALUES (1 #! )\n , ?)" , true },
283+ { "INSERT INTO t (a, b) VALUES (1 --\n , ?)" , true },
284+ { "INSERT INTO t (a, b) VALUES (1 /* ( */, ?)" , true },
285+ { "INSERT INTO t (a, b) VALUES (1 /* ? */, ?)" , true },
286+ { "INSERT INTO t (a, b) VALUES (1, ? /* ) */)" , true },
287+ { "INSERT INTO t (a, b) VALUES (toDate({d '2024-01-01'}), ?)" , true },
288+ { "INSERT INTO t (a, b) VALUES (toDateTime({ts '2024-01-01 00:00:00'}) /* ) */, ?)" , false },
289+ { "INSERT INTO t (a, b) VALUES (toDateTime({ts '2024-01-01 00:00:00'}), ?)" , false },
290+ { "INSERT INTO t (a, b) VALUES (toTime({t '10:20:30'}), ?)" , false },
291+ { "INSERT INTO t (a, b) VALUES (toInt32({d:Int32}), ?)" , false },
292+ { "INSERT INTO t (a, b) VALUES (?, toDate({d '2024-01-01'}))" , false },
293+ { "INSERT INTO t (a, b) VALUES (?, toString({tt 'temp'}))" , false },
294+ };
295+ }
296+
244297 @ DataProvider
245298 public static Object [][] testValuesListOfUnsupportedSyntaxDP () {
246299 return new Object [][] {
0 commit comments