hibernate/hibernate-orm · error · IllegalArgumentException

Can't emulate [%s] in clause %s. Only the SELECT clause is s

Error message

Can't emulate [%s] in clause %s. Only the SELECT clause is supported

What it means

InverseDistributionWindowEmulation inlines an inverse distribution function (percentile_cont/disc) as a scalar subquery on dialects without native support. The emulation can only be placed in the SELECT clause or an OVER window; any other current clause (WHERE, GROUP BY, HAVING, ORDER BY) throws IllegalArgumentException at SQM-to-SQL conversion.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/InverseDistributionWindowEmulation.java:66

			SqmOrderByClause withinGroupClause,
			ReturnableType<T> impliedResultType,
			QueryEngine queryEngine) {
		return new SelfRenderingInverseDistributionFunction<>(
				arguments,
				filter,
				withinGroupClause,
				impliedResultType,
				queryEngine
		) {

			@Override
			public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
				final Clause currentClause = walker.getCurrentClauseStack().getCurrent();
				if ( currentClause == Clause.OVER ) {
					return super.convertToSqlAst( walker );
				}
				else if ( currentClause != Clause.SELECT ) {
					throw new IllegalArgumentException( "Can't emulate [" + getName() + "] in clause " + currentClause + ". Only the SELECT clause is supported" );
				}
				final ReturnableType<?> resultType = resolveResultType( walker );

				final List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
				final ArgumentsValidator argumentsValidator = getArgumentsValidator();
				if ( argumentsValidator != null ) {
					argumentsValidator.validateSqlTypes( arguments, getFunctionName() );
				}
				final List<SortSpecification> withinGroup;
				if ( this.getWithinGroup() == null ) {
					withinGroup = Collections.emptyList();
				}
				else {
					walker.getCurrentClauseStack().push( Clause.ORDER );
					try {
						final List<SqmSortSpecification> sortSpecifications = this.getWithinGroup().getSortSpecifications();
						withinGroup = new ArrayList<>( sortSpecifications.size() );
						for ( SqmSortSpecification sortSpecification : sortSpecifications ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Compute the function in an inner SELECT with an alias and reference the alias in the outer clause
  2. Restrict the function to the SELECT list
  3. Use native SQL or a dialect with native ordered-set aggregate support

Example fix

// before
select e.dept, percentile_disc(0.5) within group (order by e.salary) from Emp e group by e.dept order by percentile_disc(0.5) within group (order by e.salary)

// after
select d.dept, d.p50 from (
  select e.dept as dept, percentile_disc(0.5) within group (order by e.salary) as p50 from Emp e group by e.dept
) d order by d.p50
Defensive patterns

Strategy: fallback

Validate before calling

// Reject percentile_ references outside the SELECT list before touching the database
static boolean selectListOnly(String hql) {
    String lower = hql.toLowerCase(java.util.Locale.ROOT);
    for (String kw : new String[]{" order by ", " where ", " group by ", " having "}) {
        int kwAt = lower.indexOf(kw);
        if (kwAt >= 0 && lower.indexOf("percentile_", kwAt) >= 0) return false;
    }
    return true;
}

Try / catch

try {
    return em.createQuery(hql, Double.class).getResultList();
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("Only the SELECT clause is supported")) {
        return em.createQuery(wrapInSubquery(hql), Double.class).getResultList();
    }
    throw e;
}

Prevention

When it happens

Trigger: HQL that references percentile_cont(...)/percentile_disc(...) inside ORDER BY, WHERE, GROUP BY or HAVING on an emulation dialect (typical MySQL family).

Common situations: Sorting by a percentile; reusing a SELECT-list expression in ORDER BY during refactoring instead of an alias; portable queries run against multiple dialects where only some emulate.

Related errors


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