@@ -165,7 +165,13 @@ func (p *Parser) parseFunctionArgumentList() []ast.Expression {
165165func (p * Parser ) parseImplicitAlias (expr ast.Expression ) ast.Expression {
166166 // If next token is a plain identifier (not a keyword), treat as implicit alias
167167 // Keywords like FROM, WHERE etc. are tokenized as their own token types, not IDENT
168+ // INTERSECT is not a keyword but should not be treated as an alias
168169 if p .currentIs (token .IDENT ) {
170+ upper := strings .ToUpper (p .current .Value )
171+ // Don't consume SQL set operation keywords that aren't tokens
172+ if upper == "INTERSECT" {
173+ return expr
174+ }
169175 alias := p .current .Value
170176 p .nextToken ()
171177
@@ -1709,16 +1715,29 @@ func (p *Parser) parseAsteriskExcept(asterisk *ast.Asterisk) ast.Expression {
17091715func (p * Parser ) parseAsteriskReplace (asterisk * ast.Asterisk ) ast.Expression {
17101716 p .nextToken () // skip REPLACE
17111717
1712- if ! p .expect (token .LPAREN ) {
1713- return asterisk
1718+ // REPLACE can have optional parentheses: REPLACE (expr AS col) or REPLACE expr AS col
1719+ hasParens := p .currentIs (token .LPAREN )
1720+ if hasParens {
1721+ p .nextToken ()
17141722 }
17151723
1716- for ! p .currentIs (token .RPAREN ) && ! p .currentIs (token .EOF ) {
1724+ for {
1725+ // Stop conditions based on context
1726+ if hasParens && p .currentIs (token .RPAREN ) {
1727+ break
1728+ }
1729+ if ! hasParens && (p .currentIs (token .FROM ) || p .currentIs (token .WHERE ) || p .currentIs (token .EOF ) ||
1730+ p .currentIs (token .GROUP ) || p .currentIs (token .ORDER ) || p .currentIs (token .HAVING ) ||
1731+ p .currentIs (token .LIMIT ) || p .currentIs (token .SETTINGS ) || p .currentIs (token .FORMAT ) ||
1732+ p .currentIs (token .UNION ) || p .currentIs (token .EXCEPT ) || p .currentIs (token .COMMA )) {
1733+ break
1734+ }
1735+
17171736 replace := & ast.ReplaceExpr {
17181737 Position : p .current .Pos ,
17191738 }
17201739
1721- replace .Expr = p .parseExpression (LOWEST )
1740+ replace .Expr = p .parseExpression (ALIAS_PREC )
17221741
17231742 if p .currentIs (token .AS ) {
17241743 p .nextToken ()
@@ -1732,10 +1751,18 @@ func (p *Parser) parseAsteriskReplace(asterisk *ast.Asterisk) ast.Expression {
17321751
17331752 if p .currentIs (token .COMMA ) {
17341753 p .nextToken ()
1754+ // If no parens and we see comma, might be end of select column
1755+ if ! hasParens {
1756+ break
1757+ }
1758+ } else if ! hasParens {
1759+ break
17351760 }
17361761 }
17371762
1738- p .expect (token .RPAREN )
1763+ if hasParens {
1764+ p .expect (token .RPAREN )
1765+ }
17391766
17401767 return asterisk
17411768}
0 commit comments