Skip to content

Commit c20a50e

Browse files
committed
Add PARTITION BY support in OVER clause for window functions
- Add Partitions and OrderByClause fields to OverClause AST type - Update OVER clause parser to handle PARTITION BY and ORDER BY - Add overClauseToJSON function for proper marshalling - Enable 4 WithinGroupTests (130, 140, both baseline and regular)
1 parent 90ad1a1 commit c20a50e

7 files changed

Lines changed: 57 additions & 11 deletions

File tree

ast/function_call.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ func (*UserDefinedTypeCallTarget) callTarget() {}
2828

2929
// OverClause represents an OVER clause for window functions.
3030
type OverClause struct {
31-
// Add partition by, order by, and window frame as needed
31+
Partitions []ScalarExpression `json:"Partitions,omitempty"`
32+
OrderByClause *OrderByClause `json:"OrderByClause,omitempty"`
3233
}
3334

3435
// WithinGroupClause represents a WITHIN GROUP clause for ordered set aggregate functions.

parser/marshal.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,9 +1389,7 @@ func scalarExpressionToJSON(expr ast.ScalarExpression) jsonNode {
13891389
node["WithinGroupClause"] = withinGroupClauseToJSON(e.WithinGroupClause)
13901390
}
13911391
if e.OverClause != nil {
1392-
node["OverClause"] = jsonNode{
1393-
"$type": "OverClause",
1394-
}
1392+
node["OverClause"] = overClauseToJSON(e.OverClause)
13951393
}
13961394
if len(e.IgnoreRespectNulls) > 0 {
13971395
idents := make([]jsonNode, len(e.IgnoreRespectNulls))
@@ -2151,6 +2149,23 @@ func withinGroupClauseToJSON(wg *ast.WithinGroupClause) jsonNode {
21512149
return node
21522150
}
21532151

2152+
func overClauseToJSON(oc *ast.OverClause) jsonNode {
2153+
node := jsonNode{
2154+
"$type": "OverClause",
2155+
}
2156+
if len(oc.Partitions) > 0 {
2157+
partitions := make([]jsonNode, len(oc.Partitions))
2158+
for i, p := range oc.Partitions {
2159+
partitions[i] = scalarExpressionToJSON(p)
2160+
}
2161+
node["Partitions"] = partitions
2162+
}
2163+
if oc.OrderByClause != nil {
2164+
node["OrderByClause"] = orderByClauseToJSON(oc.OrderByClause)
2165+
}
2166+
return node
2167+
}
2168+
21542169
// ======================= New Statement JSON Functions =======================
21552170

21562171
func tableHintToJSON(h ast.TableHintType) jsonNode {

parser/parse_select.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,14 +1374,44 @@ func (p *Parser) parsePostExpressionAccess(expr ast.ScalarExpression) (ast.Scala
13741374
}
13751375
p.nextToken() // consume (
13761376

1377-
// For now, just skip to closing paren (basic OVER() support)
1378-
// TODO: Parse partition by, order by, and window frame
1377+
overClause := &ast.OverClause{}
1378+
1379+
// Parse PARTITION BY
1380+
if strings.ToUpper(p.curTok.Literal) == "PARTITION" {
1381+
p.nextToken() // consume PARTITION
1382+
if strings.ToUpper(p.curTok.Literal) == "BY" {
1383+
p.nextToken() // consume BY
1384+
}
1385+
// Parse partition expressions
1386+
for p.curTok.Type != TokenRParen && p.curTok.Type != TokenEOF {
1387+
partExpr, err := p.parseScalarExpression()
1388+
if err != nil {
1389+
return nil, err
1390+
}
1391+
overClause.Partitions = append(overClause.Partitions, partExpr)
1392+
if p.curTok.Type == TokenComma {
1393+
p.nextToken()
1394+
} else {
1395+
break
1396+
}
1397+
}
1398+
}
1399+
1400+
// Parse ORDER BY
1401+
if p.curTok.Type == TokenOrder {
1402+
orderBy, err := p.parseOrderByClause()
1403+
if err != nil {
1404+
return nil, err
1405+
}
1406+
overClause.OrderByClause = orderBy
1407+
}
1408+
13791409
if p.curTok.Type != TokenRParen {
13801410
return nil, fmt.Errorf("expected ) in OVER clause, got %s", p.curTok.Literal)
13811411
}
13821412
p.nextToken() // consume )
13831413

1384-
fc.OverClause = &ast.OverClause{}
1414+
fc.OverClause = overClause
13851415
}
13861416

13871417
break
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}

0 commit comments

Comments
 (0)