Skip to content

Commit 9703ff4

Browse files
fix: parse a bracketed operand at the start of a PARTITION BY list (#2878)
`SELECT SUM(x) OVER (PARTITION BY (1 + a) / 2) FROM t` failed with a ParseException at the `/`. The four PARTITION BY sites chose between `LOOKAHEAD(3) ComplexExpressionList()` and a bracketed list `"(" ComplexExpressionList() ")"`. The probe scans into `Expression()`, whose binary operators live in a Java loop the scan cannot see, so it failed on `( 1 +`, the bracketed alternative won, parsed `(1 + a)` as the whole list and then met `/`. The bracketed alternative only won when the probe failed, and the parse then failed too, so dropping it changes nothing that parsed before. All four sites now call `ComplexExpressionList()` directly.
1 parent f162cfe commit 9703ff4

2 files changed

Lines changed: 27 additions & 19 deletions

File tree

‎src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt‎

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9477,7 +9477,6 @@ PlainSelect PlainSelect() #PlainSelect:
94779477
OracleHierarchicalExpression oracleHierarchicalQueryClause = null;
94789478
PreferringClause preferringClause = null;
94799479
ExpressionList expressionList = null;
9480-
boolean partitionByBrackets = false;
94819480
List<Table> intoTables = null;
94829481
MySqlSelectIntoClause mySqlSelectIntoClause = null;
94839482
MySqlProcedureAnalyse mySqlProcedureAnalyse = null;
@@ -9583,13 +9582,9 @@ PlainSelect PlainSelect() #PlainSelect:
95839582
[ LOOKAHEAD(2) oracleHierarchicalQueryClause=OracleHierarchicalQueryClause() { plainSelect.setOracleHierarchical(oracleHierarchicalQueryClause); } ]
95849583
[ LOOKAHEAD(2) preferringClause=PreferringClause() { plainSelect.setPreferringClause(preferringClause); }
95859584
[LOOKAHEAD(2) <K_PARTITION> <K_BY>
9586-
(
9587-
LOOKAHEAD(2) expressionList=ComplexExpressionList()
9588-
|
9589-
"(" {partitionByBrackets = true;} expressionList=ComplexExpressionList() ")"
9590-
)
9585+
expressionList=ComplexExpressionList()
95919586
{
9592-
preferringClause.setPartitionExpressionList(expressionList, partitionByBrackets);
9587+
preferringClause.setPartitionExpressionList(expressionList, false);
95939588
}
95949589
]
95959590
]
@@ -14467,7 +14462,6 @@ JsonAggregateFunction JsonAggregateFunction() : {
1446714462
ExpressionList expressionList = null;
1446814463
List<OrderByElement> olist = null;
1446914464
WindowElement windowElement = null;
14470-
boolean partitionByBrackets = false;
1447114465
}
1447214466
{
1447314467
(
@@ -14554,13 +14548,12 @@ JsonAggregateFunction JsonAggregateFunction() : {
1455414548
<K_OVER> {result.setAnalyticType(AnalyticType.OVER);}
1455514549
"("
1455614550
[<K_PARTITION> <K_BY>
14557-
(LOOKAHEAD(3) expressionList=ComplexExpressionList()
14558-
| "(" {partitionByBrackets = true;} expressionList=ComplexExpressionList() ")" )
14551+
expressionList=ComplexExpressionList()
1455914552
]
1456014553
[olist=OrderByElements() ]
1456114554
[windowElement = WindowElement() ]
1456214555
{
14563-
result.setPartitionExpressionList(expressionList, partitionByBrackets);
14556+
result.setPartitionExpressionList(expressionList, false);
1456414557
result.setOrderByElements(olist);
1456514558
result.setWindowElement(windowElement);
1456614559
}
@@ -14702,7 +14695,6 @@ KeepExpression KeepExpression() : {
1470214695

1470314696
void windowFun(AnalyticExpression retval):{
1470414697
ExpressionList expressionList = null;
14705-
boolean partitionByBrackets = false;
1470614698
String windowName = null;
1470714699
WindowDefinition winDef;
1470814700
} {
@@ -14726,10 +14718,9 @@ void windowFun(AnalyticExpression retval):{
1472614718
[
1472714719
LOOKAHEAD(2) <K_OVER> "("
1472814720
[ <K_PARTITION> <K_BY>
14729-
(LOOKAHEAD(3) expressionList=ComplexExpressionList()
14730-
| "(" {partitionByBrackets = true;} expressionList=ComplexExpressionList() ")" )
14721+
expressionList=ComplexExpressionList()
1473114722
]
14732-
")" { winDef.setPartitionExpressionList(expressionList, partitionByBrackets); retval.setType(AnalyticType.WITHIN_GROUP_OVER); }
14723+
")" { winDef.setPartitionExpressionList(expressionList, false); retval.setType(AnalyticType.WITHIN_GROUP_OVER); }
1473314724
]
1473414725
)
1473514726
}
@@ -14738,7 +14729,6 @@ WindowDefinition windowDefinition() : {
1473814729
ExpressionList expressionList = null;
1473914730
List<OrderByElement> olist = null;
1474014731
WindowElement windowElement = null;
14741-
boolean partitionByBrackets = false;
1474214732
WindowDefinition winDef = new WindowDefinition();
1474314733
String baseWindowName;
1474414734
} {
@@ -14752,13 +14742,12 @@ WindowDefinition windowDefinition() : {
1475214742
{}
1475314743
)
1475414744
[<K_PARTITION> <K_BY>
14755-
(LOOKAHEAD(3) expressionList=ComplexExpressionList()
14756-
| "(" {partitionByBrackets = true;} expressionList=ComplexExpressionList() ")" )
14745+
expressionList=ComplexExpressionList()
1475714746
]
1475814747
[olist=OrderByElements() ]
1475914748
[windowElement = WindowElement() ]
1476014749
{
14761-
winDef.setPartitionExpressionList(expressionList, partitionByBrackets);
14750+
winDef.setPartitionExpressionList(expressionList, false);
1476214751
winDef.setOrderByElements(olist);
1476314752
winDef.setWindowElement(windowElement);
1476414753
}

‎src/test/java/net/sf/jsqlparser/expression/AnalyticExpressionTest.java‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,23 @@ void testDatabricks() throws JSQLParserException {
4343

4444
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
4545
}
46+
47+
@Test
48+
void testPartitionByBracketedOperand() throws JSQLParserException {
49+
TestUtils.assertSqlCanBeParsedAndDeparsed(
50+
"SELECT SUM(x) OVER (PARTITION BY (1 + a) / 2 ORDER BY b) FROM t", true);
51+
52+
TestUtils.assertSqlCanBeParsedAndDeparsed(
53+
"SELECT SUM(x) OVER w FROM t WINDOW w AS (PARTITION BY (1 + a) / 2)", true);
54+
55+
TestUtils.assertSqlCanBeParsedAndDeparsed(
56+
"SELECT LISTAGG(x, ',') WITHIN GROUP (ORDER BY y) OVER (PARTITION BY (1 + a) / 2) FROM t",
57+
true);
58+
59+
TestUtils.assertSqlCanBeParsedAndDeparsed(
60+
"SELECT * FROM t PREFERRING HIGH x PARTITION BY (1 + a) / 2", true);
61+
62+
TestUtils.assertSqlCanBeParsedAndDeparsed(
63+
"SELECT SUM(x) OVER (PARTITION BY (a, b), c) FROM t", true);
64+
}
4665
}

0 commit comments

Comments
 (0)