Skip to content

Commit 5828536

Browse files
committed
Implement window function support in HQL
1 parent d5d1cf9 commit 5828536

File tree

51 files changed

+1500
-148
lines changed

Some content is hidden

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

51 files changed

+1500
-148
lines changed

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

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -308,19 +308,22 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
308308
doubleType
309309
);
310310

311-
if ( getVersion().isSameOrAfter( 4, 0 ) ) {
312-
Arrays.asList( "md5", "sha1", "sha256", "sha512" )
313-
.forEach( hash -> functionRegistry.registerPattern(
314-
hash,
315-
"crypt_hash(?1 using " + hash + ")",
316-
byteArrayType
317-
) );
318-
functionRegistry.registerAlternateKey( "sha", "sha1" );
319-
functionRegistry.registerPattern(
320-
"crc32",
321-
"hash(?1 using crc32)",
322-
integerType
323-
);
311+
if ( getVersion().isSameOrAfter( 3 ) ) {
312+
functionFactory.windowFunctions();
313+
if ( getVersion().isSameOrAfter( 4, 0 ) ) {
314+
Arrays.asList( "md5", "sha1", "sha256", "sha512" )
315+
.forEach( hash -> functionRegistry.registerPattern(
316+
hash,
317+
"crypt_hash(?1 using " + hash + ")",
318+
byteArrayType
319+
) );
320+
functionRegistry.registerAlternateKey( "sha", "sha1" );
321+
functionRegistry.registerPattern(
322+
"crc32",
323+
"hash(?1 using crc32)",
324+
integerType
325+
);
326+
}
324327
}
325328

326329
functionFactory.listagg_list( "varchar" );

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
185185

186186
queryEngine.getSqmFunctionRegistry().register( "least", new CaseLeastGreatestEmulation( true ) );
187187
queryEngine.getSqmFunctionRegistry().register( "greatest", new CaseLeastGreatestEmulation( false ) );
188+
if ( supportsWindowFunctions() ) {
189+
functionFactory.windowFunctions();
190+
}
188191
}
189192

190193
@Override

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
301301
.register();
302302

303303
// No idea since when this is supported
304+
functionFactory.windowFunctions();
304305
functionFactory.listagg( null );
305306
functionFactory.inverseDistributionOrderedSetAggregates();
306307
functionFactory.hypotheticalOrderedSetAggregates();

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
@@ -317,6 +317,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
317317
.setParameterTypes(NUMERIC)
318318
.register();
319319
}
320+
functionFactory.windowFunctions();
320321
functionFactory.listagg_groupConcat();
321322
}
322323

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ protected String columnType(int jdbcTypeCode) {
8080
@Override
8181
public void initializeFunctionRegistry(QueryEngine queryEngine) {
8282
super.initializeFunctionRegistry( queryEngine );
83-
new CommonFunctionFactory( queryEngine ).listagg_list( "varchar" );
83+
final CommonFunctionFactory functionFactory = new CommonFunctionFactory( queryEngine );
84+
functionFactory.listagg_list( "varchar" );
85+
if ( getVersion().isSameOrAfter( 12 ) ) {
86+
functionFactory.windowFunctions();
87+
}
8488
}
8589

8690
@Override

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

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

288288
// No idea since when this is supported
289+
functionFactory.windowFunctions();
289290
functionFactory.inverseDistributionOrderedSetAggregates();
290291
functionFactory.hypotheticalOrderedSetAggregates();
291292
}

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ ANY : [aA] [nN] [yY];
146146
AS : [aA] [sS];
147147
ASC : [aA] [sS] [cC];
148148
AVG : [aA] [vV] [gG];
149-
BY : [bB] [yY];
150149
BETWEEN : [bB] [eE] [tT] [wW] [eE] [eE] [nN];
151150
BOTH : [bB] [oO] [tT] [hH];
151+
BY : [bB] [yY];
152152
CASE : [cC] [aA] [sS] [eE];
153153
CAST : [cC] [aA] [sS] [tT];
154154
COLLATE : [cC] [oO] [lL] [lL] [aA] [tT] [eE];
@@ -176,19 +176,24 @@ ERROR : [eE] [rR] [rR] [oO] [rR];
176176
ESCAPE : [eE] [sS] [cC] [aA] [pP] [eE];
177177
EVERY : [eE] [vV] [eE] [rR] [yY];
178178
EXCEPT : [eE] [xX] [cC] [eE] [pP] [tT];
179+
EXCLUDE : [eE] [xX] [cC] [lL] [uU] [dD] [eE];
179180
EXISTS : [eE] [xX] [iI] [sS] [tT] [sS];
180181
EXTRACT : [eE] [xX] [tT] [rR] [aA] [cC] [tT];
181182
FETCH : [fF] [eE] [tT] [cC] [hH];
182183
FILTER : [fF] [iI] [lL] [tT] [eE] [rR];
183184
FIRST : [fF] [iI] [rR] [sS] [tT];
184-
FROM : [fF] [rR] [oO] [mM];
185+
FOLLOWING : [fF] [oO] [lL] [lL] [oO] [wW] [iI] [nN] [gG];
185186
FOR : [fF] [oO] [rR];
186187
FORMAT : [fF] [oO] [rR] [mM] [aA] [tT];
188+
FROM : [fF] [rR] [oO] [mM];
187189
FULL : [fF] [uU] [lL] [lL];
188190
FUNCTION : [fF] [uU] [nN] [cC] [tT] [iI] [oO] [nN];
189191
GROUP : [gG] [rR] [oO] [uU] [pP];
192+
GROUPS : [gG] [rR] [oO] [uU] [pP] [sS];
190193
HAVING : [hH] [aA] [vV] [iI] [nN] [gG];
191194
HOUR : [hH] [oO] [uU] [rR];
195+
IGNORE : [iI] [gG] [nN] [oO] [rR] [eE];
196+
ILIKE : [iI] [lL] [iI] [kK] [eE];
192197
IN : [iI] [nN];
193198
INDEX : [iI] [nN] [dD] [eE] [xX];
194199
INDICES : [iI] [nN] [dD] [iI] [cC] [eE] [sS];
@@ -204,7 +209,6 @@ LAST : [lL] [aA] [sS] [tT];
204209
LEADING : [lL] [eE] [aA] [dD] [iI] [nN] [gG];
205210
LEFT : [lL] [eE] [fF] [tT];
206211
LIKE : [lL] [iI] [kK] [eE];
207-
ILIKE : [iI] [lL] [iI] [kK] [eE];
208212
LIMIT : [lL] [iI] [mM] [iI] [tT];
209213
LIST : [lL] [iI] [sS] [tT];
210214
LISTAGG : [lL] [iI] [sS] [tT] [aA] [gG] [gG];
@@ -215,18 +219,19 @@ LOCAL_TIME : [lL] [oO] [cC] [aA] [lL] '_' [tT] [iI] [mM] [eE];
215219
MAP : [mM] [aA] [pP];
216220
MAX : [mM] [aA] [xX];
217221
MAXELEMENT : [mM] [aA] [xX] [eE] [lL] [eE] [mM] [eE] [nN] [tT];
218-
MIN : [mM] [iI] [nN];
219222
MAXINDEX : [mM] [aA] [xX] [iI] [nN] [dD] [eE] [xX];
220223
MEMBER : [mM] [eE] [mM] [bB] [eE] [rR];
221224
MICROSECOND : [mM] [iI] [cC] [rR] [oO] [sS] [eE] [cC] [oO] [nN] [dD];
222225
MILLISECOND : [mM] [iI] [lL] [lL] [iI] [sS] [eE] [cC] [oO] [nN] [dD];
226+
MIN : [mM] [iI] [nN];
223227
MINELEMENT : [mM] [iI] [nN] [eE] [lL] [eE] [mM] [eE] [nN] [tT];
224228
MININDEX : [mM] [iI] [nN] [iI] [nN] [dD] [eE] [xX];
225229
MINUTE : [mM] [iI] [nN] [uU] [tT] [eE];
226230
MONTH : [mM] [oO] [nN] [tT] [hH];
227231
NANOSECOND : [nN] [aA] [nN] [oO] [sS] [eE] [cC] [oO] [nN] [dD];
228-
NEXT : [nN] [eE] [xX] [tT];
229232
NEW : [nN] [eE] [wW];
233+
NEXT : [nN] [eE] [xX] [tT];
234+
NO : [nN] [oO];
230235
NOT : [nN] [oO] [tT];
231236
NULLS : [nN] [uU] [lL] [lL] [sS];
232237
OBJECT : [oO] [bB] [jJ] [eE] [cC] [tT];
@@ -237,18 +242,24 @@ ON : [oO] [nN];
237242
ONLY : [oO] [nN] [lL] [yY];
238243
OR : [oO] [rR];
239244
ORDER : [oO] [rR] [dD] [eE] [rR];
245+
OTHERS : [oO] [tT] [hH] [eE] [rR] [sS];
240246
OUTER : [oO] [uU] [tT] [eE] [rR];
247+
OVER : [oO] [vV] [eE] [rR];
241248
OVERFLOW : [oO] [vV] [eE] [rR] [fF] [lL] [oO] [wW];
242249
OVERLAY : [oO] [vV] [eE] [rR] [lL] [aA] [yY];
243250
PAD : [pP] [aA] [dD];
251+
PARTITION : [pP] [aA] [rR] [tT] [iI] [tT] [iI] [oO] [nN];
244252
PERCENT : [pP] [eE] [rR] [cC] [eE] [nN] [tT];
245253
PLACING : [pP] [lL] [aA] [cC] [iI] [nN] [gG];
246254
POSITION : [pP] [oO] [sS] [iI] [tT] [iI] [oO] [nN];
255+
PRECEDING : [pP] [rR] [eE] [cC] [eE] [dD] [iI] [nN] [gG];
247256
QUARTER : [qQ] [uU] [aA] [rR] [tT] [eE] [rR];
257+
RANGE : [rR] [aA] [nN] [gG] [eE];
258+
RESPECT : [rR] [eE] [sS] [pP] [eE] [cC] [tT];
248259
RIGHT : [rR] [iI] [gG] [hH] [tT];
249260
ROLLUP : [rR] [oO] [lL] [lL] [uU] [pP];
250-
ROWS : [rR] [oO] [wW] [sS];
251261
ROW : [rR] [oO] [wW];
262+
ROWS : [rR] [oO] [wW] [sS];
252263
SECOND : [sS] [eE] [cC] [oO] [nN] [dD];
253264
SELECT : [sS] [eE] [lL] [eE] [cC] [tT];
254265
SET : [sS] [eE] [tT];
@@ -267,6 +278,7 @@ TREAT : [tT] [rR] [eE] [aA] [tT];
267278
TRIM : [tT] [rR] [iI] [mM];
268279
TRUNCATE : [tT] [rR] [uU] [nN] [cC] [aA] [tT] [eE];
269280
TYPE : [tT] [yY] [pP] [eE];
281+
UNBOUNDED : [uU] [nN] [bB] [oO] [uU] [nN] [dD] [eE] [dD];
270282
UNION : [uU] [nN] [iI] [oO] [nN];
271283
UPDATE : [uU] [pP] [dD] [aA] [tT] [eE];
272284
VALUE : [vV] [aA] [lL] [uU] [eE];

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

Lines changed: 85 additions & 5 deletions
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 withinGroupClause? filterClause?
978+
: genericFunctionName LEFT_PAREN (genericFunctionArguments | ASTERISK)? RIGHT_PAREN nthSideClause? nullsClause? withinGroupClause? filterClause? overClause?
979979
;
980980

981981
/**
@@ -1052,7 +1052,7 @@ aggregateFunction
10521052
* The functions 'every()' and 'all()' are synonyms
10531053
*/
10541054
everyFunction
1055-
: (EVERY|ALL) LEFT_PAREN predicate RIGHT_PAREN filterClause?
1055+
: (EVERY|ALL) LEFT_PAREN predicate RIGHT_PAREN filterClause? overClause?
10561056
| (EVERY|ALL) LEFT_PAREN subquery RIGHT_PAREN
10571057
| (EVERY|ALL) (ELEMENTS|INDICES) LEFT_PAREN simplePath RIGHT_PAREN
10581058
;
@@ -1061,7 +1061,7 @@ everyFunction
10611061
* The functions 'any()' and 'some()' are synonyms
10621062
*/
10631063
anyFunction
1064-
: (ANY|SOME) LEFT_PAREN predicate RIGHT_PAREN filterClause?
1064+
: (ANY|SOME) LEFT_PAREN predicate RIGHT_PAREN filterClause? overClause?
10651065
| (ANY|SOME) LEFT_PAREN subquery RIGHT_PAREN
10661066
| (ANY|SOME) (ELEMENTS|INDICES) LEFT_PAREN simplePath RIGHT_PAREN
10671067
;
@@ -1070,7 +1070,7 @@ anyFunction
10701070
* The 'listagg()' ordered set-aggregate function
10711071
*/
10721072
listaggFunction
1073-
: LISTAGG LEFT_PAREN DISTINCT? expressionOrPredicate COMMA expressionOrPredicate onOverflowClause? RIGHT_PAREN withinGroupClause? filterClause?
1073+
: LISTAGG LEFT_PAREN DISTINCT? expressionOrPredicate COMMA expressionOrPredicate onOverflowClause? RIGHT_PAREN withinGroupClause? filterClause? overClause?
10741074
;
10751075

10761076
/**
@@ -1094,6 +1094,74 @@ filterClause
10941094
: FILTER LEFT_PAREN whereClause RIGHT_PAREN
10951095
;
10961096

1097+
/**
1098+
* A `nulls` clause: what should a value access window function do when encountering a `null`
1099+
*/
1100+
nullsClause
1101+
: RESPECT NULLS
1102+
| IGNORE NULLS
1103+
;
1104+
1105+
/**
1106+
* A `nulls` clause: what should a value access window function do when encountering a `null`
1107+
*/
1108+
nthSideClause
1109+
: FROM FIRST
1110+
| FROM LAST
1111+
;
1112+
1113+
/**
1114+
* A 'over' clause: the specification of a window within which the function should act
1115+
*/
1116+
overClause
1117+
: OVER LEFT_PAREN partitionClause? orderByClause? frameClause? RIGHT_PAREN
1118+
;
1119+
1120+
/**
1121+
* A 'partition' clause: the specification the group within which a function should act in a window
1122+
*/
1123+
partitionClause
1124+
: PARTITION BY expression (COMMA expression)*
1125+
;
1126+
1127+
/**
1128+
* A 'frame' clause: the specification the content of the window
1129+
*/
1130+
frameClause
1131+
: (RANGE|ROWS|GROUPS) frameStart frameExclusion?
1132+
| (RANGE|ROWS|GROUPS) BETWEEN frameStart AND frameEnd frameExclusion?
1133+
;
1134+
1135+
/**
1136+
* The start of the window content
1137+
*/
1138+
frameStart
1139+
: UNBOUNDED PRECEDING
1140+
| expression PRECEDING
1141+
| CURRENT ROW
1142+
| expression FOLLOWING
1143+
;
1144+
1145+
/**
1146+
* The end of the window content
1147+
*/
1148+
frameEnd
1149+
: expression PRECEDING
1150+
| CURRENT ROW
1151+
| expression FOLLOWING
1152+
| UNBOUNDED FOLLOWING
1153+
;
1154+
1155+
/**
1156+
* A 'exclusion' clause: the specification what to exclude from the window content
1157+
*/
1158+
frameExclusion
1159+
: EXCLUDE CURRENT ROW
1160+
| EXCLUDE GROUP
1161+
| EXCLUDE TIES
1162+
| EXCLUDE NO OTHERS
1163+
;
1164+
10971165
/**
10981166
* Any function with an irregular syntax for the argument list
10991167
*
@@ -1418,8 +1486,8 @@ identifier
14181486
| CURRENT_TIME
14191487
| CURRENT_TIMESTAMP
14201488
| DATE
1421-
| DAY
14221489
| DATETIME
1490+
| DAY
14231491
| DELETE
14241492
| DESC
14251493
| DISTINCT
@@ -1433,20 +1501,24 @@ identifier
14331501
| ESCAPE
14341502
| EVERY
14351503
| EXCEPT
1504+
| EXCLUDE
14361505
| EXISTS
14371506
| EXTRACT
14381507
| FETCH
14391508
| FILTER
14401509
| FIRST
1510+
| FOLLOWING
14411511
| FOR
14421512
| FORMAT
14431513
| FROM
14441514
| FULL
14451515
| FUNCTION
14461516
| GROUP
1517+
| GROUPS
14471518
| HAVING
14481519
| HOUR
14491520
| ID
1521+
| IGNORE
14501522
| ILIKE
14511523
| IN
14521524
| INDEX
@@ -1486,6 +1558,7 @@ identifier
14861558
| NATURALID
14871559
| NEW
14881560
| NEXT
1561+
| NO
14891562
| NOT
14901563
| NULLS
14911564
| OBJECT
@@ -1496,14 +1569,20 @@ identifier
14961569
| ONLY
14971570
| OR
14981571
| ORDER
1572+
| OTHERS
14991573
| OUTER
1574+
| OVER
15001575
| OVERFLOW
15011576
| OVERLAY
15021577
| PAD
1578+
| PARTITION
15031579
| PERCENT
15041580
| PLACING
15051581
| POSITION
1582+
| PRECEDING
15061583
| QUARTER
1584+
| RANGE
1585+
| RESPECT
15071586
| RIGHT
15081587
| ROLLUP
15091588
| ROW
@@ -1526,6 +1605,7 @@ identifier
15261605
| TRIM
15271606
| TRUNCATE
15281607
| TYPE
1608+
| UNBOUNDED
15291609
| UNION
15301610
| UPDATE
15311611
| VALUE

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
311311
functionFactory.everyAny_minMaxCase();
312312
functionFactory.bitLength_pattern( "length(to_binary(?1))*8" );
313313

314+
functionFactory.windowFunctions();
314315
functionFactory.listagg_stringAgg( "varchar" );
315316
functionFactory.inverseDistributionOrderedSetAggregates();
316317
functionFactory.hypotheticalOrderedSetAggregates_windowEmulation();

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
235235
.setArgumentsValidator( CommonFunctionFactory.formatValidator() )
236236
.setArgumentListSignature("(TEMPORAL datetime as STRING pattern)")
237237
.register();
238+
functionFactory.windowFunctions();
238239
functionFactory.listagg_stringAgg( "string" );
239240
functionFactory.inverseDistributionOrderedSetAggregates();
240241
functionFactory.hypotheticalOrderedSetAggregates();

0 commit comments

Comments
 (0)