Skip to content

Commit 0bc058e

Browse files
committed
Fix IN expression and WITH clause parsing
- Support IN with array literals: `expr IN [1, 2, 3]` - Support IN with identifiers: `expr IN tablename` - Fix function call alias handling to respect expression precedence - Add SETTINGS clause after FORMAT in SELECT - Fix multiple WITH clause elements (comma-separated) This allows parsing queries like: - SELECT 1 IN [1, 2] - WITH toDate('2023-01-09') AS d1, d1 - 1 AS d2 SELECT d1, d2 Test count: 5517 -> 5542 (+25 tests)
1 parent af21faa commit 0bc058e

2 files changed

Lines changed: 32 additions & 16 deletions

File tree

parser/expression.go

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -432,14 +432,8 @@ func (p *Parser) parseFunctionCall(name string, pos token.Position) *ast.Functio
432432
fn.Over = p.parseWindowSpec()
433433
}
434434

435-
// Handle alias
436-
if p.currentIs(token.AS) {
437-
p.nextToken()
438-
if p.currentIs(token.IDENT) {
439-
fn.Alias = p.current.Value
440-
p.nextToken()
441-
}
442-
}
435+
// Note: AS alias is handled by the expression parser's infix handling (parseAlias)
436+
// to respect precedence levels when called from contexts like WITH clauses
443437

444438
return fn
445439
}
@@ -1095,18 +1089,34 @@ func (p *Parser) parseInExpression(left ast.Expression, not bool) ast.Expression
10951089

10961090
p.nextToken() // skip IN
10971091

1098-
if !p.expect(token.LPAREN) {
1099-
return nil
1100-
}
1092+
// Handle different IN list formats:
1093+
// 1. (subquery or list) - standard format
1094+
// 2. [array literal] - array format
1095+
// 3. identifier - table or alias reference
1096+
// 4. tuple(...) - explicit tuple function
11011097

1102-
// Check for subquery
1103-
if p.currentIs(token.SELECT) || p.currentIs(token.WITH) {
1104-
expr.Query = p.parseSelectWithUnion()
1098+
if p.currentIs(token.LPAREN) {
1099+
p.nextToken() // skip (
1100+
// Check for subquery
1101+
if p.currentIs(token.SELECT) || p.currentIs(token.WITH) {
1102+
expr.Query = p.parseSelectWithUnion()
1103+
} else {
1104+
expr.List = p.parseExpressionList()
1105+
}
1106+
p.expect(token.RPAREN)
1107+
} else if p.currentIs(token.LBRACKET) {
1108+
// Array literal: IN [1, 2, 3]
1109+
arr := p.parseArrayLiteral()
1110+
expr.List = []ast.Expression{arr}
11051111
} else {
1106-
expr.List = p.parseExpressionList()
1112+
// Could be identifier, tuple function, or other expression
1113+
// Parse as expression
1114+
innerExpr := p.parseExpression(CALL)
1115+
if innerExpr != nil {
1116+
expr.List = []ast.Expression{innerExpr}
1117+
}
11071118
}
11081119

1109-
p.expect(token.RPAREN)
11101120
return expr
11111121
}
11121122

parser/parser.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,12 @@ func (p *Parser) parseSelect() *ast.SelectQuery {
380380
}
381381
}
382382

383+
// Parse SETTINGS clause (can come after FORMAT)
384+
if p.currentIs(token.SETTINGS) {
385+
p.nextToken()
386+
sel.Settings = p.parseSettingsList()
387+
}
388+
383389
return sel
384390
}
385391

0 commit comments

Comments
 (0)