Skip to content

Commit 02c03d1

Browse files
authored
Merge pull request #4529 from evolvedbinary/feature/tumbling-sliding-window
Support for XQuery Tumbling and Sliding Window
2 parents 363aaa7 + 57f3010 commit 02c03d1

Some content is hidden

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

61 files changed

+3703
-624
lines changed

exist-core/src/main/antlr/org/exist/xquery/parser/XQuery.g

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ options {
8686
8787
public XQueryParser(XQueryLexer lexer) {
8888
this((TokenStream)lexer);
89-
this.lexer= lexer;
89+
this.lexer = lexer;
9090
setASTNodeClass("org.exist.xquery.parser.XQueryAST");
9191
}
9292
@@ -95,15 +95,18 @@ options {
9595
}
9696
9797
public String getErrorMessage() {
98-
StringBuilder buf= new StringBuilder();
99-
for (Iterator i= exceptions.iterator(); i.hasNext();) {
98+
StringBuilder buf = new StringBuilder();
99+
for (Iterator i = exceptions.iterator(); i.hasNext();) {
100100
buf.append(((Exception) i.next()).toString());
101101
buf.append('\n');
102102
}
103103
return buf.toString();
104104
}
105105
106106
public Exception getLastException() {
107+
if (!foundError) {
108+
return null;
109+
}
107110
return (Exception) exceptions.get(exceptions.size() - 1);
108111
}
109112
@@ -112,7 +115,7 @@ options {
112115
}
113116
114117
protected void handleException(Exception e) {
115-
foundError= true;
118+
foundError = true;
116119
exceptions.add(e);
117120
}
118121
}
@@ -184,6 +187,11 @@ imaginaryTokenDefinitions
184187
PRAGMA
185188
GTEQ
186189
SEQUENCE
190+
TUMBLING_WINDOW
191+
CURRENT_ITEM
192+
PREVIOUS_ITEM
193+
NEXT_ITEM
194+
WINDOW_VARS
187195
;
188196
189197
// === XPointer ===
@@ -694,7 +702,7 @@ expr throws XPathException
694702
695703
exprSingle throws XPathException
696704
:
697-
( ( "for" | "let" ) DOLLAR ) => flworExpr
705+
( ( "for" | "let" ) ("tumbling" | "sliding" | DOLLAR ) ) => flworExpr
698706
| ( "try" LCURLY ) => tryCatchExpr
699707
| ( ( "some" | "every" ) DOLLAR ) => quantifiedExpr
700708
| ( "if" LPAREN ) => ifExpr
@@ -801,7 +809,9 @@ flworExpr throws XPathException
801809
802810
initialClause throws XPathException
803811
:
804-
( forClause | letClause )
812+
( ( "for" DOLLAR ) => forClause
813+
| ( "for" ( "tumbling" | "sliding" ) ) => windowClause
814+
| letClause )
805815
;
806816
807817
intermediateClause throws XPathException
@@ -831,6 +841,11 @@ letClause throws XPathException
831841
"let"^ letVarBinding ( COMMA! letVarBinding )*
832842
;
833843
844+
windowClause throws XPathException
845+
:
846+
"for"! ("tumbling"|"sliding") "window"^ inVarBinding windowStartCondition ( windowEndCondition )?
847+
;
848+
834849
inVarBinding throws XPathException
835850
{ String varName; }
836851
:
@@ -855,6 +870,37 @@ allowingEmpty
855870
"allowing"! "empty"
856871
;
857872
873+
windowStartCondition throws XPathException
874+
:
875+
"start"^ windowVars "when" exprSingle
876+
;
877+
878+
windowEndCondition throws XPathException
879+
:
880+
( "only" )? "end"^ windowVars "when" exprSingle
881+
;
882+
883+
windowVars throws XPathException
884+
{ String currentItemName = null, positionalVarName = null, previousItemName = null, nextItemName = null; }
885+
:
886+
( DOLLAR! currentItemName=eqName! )?
887+
( "at"! DOLLAR! positionalVarName=eqName! )?
888+
( "previous"! DOLLAR! previousItemName=eqName! )?
889+
( "next"! DOLLAR! nextItemName=eqName! )?
890+
{
891+
windowVars_AST = (org.exist.xquery.parser.XQueryAST)astFactory.create(WINDOW_VARS);
892+
if (currentItemName != null)
893+
windowVars_AST.addChild(astFactory.create(CURRENT_ITEM,currentItemName));
894+
if (positionalVarName != null)
895+
windowVars_AST.addChild(astFactory.create(POSITIONAL_VAR,positionalVarName));
896+
if (previousItemName != null)
897+
windowVars_AST.addChild(astFactory.create(PREVIOUS_ITEM,previousItemName));
898+
if (nextItemName != null)
899+
windowVars_AST.addChild(astFactory.create(NEXT_ITEM,nextItemName));
900+
currentAST.root = (org.exist.xquery.parser.XQueryAST) windowVars_AST;
901+
}
902+
;
903+
858904
letVarBinding throws XPathException
859905
{ String varName; }
860906
:
@@ -887,7 +933,6 @@ orderModifier
887933
groupByClause throws XPathException
888934
:
889935
"group"! "by"! groupingSpecList
890-
// "group"! toGroupVarRef "as"! groupVarBinding "by"! groupSpecList
891936
{ #groupByClause= #([GROUP_BY, "group by"], #groupByClause); }
892937
;
893938
@@ -899,7 +944,7 @@ groupingSpecList throws XPathException
899944
groupingSpec throws XPathException
900945
{ String groupKeyVarName; }
901946
:
902-
DOLLAR! groupKeyVarName=varName! ( COLON! EQ! exprSingle )? ( "collation" STRING_LITERAL )?
947+
DOLLAR! groupKeyVarName=varName! ( ( typeDeclaration )? COLON! EQ! exprSingle )? ( "collation" STRING_LITERAL )?
903948
{ #groupingSpec = #(#[VARIABLE_BINDING, groupKeyVarName], #groupingSpec); }
904949
;
905950
@@ -2241,8 +2286,27 @@ reservedKeywords returns [String name]
22412286
"empty-sequence" { name = "empty-sequence"; }
22422287
|
22432288
"schema-element" { name = "schema-element"; }
2289+
|
2290+
"tumbling" { name = "tumbling"; }
2291+
|
2292+
"sliding" { name = "sliding"; }
2293+
|
2294+
"window" { name = "window"; }
2295+
|
2296+
"start" { name = "start"; }
2297+
|
2298+
"end" { name = "end"; }
2299+
|
2300+
"only" { name = "only"; }
2301+
|
2302+
"previous" { name = "previous"; }
2303+
|
2304+
"next" { name = "next"; }
2305+
|
2306+
"when" { name = "when"; }
22442307
;
22452308

2309+
22462310
/**
22472311
* The XQuery/XPath lexical analyzer.
22482312
*/

0 commit comments

Comments
 (0)