Skip to content

Commit 819c623

Browse files
committed
Implement support for ordered set-aggregate functions like listagg, percentile_disc, rank etc.
1 parent 0ad5796 commit 819c623

File tree

54 files changed

+1984
-47
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1984
-47
lines changed

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
321321
integerType
322322
);
323323
}
324+
325+
CommonFunctionFactory.listagg_list( "varchar", queryEngine );
324326
}
325327

326328
@Override

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,11 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
299299
.setInvariantType( stringType )
300300
.register();
301301

302+
// No idea since when this is supported
303+
CommonFunctionFactory.listagg( queryEngine );
304+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
305+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
306+
302307
}
303308

304309
@Override

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
316316
.setParameterTypes(NUMERIC)
317317
.register();
318318
}
319+
CommonFunctionFactory.listagg_groupConcat( queryEngine );
319320
}
320321

321322
@Override

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
import org.hibernate.dialect.RowLockStrategy;
1616
import org.hibernate.dialect.SybaseDialect;
1717
import org.hibernate.dialect.TimeZoneSupport;
18+
import org.hibernate.dialect.function.CommonFunctionFactory;
1819
import org.hibernate.dialect.identity.IdentityColumnSupport;
1920
import org.hibernate.dialect.pagination.LimitHandler;
2021
import org.hibernate.dialect.pagination.TopLimitHandler;
2122
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
2223
import org.hibernate.engine.spi.SessionFactoryImplementor;
24+
import org.hibernate.query.spi.QueryEngine;
2325
import org.hibernate.sql.ForUpdateFragment;
2426
import org.hibernate.sql.ast.SqlAstTranslator;
2527
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@@ -75,6 +77,12 @@ protected String columnType(int jdbcTypeCode) {
7577
}
7678
}
7779

80+
@Override
81+
public void initializeFunctionRegistry(QueryEngine queryEngine) {
82+
super.initializeFunctionRegistry( queryEngine );
83+
CommonFunctionFactory.listagg_list( "varchar", queryEngine );
84+
}
85+
7886
@Override
7987
public int getMaxVarcharLength() {
8088
return 32_767;

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataDialect.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
284284
CommonFunctionFactory.varPopSamp( queryEngine );
285285
}
286286

287+
// No idea since when this is supported
288+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
289+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
287290
}
288291

289292
/**

hibernate-core/src/main/antlr/org/hibernate/grammars/hql/HqlLexer.g4

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ BOTH : [bB] [oO] [tT] [hH];
152152
CASE : [cC] [aA] [sS] [eE];
153153
CAST : [cC] [aA] [sS] [tT];
154154
COLLATE : [cC] [oO] [lL] [lL] [aA] [tT] [eE];
155+
COUNT : [cC] [oO] [uU] [nN] [tT];
155156
CROSS : [cC] [rR] [oO] [sS] [sS];
156157
CUBE : [cC] [uU] [bB] [eE];
157158
CURRENT : [cC] [uU] [rR] [rR] [eE] [nN] [tT];
@@ -171,6 +172,7 @@ ELSE : [eE] [lL] [sS] [eE];
171172
EMPTY : [eE] [mM] [pP] [tT] [yY];
172173
END : [eE] [nN] [dD];
173174
ENTRY : [eE] [nN] [tT] [rR] [yY];
175+
ERROR : [eE] [rR] [rR] [oO] [rR];
174176
ESCAPE : [eE] [sS] [cC] [aA] [pP] [eE];
175177
EVERY : [eE] [vV] [eE] [rR] [yY];
176178
EXCEPT : [eE] [xX] [cC] [eE] [pP] [tT];
@@ -205,6 +207,7 @@ LIKE : [lL] [iI] [kK] [eE];
205207
ILIKE : [iI] [lL] [iI] [kK] [eE];
206208
LIMIT : [lL] [iI] [mM] [iI] [tT];
207209
LIST : [lL] [iI] [sS] [tT];
210+
LISTAGG : [lL] [iI] [sS] [tT] [aA] [gG] [gG];
208211
LOCAL : [lL] [oO] [cC] [aA] [lL];
209212
LOCAL_DATE : [lL] [oO] [cC] [aA] [lL] '_' [dD] [aA] [tT] [eE];
210213
LOCAL_DATETIME : [lL] [oO] [cC] [aA] [lL] '_' [dD] [aA] [tT] [eE] [tT] [iI] [mM] [eE];
@@ -235,6 +238,7 @@ ONLY : [oO] [nN] [lL] [yY];
235238
OR : [oO] [rR];
236239
ORDER : [oO] [rR] [dD] [eE] [rR];
237240
OUTER : [oO] [uU] [tT] [eE] [rR];
241+
OVERFLOW : [oO] [vV] [eE] [rR] [fF] [lL] [oO] [wW];
238242
OVERLAY : [oO] [vV] [eE] [rR] [lL] [aA] [yY];
239243
PAD : [pP] [aA] [dD];
240244
PERCENT : [pP] [eE] [rR] [cC] [eE] [nN] [tT];
@@ -261,6 +265,7 @@ TIMEZONE_MINUTE : [tT] [iI] [mM] [eE] [zZ] [oO] [nN] [eE] '_' [mM] [iI] [nN] [u
261265
TRAILING : [tT] [rR] [aA] [iI] [lL] [iI] [nN] [gG];
262266
TREAT : [tT] [rR] [eE] [aA] [tT];
263267
TRIM : [tT] [rR] [iI] [mM];
268+
TRUNCATE : [tT] [rR] [uU] [nN] [cC] [aA] [tT] [eE];
264269
TYPE : [tT] [yY] [pP] [eE];
265270
UNION : [uU] [nN] [iI] [oO] [nN];
266271
UPDATE : [uU] [pP] [dD] [aA] [tT] [eE];
@@ -270,6 +275,8 @@ WEEK : [wW] [eE] [eE] [kK];
270275
WHEN : [wW] [hH] [eE] [nN];
271276
WHERE : [wW] [hH] [eE] [rR] [eE];
272277
WITH : [wW] [iI] [tT] [hH];
278+
WITHIN : [wW] [iI] [tT] [hH] [iI] [nN];
279+
WITHOUT : [wW] [iI] [tT] [hH] [oO] [uU] [tT];
273280
YEAR : [yY] [eE] [aA] [rR];
274281
275282
// case-insensitive true, false and null recognition (split vote :)

hibernate-core/src/main/antlr/org/hibernate/grammars/hql/HqlParser.g4

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,7 @@ jpaNonstandardFunctionName
975975
* The function name, followed by a parenthesized list of comma-separated expressions
976976
*/
977977
genericFunction
978-
: genericFunctionName LEFT_PAREN (genericFunctionArguments | ASTERISK)? RIGHT_PAREN filterClause?
978+
: genericFunctionName LEFT_PAREN (genericFunctionArguments | ASTERISK)? RIGHT_PAREN withinGroupClause? filterClause?
979979
;
980980

981981
/**
@@ -1045,6 +1045,7 @@ collectionFunctionMisuse
10451045
aggregateFunction
10461046
: everyFunction
10471047
| anyFunction
1048+
| listaggFunction
10481049
;
10491050

10501051
/**
@@ -1065,6 +1066,27 @@ anyFunction
10651066
| (ANY|SOME) (ELEMENTS|INDICES) LEFT_PAREN simplePath RIGHT_PAREN
10661067
;
10671068

1069+
/**
1070+
* The `listagg()` ordered set-aggregate function
1071+
*/
1072+
listaggFunction
1073+
: LISTAGG LEFT_PAREN DISTINCT? expressionOrPredicate COMMA expressionOrPredicate onOverflowClause? RIGHT_PAREN withinGroupClause? filterClause?
1074+
;
1075+
1076+
/**
1077+
* A `on overflow` clause: what to do when the text data type used for `listagg` overflows
1078+
*/
1079+
onOverflowClause
1080+
: ON OVERFLOW (ERROR | (TRUNCATE expression? (WITH|WITHOUT) COUNT))
1081+
;
1082+
1083+
/**
1084+
* A 'within group' clause: defines the order in which the ordered set-aggregate function should work
1085+
*/
1086+
withinGroupClause
1087+
: WITHIN GROUP LEFT_PAREN orderByClause RIGHT_PAREN
1088+
;
1089+
10681090
/**
10691091
* A 'filter' clause: a restriction applied to an aggregate function
10701092
*/
@@ -1387,6 +1409,7 @@ identifier
13871409
| CASE
13881410
| CAST
13891411
| COLLATE
1412+
| COUNT
13901413
| CROSS
13911414
| CUBE
13921415
| CURRENT
@@ -1406,6 +1429,7 @@ identifier
14061429
| EMPTY
14071430
| END
14081431
| ENTRY
1432+
| ERROR
14091433
| ESCAPE
14101434
| EVERY
14111435
| EXCEPT
@@ -1441,6 +1465,7 @@ identifier
14411465
| LIKE
14421466
| LIMIT
14431467
| LIST
1468+
| LISTAGG
14441469
| LOCAL
14451470
| LOCAL_DATE
14461471
| LOCAL_DATETIME
@@ -1472,6 +1497,7 @@ identifier
14721497
| OR
14731498
| ORDER
14741499
| OUTER
1500+
| OVERFLOW
14751501
| OVERLAY
14761502
| PAD
14771503
| PERCENT
@@ -1498,6 +1524,7 @@ identifier
14981524
| TRAILING
14991525
| TREAT
15001526
| TRIM
1527+
| TRUNCATE
15011528
| TYPE
15021529
| UNION
15031530
| UPDATE
@@ -1509,6 +1536,8 @@ identifier
15091536
| WHEN
15101537
| WHERE
15111538
| WITH
1539+
| WITHIN
1540+
| WITHOUT
15121541
| YEAR) {
15131542
logUseOfReservedWordAsIdentifier( getCurrentToken() );
15141543
}

hibernate-core/src/main/java/org/hibernate/dialect/AbstractHANADialect.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
307307
CommonFunctionFactory.currentUtcdatetimetimestamp( queryEngine );
308308
CommonFunctionFactory.everyAny_sumCaseCase( queryEngine );
309309
CommonFunctionFactory.bitLength_pattern( queryEngine, "length(to_binary(?1))*8" );
310+
311+
CommonFunctionFactory.listagg_stringAgg( "varchar", queryEngine );
312+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
313+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
310314
}
311315

312316
@Override

hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
234234
.setArgumentsValidator( CommonFunctionFactory.formatValidator() )
235235
.setArgumentListSignature("(TEMPORAL datetime as STRING pattern)")
236236
.register();
237+
CommonFunctionFactory.listagg_stringAgg( "string", queryEngine );
238+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
239+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
237240
}
238241

239242
@Override

hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,14 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
261261
.setParameterTypes(FunctionParameterType.STRING, FunctionParameterType.STRING)
262262
.setArgumentListSignature("(STRING string, STRING pattern)")
263263
.register();
264+
265+
if ( getDB2Version().isSameOrAfter( 9, 5 ) ) {
266+
CommonFunctionFactory.listagg( queryEngine );
267+
if ( getDB2Version().isSameOrAfter( 11, 1 ) ) {
268+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
269+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
270+
}
271+
}
264272
}
265273

266274
@Override

hibernate-core/src/main/java/org/hibernate/dialect/DB2iDialect.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
package org.hibernate.dialect;
88

9+
import org.hibernate.dialect.function.CommonFunctionFactory;
910
import org.hibernate.dialect.identity.DB2390IdentityColumnSupport;
1011
import org.hibernate.dialect.identity.DB2IdentityColumnSupport;
1112
import org.hibernate.dialect.identity.IdentityColumnSupport;
@@ -19,6 +20,7 @@
1920
import org.hibernate.dialect.unique.UniqueDelegate;
2021
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
2122
import org.hibernate.engine.spi.SessionFactoryImplementor;
23+
import org.hibernate.query.spi.QueryEngine;
2224
import org.hibernate.sql.ast.SqlAstTranslator;
2325
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
2426
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
@@ -40,6 +42,16 @@ public DB2iDialect(DialectResolutionInfo info) {
4042
registerKeywords( info );
4143
}
4244

45+
@Override
46+
public void initializeFunctionRegistry(QueryEngine queryEngine) {
47+
super.initializeFunctionRegistry( queryEngine );
48+
if ( getVersion().isSameOrAfter( 7, 2 ) ) {
49+
CommonFunctionFactory.listagg( queryEngine );
50+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
51+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
52+
}
53+
}
54+
4355
public DB2iDialect() {
4456
this( DatabaseVersion.make(7) );
4557
}

hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import jakarta.persistence.TemporalType;
1111

12+
import org.hibernate.dialect.function.CommonFunctionFactory;
1213
import org.hibernate.dialect.identity.DB2390IdentityColumnSupport;
1314
import org.hibernate.dialect.identity.IdentityColumnSupport;
1415
import org.hibernate.dialect.pagination.FetchLimitHandler;
@@ -19,6 +20,7 @@
1920
import org.hibernate.dialect.sequence.SequenceSupport;
2021
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
2122
import org.hibernate.engine.spi.SessionFactoryImplementor;
23+
import org.hibernate.query.spi.QueryEngine;
2224
import org.hibernate.query.sqm.IntervalType;
2325
import org.hibernate.query.sqm.TemporalUnit;
2426
import org.hibernate.sql.ast.SqlAstTranslator;
@@ -51,6 +53,16 @@ public DB2zDialect(DatabaseVersion version) {
5153
super(version);
5254
}
5355

56+
@Override
57+
public void initializeFunctionRegistry(QueryEngine queryEngine) {
58+
super.initializeFunctionRegistry( queryEngine );
59+
if ( getVersion().isSameOrAfter( 12 ) ) {
60+
CommonFunctionFactory.listagg( queryEngine );
61+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
62+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
63+
}
64+
}
65+
5466
@Override
5567
protected String columnType(int jdbcTypeCode) {
5668
// See https://www.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/wnew/src/tpc/db2z_10_timestamptimezone.html

hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,16 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
278278
CommonFunctionFactory.format_formatdatetime( queryEngine );
279279
}
280280
CommonFunctionFactory.rownum( queryEngine );
281+
if ( getVersion().isSameOrAfter( 1, 4, 200 ) ) {
282+
CommonFunctionFactory.listagg( queryEngine );
283+
if ( getVersion().isSameOrAfter( 2 ) ) {
284+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
285+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
286+
}
287+
}
288+
else {
289+
CommonFunctionFactory.listagg_groupConcat( queryEngine );
290+
}
281291
}
282292

283293
@Override

hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
224224
if ( getVersion().isSameOrAfter( 2, 2 ) ) {
225225
CommonFunctionFactory.rownum( queryEngine );
226226
}
227+
CommonFunctionFactory.listagg_groupConcat( queryEngine );
227228
}
228229

229230
@Override

hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
446446
}
447447

448448
queryEngine.getSqmFunctionRegistry().register( "field", new FieldFunction( queryEngine.getTypeConfiguration() ) );
449+
CommonFunctionFactory.listagg_groupConcat( queryEngine );
449450
}
450451

451452
@Override

hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.hibernate.boot.model.TypeContributions;
2323
import org.hibernate.cfg.Environment;
2424
import org.hibernate.dialect.function.CommonFunctionFactory;
25+
import org.hibernate.dialect.function.ModeStatsModeEmulation;
2526
import org.hibernate.dialect.function.NvlCoalesceEmulation;
2627
import org.hibernate.dialect.identity.IdentityColumnSupport;
2728
import org.hibernate.dialect.identity.Oracle12cIdentityColumnSupport;
@@ -188,6 +189,14 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
188189
"instr(?2,?1,?3)",
189190
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER
190191
).setArgumentListSignature("(pattern, string[, start])");
192+
CommonFunctionFactory.listagg( queryEngine );
193+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
194+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
195+
// Oracle has a regular aggregate function named stats_mode
196+
queryEngine.getSqmFunctionRegistry().register(
197+
"mode",
198+
new ModeStatsModeEmulation( queryEngine.getTypeConfiguration() )
199+
);
191200
}
192201

193202
@Override

hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,12 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
448448
CommonFunctionFactory.soundex( queryEngine ); //was introduced in Postgres 9 apparently
449449

450450
CommonFunctionFactory.locate_positionSubstring( queryEngine );
451+
CommonFunctionFactory.listagg_stringAgg( "varchar", queryEngine );
451452

452453
if ( getVersion().isSameOrAfter( 9, 4 ) ) {
453454
CommonFunctionFactory.makeDateTimeTimestamp( queryEngine );
455+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
456+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
454457
}
455458
}
456459

hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,11 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
265265
.setParameterTypes(INTEGER)
266266
.register();
267267
}
268+
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
269+
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
270+
if ( getVersion().isSameOrAfter( 14 ) ) {
271+
CommonFunctionFactory.listagg_stringAggWithinGroup( "varchar(max)", queryEngine );
272+
}
268273
}
269274

270275
@Override

0 commit comments

Comments
 (0)