@@ -212,9 +212,9 @@ ClientSideStatement getClientSideStatement() {
212212 }
213213 }
214214
215- private final Set <String > ddlStatements = ImmutableSet .of ("CREATE" , "DROP" , "ALTER" );
216- private final Set <String > selectStatements = ImmutableSet .of ("SELECT" , "WITH" );
217- private final Set <String > dmlStatements = ImmutableSet .of ("INSERT" , "UPDATE" , "DELETE" );
215+ private static final Set <String > ddlStatements = ImmutableSet .of ("CREATE" , "DROP" , "ALTER" );
216+ private static final Set <String > selectStatements = ImmutableSet .of ("SELECT" , "WITH" );
217+ private static final Set <String > dmlStatements = ImmutableSet .of ("INSERT" , "UPDATE" , "DELETE" );
218218 private final Set <ClientSideStatementImpl > statements ;
219219
220220 /** Private constructor for singleton instance. */
@@ -445,19 +445,31 @@ public static String removeCommentsAndTrim(String sql) {
445445
446446 /** Removes any statement hints at the beginning of the statement. */
447447 static String removeStatementHint (String sql ) {
448- // Valid statement hints at the beginning of a SQL statement can only contain a fixed set of
448+ // Valid statement hints at the beginning of a query statement can only contain a fixed set of
449449 // possible values. Although it is possible to add a @{FORCE_INDEX=...} as a statement hint, the
450450 // only allowed value is _BASE_TABLE. This means that we can safely assume that the statement
451- // hint will not contain any special characters, for example a closing curly brace, and
452- // that we can keep the check simple by just searching for the first occurrence of a closing
453- // curly brace at the end of the statement hint.
451+ // hint will not contain any special characters, for example a closing curly brace or one of the
452+ // keywords SELECT, UPDATE, DELETE, WITH, and that we can keep the check simple by just
453+ // searching for the first occurrence of a keyword that should be preceded by a closing curly
454+ // brace at the end of the statement hint.
454455 int startStatementHintIndex = sql .indexOf ('{' );
455- int endStatementHintIndex = sql .indexOf ('}' );
456- if (startStatementHintIndex == -1 || startStatementHintIndex > endStatementHintIndex ) {
457- // Looks like an invalid statement hint. Just ignore at this point and let the caller handle
458- // the invalid query.
459- return sql ;
456+ // Statement hints are only allowed for queries.
457+ int startQueryIndex = -1 ;
458+ String upperCaseSql = sql .toUpperCase ();
459+ for (String keyword : selectStatements ) {
460+ startQueryIndex = upperCaseSql .indexOf (keyword );
461+ if (startQueryIndex > -1 ) break ;
460462 }
461- return removeCommentsAndTrim (sql .substring (endStatementHintIndex + 1 ));
463+ if (startQueryIndex > -1 ) {
464+ int endStatementHintIndex = sql .substring (0 , startQueryIndex ).lastIndexOf ('}' );
465+ if (startStatementHintIndex == -1 || startStatementHintIndex > endStatementHintIndex ) {
466+ // Looks like an invalid statement hint. Just ignore at this point and let the caller handle
467+ // the invalid query.
468+ return sql ;
469+ }
470+ return removeCommentsAndTrim (sql .substring (endStatementHintIndex + 1 ));
471+ }
472+ // Seems invalid, just return the original statement.
473+ return sql ;
462474 }
463475}
0 commit comments