{"record":{"id":"46f5610be317f0b3","repo":"hibernate/hibernate-orm","slug":"can-t-emulate-s-in-clause-s-only-the-select-c-46f561","errorCode":null,"errorMessage":"Can't emulate [%s] in clause %s. Only the SELECT clause is supported","messagePattern":"Can't emulate \\[(.+?)\\] in clause (.+?)\\. Only the SELECT clause is supported","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/dialect/function/InverseDistributionWindowEmulation.java","lineNumber":66,"sourceCode":"\t\t\tSqmOrderByClause withinGroupClause,\n\t\t\tReturnableType<T> impliedResultType,\n\t\t\tQueryEngine queryEngine) {\n\t\treturn new SelfRenderingInverseDistributionFunction<>(\n\t\t\t\targuments,\n\t\t\t\tfilter,\n\t\t\t\twithinGroupClause,\n\t\t\t\timpliedResultType,\n\t\t\t\tqueryEngine\n\t\t) {\n\n\t\t\t@Override\n\t\t\tpublic Expression convertToSqlAst(SqmToSqlAstConverter walker) {\n\t\t\t\tfinal Clause currentClause = walker.getCurrentClauseStack().getCurrent();\n\t\t\t\tif ( currentClause == Clause.OVER ) {\n\t\t\t\t\treturn super.convertToSqlAst( walker );\n\t\t\t\t}\n\t\t\t\telse if ( currentClause != Clause.SELECT ) {\n\t\t\t\t\tthrow new IllegalArgumentException( \"Can't emulate [\" + getName() + \"] in clause \" + currentClause + \". Only the SELECT clause is supported\" );\n\t\t\t\t}\n\t\t\t\tfinal ReturnableType<?> resultType = resolveResultType( walker );\n\n\t\t\t\tfinal List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );\n\t\t\t\tfinal ArgumentsValidator argumentsValidator = getArgumentsValidator();\n\t\t\t\tif ( argumentsValidator != null ) {\n\t\t\t\t\targumentsValidator.validateSqlTypes( arguments, getFunctionName() );\n\t\t\t\t}\n\t\t\t\tfinal List<SortSpecification> withinGroup;\n\t\t\t\tif ( this.getWithinGroup() == null ) {\n\t\t\t\t\twithinGroup = Collections.emptyList();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\twalker.getCurrentClauseStack().push( Clause.ORDER );\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfinal List<SqmSortSpecification> sortSpecifications = this.getWithinGroup().getSortSpecifications();\n\t\t\t\t\t\twithinGroup = new ArrayList<>( sortSpecifications.size() );\n\t\t\t\t\t\tfor ( SqmSortSpecification sortSpecification : sortSpecifications ) {","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/dialect/function/InverseDistributionWindowEmulation.java#L48-L84","documentation":"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.","triggerScenarios":"HQL that references percentile_cont(...)/percentile_disc(...) inside ORDER BY, WHERE, GROUP BY or HAVING on an emulation dialect (typical MySQL family).","commonSituations":"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.","solutions":["Compute the function in an inner SELECT with an alias and reference the alias in the outer clause","Restrict the function to the SELECT list","Use native SQL or a dialect with native ordered-set aggregate support"],"exampleFix":"// before\nselect 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)\n\n// after\nselect d.dept, d.p50 from (\n  select e.dept as dept, percentile_disc(0.5) within group (order by e.salary) as p50 from Emp e group by e.dept\n) d order by d.p50","handlingStrategy":"fallback","validationCode":"// Reject percentile_ references outside the SELECT list before touching the database\nstatic boolean selectListOnly(String hql) {\n    String lower = hql.toLowerCase(java.util.Locale.ROOT);\n    for (String kw : new String[]{\" order by \", \" where \", \" group by \", \" having \"}) {\n        int kwAt = lower.indexOf(kw);\n        if (kwAt >= 0 && lower.indexOf(\"percentile_\", kwAt) >= 0) return false;\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n    return em.createQuery(hql, Double.class).getResultList();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Only the SELECT clause is supported\")) {\n        return em.createQuery(wrapInSubquery(hql), Double.class).getResultList();\n    }\n    throw e;\n}","preventionTips":["Reference computed percentiles by alias from an outer query","Keep emulated window/ordered-set functions out of WHERE/ORDER BY/GROUP BY/HAVING","Add CI runs on emulation dialects for percentile-based queries"],"tags":["hibernate","hql","window-function","inverse-distribution","query-clause"],"backgroundTag":"window-function-emulation-limit","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}