@@ -1713,6 +1713,17 @@ public class CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> {
17131713 }
17141714 }
17151715
1716+ /** Whether a window specification starts with the name of the window it extends. */
1717+ private boolean isBaseWindowNameAhead() {
1718+ Token token = getToken(1);
1719+ switch (token.kind) {
1720+ case K_PARTITION: case K_ORDER: case K_ROWS: case K_RANGE: case K_GROUPS:
1721+ return false;
1722+ default:
1723+ return isIdentifierishNameToken(token);
1724+ }
1725+ }
1726+
17161727 private boolean isAliasAhead() {
17171728 if (isAsOfJoinAhead() || isSemiAntiJoinAhead() || isApproxNearestAhead()) {
17181729 return false;
@@ -8289,6 +8300,9 @@ PlainSelect PlainSelect() #PlainSelect:
82898300 ( LOOKAHEAD(2) "," windowName = RelObjectName() <K_AS> winDef = windowDefinition() { winDefs.add(winDef.withWindowName(windowName)); } )*
82908301 { plainSelect.setWindowDefinitions(winDefs); }
82918302 ]
8303+ // DuckDB: QUALIFY after WINDOW
8304+ [ LOOKAHEAD(2, { plainSelect.getQualify() == null }) qualify=Qualify()
8305+ { plainSelect.setQualify(qualify); plainSelect.setQualifyAfterWindow(true); } ]
82928306 [ LOOKAHEAD(<K_ORDER> <K_BY>) orderByElements = OrderByElements() { plainSelect.setOrderByElements(orderByElements); } ]
82938307 [ LOOKAHEAD(2) interpolateElements = InterpolateClause() { plainSelect.setInterpolate(interpolateElements); } ]
82948308 [ LOOKAHEAD(2) forClause = ForClause() {plainSelect.setForClause(forClause);} ]
@@ -13333,8 +13347,12 @@ WindowDefinition windowDefinition() : {
1333313347 WindowElement windowElement = null;
1333413348 boolean partitionByBrackets = false;
1333513349 WindowDefinition winDef = new WindowDefinition();
13350+ String baseWindowName;
1333613351} {
1333713352 "("
13353+ // DuckDB: (w ORDER BY b) extends the named window w
13354+ [ LOOKAHEAD({ isBaseWindowNameAhead() }) baseWindowName=RelObjectName()
13355+ { winDef.setBaseWindowName(baseWindowName); } ]
1333813356 [<K_PARTITION> <K_BY>
1333913357 (LOOKAHEAD(3) expressionList=ComplexExpressionList()
1334013358 | "(" {partitionByBrackets = true;} expressionList=ComplexExpressionList() ")" )
@@ -13358,7 +13376,7 @@ AnalyticExpression AnalyticExpression(Function function) :
1335813376{
1335913377 (
1336013378 (
13361- filter=AggregateFilter() { retval.setType(AnalyticType.FILTER_ONLY); }
13379+ filter=AggregateFilter(retval ) { retval.setType(AnalyticType.FILTER_ONLY); }
1336213380 [ LOOKAHEAD(2) windowFun(retval) ]
1336313381 {
1336413382 if (Dialect.POSTGRESQL.name().equals(getAsString(Feature.dialect))
@@ -13370,19 +13388,29 @@ AnalyticExpression AnalyticExpression(Function function) :
1337013388 )
1337113389 | windowFun(retval)
1337213390 [ LOOKAHEAD({ retval.getType() == AnalyticType.WITHIN_GROUP
13373- && getToken(1).kind == K_FILTER }) filter=AggregateFilter() ]
13391+ && getToken(1).kind == K_FILTER }) filter=AggregateFilter(retval ) ]
1337413392 )
1337513393 {
1337613394 retval.setFilterExpression(filter);
1337713395 if (true) { return retval; }
1337813396 }
1337913397}
1338013398
13381- /** Shared FILTER predicate for ordinary, window, and ordered-set aggregates. */
13382- Expression AggregateFilter():
13399+ /**
13400+ * Shared FILTER predicate for ordinary, window, and ordered-set aggregates. DuckDB also accepts
13401+ * it without WHERE, FILTER (x > 1), but PostgreSQL does not.
13402+ */
13403+ Expression AggregateFilter(AnalyticExpression analyticExpression):
1338313404{ Expression filter; }
1338413405{
13385- <K_FILTER> "(" <K_WHERE> filter=Expression() ")"
13406+ <K_FILTER> "("
13407+ (
13408+ <K_WHERE>
13409+ |
13410+ LOOKAHEAD({ !Dialect.POSTGRESQL.name().equals(getAsString(Feature.dialect)) })
13411+ { analyticExpression.setFilterWhereKeyword(false); }
13412+ )
13413+ filter=Expression() ")"
1338613414 { return filter; }
1338713415}
1338813416
0 commit comments