Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement support for ordered set-aggregate functions like listagg, percentile_disc, rank etc. #4758

Merged
merged 1 commit into from
Feb 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,8 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
integerType
);
}

CommonFunctionFactory.listagg_list( "varchar", queryEngine );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
.setInvariantType( stringType )
.register();

// No idea since when this is supported
CommonFunctionFactory.listagg( null, queryEngine );
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );

}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
.setParameterTypes(NUMERIC)
.register();
}
CommonFunctionFactory.listagg_groupConcat( queryEngine );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
import org.hibernate.dialect.RowLockStrategy;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.TopLimitHandler;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.ForUpdateFragment;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
Expand Down Expand Up @@ -75,6 +77,12 @@ protected String columnType(int jdbcTypeCode) {
}
}

@Override
public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry( queryEngine );
CommonFunctionFactory.listagg_list( "varchar", queryEngine );
}

@Override
public int getMaxVarcharLength() {
return 32_767;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
CommonFunctionFactory.varPopSamp( queryEngine );
}

// No idea since when this is supported
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ BOTH : [bB] [oO] [tT] [hH];
CASE : [cC] [aA] [sS] [eE];
CAST : [cC] [aA] [sS] [tT];
COLLATE : [cC] [oO] [lL] [lL] [aA] [tT] [eE];
COUNT : [cC] [oO] [uU] [nN] [tT];
CROSS : [cC] [rR] [oO] [sS] [sS];
CUBE : [cC] [uU] [bB] [eE];
CURRENT : [cC] [uU] [rR] [rR] [eE] [nN] [tT];
Expand All @@ -171,6 +172,7 @@ ELSE : [eE] [lL] [sS] [eE];
EMPTY : [eE] [mM] [pP] [tT] [yY];
END : [eE] [nN] [dD];
ENTRY : [eE] [nN] [tT] [rR] [yY];
ERROR : [eE] [rR] [rR] [oO] [rR];
ESCAPE : [eE] [sS] [cC] [aA] [pP] [eE];
EVERY : [eE] [vV] [eE] [rR] [yY];
EXCEPT : [eE] [xX] [cC] [eE] [pP] [tT];
Expand Down Expand Up @@ -205,6 +207,7 @@ LIKE : [lL] [iI] [kK] [eE];
ILIKE : [iI] [lL] [iI] [kK] [eE];
LIMIT : [lL] [iI] [mM] [iI] [tT];
LIST : [lL] [iI] [sS] [tT];
LISTAGG : [lL] [iI] [sS] [tT] [aA] [gG] [gG];
LOCAL : [lL] [oO] [cC] [aA] [lL];
LOCAL_DATE : [lL] [oO] [cC] [aA] [lL] '_' [dD] [aA] [tT] [eE];
LOCAL_DATETIME : [lL] [oO] [cC] [aA] [lL] '_' [dD] [aA] [tT] [eE] [tT] [iI] [mM] [eE];
Expand Down Expand Up @@ -235,6 +238,7 @@ ONLY : [oO] [nN] [lL] [yY];
OR : [oO] [rR];
ORDER : [oO] [rR] [dD] [eE] [rR];
OUTER : [oO] [uU] [tT] [eE] [rR];
OVERFLOW : [oO] [vV] [eE] [rR] [fF] [lL] [oO] [wW];
OVERLAY : [oO] [vV] [eE] [rR] [lL] [aA] [yY];
PAD : [pP] [aA] [dD];
PERCENT : [pP] [eE] [rR] [cC] [eE] [nN] [tT];
Expand All @@ -261,6 +265,7 @@ TIMEZONE_MINUTE : [tT] [iI] [mM] [eE] [zZ] [oO] [nN] [eE] '_' [mM] [iI] [nN] [u
TRAILING : [tT] [rR] [aA] [iI] [lL] [iI] [nN] [gG];
TREAT : [tT] [rR] [eE] [aA] [tT];
TRIM : [tT] [rR] [iI] [mM];
TRUNCATE : [tT] [rR] [uU] [nN] [cC] [aA] [tT] [eE];
TYPE : [tT] [yY] [pP] [eE];
UNION : [uU] [nN] [iI] [oO] [nN];
UPDATE : [uU] [pP] [dD] [aA] [tT] [eE];
Expand All @@ -270,6 +275,8 @@ WEEK : [wW] [eE] [eE] [kK];
WHEN : [wW] [hH] [eE] [nN];
WHERE : [wW] [hH] [eE] [rR] [eE];
WITH : [wW] [iI] [tT] [hH];
WITHIN : [wW] [iI] [tT] [hH] [iI] [nN];
WITHOUT : [wW] [iI] [tT] [hH] [oO] [uU] [tT];
YEAR : [yY] [eE] [aA] [rR];

// case-insensitive true, false and null recognition (split vote :)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ jpaNonstandardFunctionName
* The function name, followed by a parenthesized list of comma-separated expressions
*/
genericFunction
: genericFunctionName LEFT_PAREN (genericFunctionArguments | ASTERISK)? RIGHT_PAREN filterClause?
: genericFunctionName LEFT_PAREN (genericFunctionArguments | ASTERISK)? RIGHT_PAREN withinGroupClause? filterClause?
;

/**
Expand Down Expand Up @@ -1045,6 +1045,7 @@ collectionFunctionMisuse
aggregateFunction
: everyFunction
| anyFunction
| listaggFunction
;

/**
Expand All @@ -1065,6 +1066,27 @@ anyFunction
| (ANY|SOME) (ELEMENTS|INDICES) LEFT_PAREN simplePath RIGHT_PAREN
;

/**
* The `listagg()` ordered set-aggregate function
*/
listaggFunction
: LISTAGG LEFT_PAREN DISTINCT? expressionOrPredicate COMMA expressionOrPredicate onOverflowClause? RIGHT_PAREN withinGroupClause? filterClause?
;

/**
* A `on overflow` clause: what to do when the text data type used for `listagg` overflows
*/
onOverflowClause
: ON OVERFLOW (ERROR | (TRUNCATE expression? (WITH|WITHOUT) COUNT))
;

/**
* A 'within group' clause: defines the order in which the ordered set-aggregate function should work
*/
withinGroupClause
: WITHIN GROUP LEFT_PAREN orderByClause RIGHT_PAREN
;

/**
* A 'filter' clause: a restriction applied to an aggregate function
*/
Expand Down Expand Up @@ -1387,6 +1409,7 @@ identifier
| CASE
| CAST
| COLLATE
| COUNT
| CROSS
| CUBE
| CURRENT
Expand All @@ -1406,6 +1429,7 @@ identifier
| EMPTY
| END
| ENTRY
| ERROR
| ESCAPE
| EVERY
| EXCEPT
Expand Down Expand Up @@ -1441,6 +1465,7 @@ identifier
| LIKE
| LIMIT
| LIST
| LISTAGG
| LOCAL
| LOCAL_DATE
| LOCAL_DATETIME
Expand Down Expand Up @@ -1472,6 +1497,7 @@ identifier
| OR
| ORDER
| OUTER
| OVERFLOW
| OVERLAY
| PAD
| PERCENT
Expand All @@ -1498,6 +1524,7 @@ identifier
| TRAILING
| TREAT
| TRIM
| TRUNCATE
| TYPE
| UNION
| UPDATE
Expand All @@ -1509,6 +1536,8 @@ identifier
| WHEN
| WHERE
| WITH
| WITHIN
| WITHOUT
| YEAR) {
logUseOfReservedWordAsIdentifier( getCurrentToken() );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,10 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
CommonFunctionFactory.currentUtcdatetimetimestamp( queryEngine );
CommonFunctionFactory.everyAny_sumCaseCase( queryEngine );
CommonFunctionFactory.bitLength_pattern( queryEngine, "length(to_binary(?1))*8" );

CommonFunctionFactory.listagg_stringAgg( "varchar", queryEngine );
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
.setArgumentsValidator( CommonFunctionFactory.formatValidator() )
.setArgumentListSignature("(TEMPORAL datetime as STRING pattern)")
.register();
CommonFunctionFactory.listagg_stringAgg( "string", queryEngine );
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,14 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
.setParameterTypes(FunctionParameterType.STRING, FunctionParameterType.STRING)
.setArgumentListSignature("(STRING string, STRING pattern)")
.register();

if ( getDB2Version().isSameOrAfter( 9, 5 ) ) {
CommonFunctionFactory.listagg( null, queryEngine );
if ( getDB2Version().isSameOrAfter( 11, 1 ) ) {
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package org.hibernate.dialect;

import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.identity.DB2390IdentityColumnSupport;
import org.hibernate.dialect.identity.DB2IdentityColumnSupport;
import org.hibernate.dialect.identity.IdentityColumnSupport;
Expand All @@ -19,6 +20,7 @@
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
Expand All @@ -40,6 +42,16 @@ public DB2iDialect(DialectResolutionInfo info) {
registerKeywords( info );
}

@Override
public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry( queryEngine );
if ( getVersion().isSameOrAfter( 7, 2 ) ) {
CommonFunctionFactory.listagg( null, queryEngine );
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
}
}

public DB2iDialect() {
this( DatabaseVersion.make(7) );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import jakarta.persistence.TemporalType;

import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.identity.DB2390IdentityColumnSupport;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.pagination.FetchLimitHandler;
Expand All @@ -19,6 +20,7 @@
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.IntervalType;
import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.sql.ast.SqlAstTranslator;
Expand Down Expand Up @@ -51,6 +53,16 @@ public DB2zDialect(DatabaseVersion version) {
super(version);
}

@Override
public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry( queryEngine );
if ( getVersion().isSameOrAfter( 12 ) ) {
CommonFunctionFactory.listagg( null, queryEngine );
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
}
}

@Override
protected String columnType(int jdbcTypeCode) {
// See https://www.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/wnew/src/tpc/db2z_10_timestamptimezone.html
Expand Down
10 changes: 10 additions & 0 deletions hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,16 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
CommonFunctionFactory.format_formatdatetime( queryEngine );
}
CommonFunctionFactory.rownum( queryEngine );
if ( getVersion().isSameOrAfter( 1, 4, 200 ) ) {
CommonFunctionFactory.listagg( null, queryEngine );
if ( getVersion().isSameOrAfter( 2 ) ) {
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
}
}
else {
CommonFunctionFactory.listagg_groupConcat( queryEngine );
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
if ( getVersion().isSameOrAfter( 2, 2 ) ) {
CommonFunctionFactory.rownum( queryEngine );
}
CommonFunctionFactory.listagg_groupConcat( queryEngine );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
}

queryEngine.getSqmFunctionRegistry().register( "field", new FieldFunction( queryEngine.getTypeConfiguration() ) );
CommonFunctionFactory.listagg_groupConcat( queryEngine );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.function.ModeStatsModeEmulation;
import org.hibernate.dialect.function.NvlCoalesceEmulation;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.identity.Oracle12cIdentityColumnSupport;
Expand Down Expand Up @@ -188,6 +189,20 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
"instr(?2,?1,?3)",
FunctionParameterType.STRING, FunctionParameterType.STRING, FunctionParameterType.INTEGER
).setArgumentListSignature("(pattern, string[, start])");
// The within group clause became optional in 18
if ( getVersion().isSameOrAfter( 18 ) ) {
CommonFunctionFactory.listagg( null, queryEngine );
}
else {
CommonFunctionFactory.listagg( "within group (order by rownum)", queryEngine );
}
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
// Oracle has a regular aggregate function named stats_mode
queryEngine.getSqmFunctionRegistry().register(
"mode",
new ModeStatsModeEmulation( queryEngine.getTypeConfiguration() )
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -448,9 +448,13 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
CommonFunctionFactory.soundex( queryEngine ); //was introduced in Postgres 9 apparently

CommonFunctionFactory.locate_positionSubstring( queryEngine );
CommonFunctionFactory.listagg_stringAgg( "varchar", queryEngine );

if ( getVersion().isSameOrAfter( 9, 4 ) ) {
CommonFunctionFactory.makeDateTimeTimestamp( queryEngine );
// Note that PostgreSQL doesn't support the OVER clause for ordered set-aggregate functions
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
.setParameterTypes(INTEGER)
.register();
}
CommonFunctionFactory.inverseDistributionOrderedSetAggregates( queryEngine );
CommonFunctionFactory.hypotheticalOrderedSetAggregates( queryEngine );
if ( getVersion().isSameOrAfter( 14 ) ) {
CommonFunctionFactory.listagg_stringAggWithinGroup( "varchar(max)", queryEngine );
}
}

@Override
Expand Down
Loading