hibernate/hibernate-orm · error · IllegalArgumentException

Can't determine SQL statement type for statement: {sql}

Error message

Can't determine SQL statement type for statement: {sql}

What it means

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.

Source

Thrown at hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java:1394

	@Override
	public String getCurrentSchemaCommand() {
		return "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL";
	}

	@Override
	public boolean supportsPartitionBy() {
		return true;
	}


	private String statementType(String sql) {
		final Matcher matcher = SQL_STATEMENT_TYPE_PATTERN.matcher( sql );
		if ( matcher.matches() && matcher.groupCount() == 1 ) {
			return matcher.group(1);
		}
		else {
			throw new IllegalArgumentException( "Can't determine SQL statement type for statement: " + sql );
		}
	}

	@Override
	public boolean supportsTupleDistinctCounts() {
		return false;
	}

	@Override
	public boolean supportsOffsetInSubquery() {
		return true;
	}

	@Override
	public boolean supportsFetchClause(FetchClauseType type) {
		// Until 12.2 there was a bug in the Oracle query rewriter causing ORA-00918
		// when the query contains duplicate implicit aliases in the select clause
		return getVersion().isSameOrAfter( 12, 2 );

View on GitHub (pinned to fad1729dce)

Solutions

  1. 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
  2. Restructure the HQL so it does not render with a leading WITH clause
  3. Strip leading '--' comments or other prefixes before applying hints
  4. Upgrade Hibernate — later Oracle dialects place hints more robustly

Example fix

// before
// generated SQL: with cte as (...) select * from cte ...
query.setHint( QueryHints.HINT_HINT, "FIRST_ROWS(10)" ); // -> statementType() throws

// after: apply hints only to classifiable statements
if ( sql.matches( "(?is)^(?:/\\*.*?\\*/)?\\s*(select|insert|update|delete)\\s+.*" ) ) {
    query.setHint( QueryHints.HINT_HINT, "FIRST_ROWS(10)" );
}
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern ORACLE_STMT_TYPE = Pattern.compile(
        "^(?:/\\*.*?\\*/)?\\s*(select|insert|update|delete)\\s+.*?", Pattern.CASE_INSENSITIVE );

boolean canApplyOracleHint(String sql) {
    return ORACLE_STMT_TYPE.matcher( sql ).matches();
}

if ( canApplyOracleHint( sql ) ) {
    query.setHint( QueryHints.HINT_HINT, "FIRST_ROWS(10)" );
}

Try / catch

try {
    return query.list();
}
catch ( IllegalArgumentException e ) {
    if ( e.getMessage() != null && e.getMessage().startsWith( "Can't determine SQL statement type" ) ) {
        query.setHints( Collections.emptyMap() ); // retry without the hint
        return query.list();
    }
    throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/f81bfc4b3414f591. Report an issue: GitHub.