Skip to content

Commit 5a33943

Browse files
committed
Add APPLY column transformer support for asterisk expressions
- Add APPLY token to lexer - Add Apply field to ast.Asterisk struct - Add parseAsteriskApply function for parsing APPLY(func) and APPLY func syntax - Add APPLY to expression precedence for proper infix parsing - Update explain code to output ColumnsApplyTransformer nodes This fixes 01470_columns_transformers test and many other tests that use APPLY column transformers.
1 parent 43aed1a commit 5a33943

48 files changed

Lines changed: 75 additions & 232 deletions

File tree

Some content is hidden

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

ast/ast.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,7 @@ type Asterisk struct {
11261126
Table string `json:"table,omitempty"` // for table.*
11271127
Except []string `json:"except,omitempty"` // for * EXCEPT (col1, col2)
11281128
Replace []*ReplaceExpr `json:"replace,omitempty"` // for * REPLACE (expr AS col)
1129+
Apply []string `json:"apply,omitempty"` // for * APPLY (func1) APPLY(func2)
11291130
}
11301131

11311132
func (a *Asterisk) Pos() token.Position { return a.Position }

internal/explain/expressions.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,8 +529,8 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) {
529529
}
530530

531531
func explainAsterisk(sb *strings.Builder, n *ast.Asterisk, indent string, depth int) {
532-
// Check if there are any column transformers (EXCEPT, REPLACE)
533-
hasTransformers := len(n.Except) > 0 || len(n.Replace) > 0
532+
// Check if there are any column transformers (EXCEPT, REPLACE, APPLY)
533+
hasTransformers := len(n.Except) > 0 || len(n.Replace) > 0 || len(n.Apply) > 0
534534

535535
if n.Table != "" {
536536
if hasTransformers {
@@ -559,6 +559,8 @@ func explainColumnsTransformers(sb *strings.Builder, n *ast.Asterisk, indent str
559559
if len(n.Replace) > 0 {
560560
transformerCount++
561561
}
562+
// Each APPLY adds one transformer
563+
transformerCount += len(n.Apply)
562564

563565
fmt.Fprintf(sb, "%sColumnsTransformerList (children %d)\n", indent, transformerCount)
564566

@@ -583,6 +585,11 @@ func explainColumnsTransformers(sb *strings.Builder, n *ast.Asterisk, indent str
583585
}
584586
}
585587
}
588+
589+
// Each APPLY function gets its own ColumnsApplyTransformer
590+
for range n.Apply {
591+
fmt.Fprintf(sb, "%s ColumnsApplyTransformer\n", indent)
592+
}
586593
}
587594

588595
func explainColumnsMatcher(sb *strings.Builder, n *ast.ColumnsMatcher, indent string, depth int) {

parser/expression.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func (p *Parser) precedence(tok token.Token) int {
4949
return MUL_PREC
5050
case token.LPAREN, token.LBRACKET:
5151
return CALL
52-
case token.EXCEPT, token.REPLACE:
52+
case token.EXCEPT, token.REPLACE, token.APPLY:
5353
return CALL // For asterisk modifiers
5454
case token.COLONCOLON:
5555
return CALL // Cast operator
@@ -418,6 +418,12 @@ func (p *Parser) parseInfixExpression(left ast.Expression) ast.Expression {
418418
return p.parseAsteriskReplace(asterisk)
419419
}
420420
return left
421+
case token.APPLY:
422+
// Handle * APPLY (func) or * APPLY func
423+
if asterisk, ok := left.(*ast.Asterisk); ok {
424+
return p.parseAsteriskApply(asterisk)
425+
}
426+
return left
421427
case token.NUMBER:
422428
// Handle tuple access like t.1 where .1 is lexed as a number
423429
if strings.HasPrefix(p.current.Value, ".") {
@@ -2387,3 +2393,25 @@ func (p *Parser) parseAsteriskReplace(asterisk *ast.Asterisk) ast.Expression {
23872393

23882394
return asterisk
23892395
}
2396+
2397+
func (p *Parser) parseAsteriskApply(asterisk *ast.Asterisk) ast.Expression {
2398+
p.nextToken() // skip APPLY
2399+
2400+
// APPLY can have optional parentheses: * APPLY(func) or * APPLY func
2401+
hasParens := p.currentIs(token.LPAREN)
2402+
if hasParens {
2403+
p.nextToken() // skip (
2404+
}
2405+
2406+
// Parse function name (can be IDENT or keyword like sum, avg, etc.)
2407+
if p.currentIs(token.IDENT) || p.current.Token.IsKeyword() {
2408+
asterisk.Apply = append(asterisk.Apply, p.current.Value)
2409+
p.nextToken()
2410+
}
2411+
2412+
if hasParens {
2413+
p.expect(token.RPAREN)
2414+
}
2415+
2416+
return asterisk
2417+
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"explain_todo": {
3-
"stmt2": true,
4-
"stmt7": true
3+
"stmt2": true
54
}
65
}
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
{
22
"explain_todo": {
3-
"stmt11": true,
43
"stmt13": true,
54
"stmt17": true,
65
"stmt18": true,
76
"stmt22": true,
87
"stmt23": true,
98
"stmt28": true,
10-
"stmt35": true,
119
"stmt37": true,
1210
"stmt43": true,
13-
"stmt47": true,
1411
"stmt48": true,
1512
"stmt51": true,
16-
"stmt52": true,
1713
"stmt53": true
1814
}
1915
}
Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt14": true,
4-
"stmt21": true,
5-
"stmt6": true,
6-
"stmt8": true
7-
}
8-
}
1+
{}
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt6": true
4-
}
5-
}
1+
{}
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"explain_todo": {
3-
"stmt4": true,
43
"stmt9": true
54
}
65
}

parser/testdata/01048_exists_query/metadata.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"explain_todo": {
33
"stmt22": true,
44
"stmt23": true,
5-
"stmt24": true,
6-
"stmt25": true
5+
"stmt24": true
76
}
87
}

parser/testdata/01110_dictionary_layout_without_arguments/metadata.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"explain_todo": {
3-
"stmt5": true,
43
"stmt7": true,
54
"stmt8": true
65
}

0 commit comments

Comments
 (0)