{"record":{"id":"855aabf67bc812d9","repo":"hibernate/hibernate-orm","slug":"can-t-emulate-filter-clause-for-inverse-distributi","errorCode":null,"errorMessage":"Can't emulate filter clause for inverse distribution function [%s]","messagePattern":"Can't emulate filter clause for inverse distribution function \\[(.+?)\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/dialect/function/HypotheticalSetFunction.java","lineNumber":68,"sourceCode":"\tpublic void render(\n\t\t\tSqlAppender sqlAppender,\n\t\t\tList<? extends SqlAstNode> sqlAstArguments,\n\t\t\tPredicate filter,\n\t\t\tReturnableType<?> returnType,\n\t\t\tSqlAstTranslator<?> walker) {\n\t\trender( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), returnType, walker );\n\t}\n\n\t@Override\n\tpublic void render(\n\t\t\tSqlAppender sqlAppender,\n\t\t\tList<? extends SqlAstNode> sqlAstArguments,\n\t\t\tPredicate filter,\n\t\t\tList<SortSpecification> withinGroup,\n\t\t\tReturnableType<?> returnType,\n\t\t\tSqlAstTranslator<?> translator) {\n\t\tif ( filter != null && !filterClauseSupported( translator ) ) {\n\t\t\tthrow new IllegalArgumentException( \"Can't emulate filter clause for inverse distribution function [\" + getName() + \"]\" );\n\t\t}\n\t\tsqlAppender.appendSql( getName() );\n\t\tsqlAppender.appendSql( '(' );\n\t\tif ( !sqlAstArguments.isEmpty() ) {\n\t\t\tsqlAstArguments.get( 0 ).accept( translator );\n\t\t\tfor ( int i = 1; i < sqlAstArguments.size(); i++ ) {\n\t\t\t\tsqlAppender.append( ',' );\n\t\t\t\tsqlAstArguments.get( i ).accept( translator );\n\t\t\t}\n\t\t}\n\t\tsqlAppender.appendSql( ')' );\n\t\tif ( withinGroup != null && !withinGroup.isEmpty() ) {\n\t\t\ttranslator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );\n\t\t\tsqlAppender.appendSql( \" within group (order by \" );\n\t\t\twithinGroup.get( 0 ).accept( translator );\n\t\t\tfor ( int i = 1; i < withinGroup.size(); i++ ) {\n\t\t\t\tsqlAppender.appendSql( ',' );\n\t\t\t\twithinGroup.get( i ).accept( translator );","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/dialect/function/HypotheticalSetFunction.java#L50-L86","documentation":"HypotheticalSetFunction renders ordered-set aggregates (percentile_cont, percentile_disc and friends). The SQL FILTER clause on aggregates cannot always be translated: when a filter predicate is present and the target dialect's translator does not support the FILTER clause, this renderer has no emulation for hypothetical set functions and throws during SQL rendering.","triggerScenarios":"HQL: percentile_cont(0.5) within group (order by x) filter (where e.type = 'A') executed on a dialect that reports no FILTER support (typical MySQL/MariaDB bases without native FILTER).","commonSituations":"Porting analytics HQL from PostgreSQL to MySQL-family databases; using HQL filter clauses generated by query DSLs; upgrading a dialect where FILTER emulation was previously absent but tolerated.","solutions":["Move the FILTER predicate into the WHERE clause of the subquery feeding the aggregate","Select the filtered rows in a derived table and apply the ordered-set aggregate on top of it","Drop FILTER when the semantics allow folding it into the main WHERE clause","Run the query as native SQL, or target a dialect with native FILTER support"],"exampleFix":"// before\nselect percentile_cont(0.5) within group (order by s.amount) filter (where s.status = 'OK') from Sale s\n\n// after\nselect percentile_cont(0.5) within group (order by t.amount) from (\n  select s.amount as amount from Sale s where s.status = 'OK'\n) t","handlingStrategy":"fallback","validationCode":"// Only use FILTER on ordered-set aggregates for translators that support the clause\nboolean filterSupported(SessionFactory sf) {\n    String dialect = sf.getJdbcServices().getDialect().getClass().getSimpleName();\n    return dialect.contains(\"PostgreSQL\") || dialect.contains(\"H2\"); // extend per your verified matrix\n}","typeGuard":null,"tryCatchPattern":"try {\n    return em.createQuery(hqlWithFilter, Double.class).getResultList();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"emulate filter clause\")) {\n        // predicate moved from FILTER into the feeding subquery's WHERE\n        return em.createQuery(hqlWithWhere, Double.class).getResultList();\n    }\n    throw e;\n}","preventionTips":["Prefer WHERE over FILTER in HQL meant to be portable","Maintain a per-dialect capability matrix in integration tests for ordered-set aggregates","Run analytics HQL against every target dialect in CI"],"tags":["hibernate","hql","filter-clause","ordered-set-aggregate","dialect-limitation"],"backgroundTag":"aggregate-filter-clause-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}