{"record":{"id":"f81bfc4b3414f591","repo":"hibernate/hibernate-orm","slug":"can-t-determine-sql-statement-type-for-statement","errorCode":null,"errorMessage":"Can't determine SQL statement type for statement: {sql}","messagePattern":"Can't determine SQL statement type for statement: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java","lineNumber":1394,"sourceCode":"\n\t@Override\n\tpublic String getCurrentSchemaCommand() {\n\t\treturn \"SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL\";\n\t}\n\n\t@Override\n\tpublic boolean supportsPartitionBy() {\n\t\treturn true;\n\t}\n\n\n\tprivate String statementType(String sql) {\n\t\tfinal Matcher matcher = SQL_STATEMENT_TYPE_PATTERN.matcher( sql );\n\t\tif ( matcher.matches() && matcher.groupCount() == 1 ) {\n\t\t\treturn matcher.group(1);\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException( \"Can't determine SQL statement type for statement: \" + sql );\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean supportsTupleDistinctCounts() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean supportsOffsetInSubquery() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean supportsFetchClause(FetchClauseType type) {\n\t\t// Until 12.2 there was a bug in the Oracle query rewriter causing ORA-00918\n\t\t// when the query contains duplicate implicit aliases in the select clause\n\t\treturn getVersion().isSameOrAfter( 12, 2 );","sourceCodeStart":1376,"sourceCodeEnd":1412,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java#L1376-L1412","documentation":"OracleLegacyDialect.getQueryHintString(sql, hints) injects Oracle optimizer hints right after the statement keyword, using statementType(sql) to locate that keyword via SQL_STATEMENT_TYPE_PATTERN ('^(?:/*.**/)?\\s*(select|insert|update|delete)\\s+...'). If the SQL does not start (after an optional /* */ comment) with select/insert/update/delete followed by whitespace, the regex match fails and IllegalArgumentException is thrown while the hint is being applied.","triggerScenarios":"Setting a query hint (QueryHints.HINT_HINT / hibernate query hints) on a statement that renders as a CTE ('with ... select ...'), begins with '--' line comments, or is a merge/call/DDL statement, on OracleLegacyDialect.","commonSituations":"Applying Oracle optimizer hints (FIRST_ROWS, PARALLEL, GATHER_PLAN_STATISTICS) to HQL that Hibernate renders as 'with ...' because of CTE-generating constructs; hinted native queries with leading line comments.","solutions":["Only set HINT_HINT on queries whose generated SQL starts with select/insert/update/delete; inline the hint manually for CTE statements via a native query","Restructure the HQL so it does not render with a leading WITH clause","Strip leading '--' comments or other prefixes before applying hints","Upgrade Hibernate — later Oracle dialects place hints more robustly"],"exampleFix":"// before\n// generated SQL: with cte as (...) select * from cte ...\nquery.setHint( QueryHints.HINT_HINT, \"FIRST_ROWS(10)\" ); // -> statementType() throws\n\n// after: apply hints only to classifiable statements\nif ( sql.matches( \"(?is)^(?:/\\\\*.*?\\\\*/)?\\\\s*(select|insert|update|delete)\\\\s+.*\" ) ) {\n    query.setHint( QueryHints.HINT_HINT, \"FIRST_ROWS(10)\" );\n}","handlingStrategy":"validation","validationCode":"private static final Pattern ORACLE_STMT_TYPE = Pattern.compile(\n        \"^(?:/\\\\*.*?\\\\*/)?\\\\s*(select|insert|update|delete)\\\\s+.*?\", Pattern.CASE_INSENSITIVE );\n\nboolean canApplyOracleHint(String sql) {\n    return ORACLE_STMT_TYPE.matcher( sql ).matches();\n}\n\nif ( canApplyOracleHint( sql ) ) {\n    query.setHint( QueryHints.HINT_HINT, \"FIRST_ROWS(10)\" );\n}","typeGuard":null,"tryCatchPattern":"try {\n    return query.list();\n}\ncatch ( IllegalArgumentException e ) {\n    if ( e.getMessage() != null && e.getMessage().startsWith( \"Can't determine SQL statement type\" ) ) {\n        query.setHints( Collections.emptyMap() ); // retry without the hint\n        return query.list();\n    }\n    throw e;\n}","preventionTips":["Only set HINT_HINT on queries whose generated SQL starts with select/insert/update/delete","Avoid leading '--' comments in hinted native queries","For CTE-style SQL, inline optimizer hints directly in a native query"],"tags":["oracle","query-hints","sql-translation","regex"],"backgroundTag":"query-hint-application-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}