@@ -36,7 +36,7 @@ func (p *Parser) precedence(tok token.Token) int {
3636 case token .NOT :
3737 return NOT_PREC
3838 case token .EQ , token .NEQ , token .LT , token .GT , token .LTE , token .GTE ,
39- token .LIKE , token .ILIKE , token .IN , token .BETWEEN , token .IS ,
39+ token .LIKE , token .ILIKE , token .REGEXP , token . IN , token .BETWEEN , token .IS ,
4040 token .NULL_SAFE_EQ , token .GLOBAL :
4141 return COMPARE
4242 case token .QUESTION :
@@ -101,6 +101,38 @@ func (p *Parser) parseExpressionList() []ast.Expression {
101101 return exprs
102102}
103103
104+ // parseGroupingSets parses GROUPING SETS ((a), (b), (a, b))
105+ func (p * Parser ) parseGroupingSets () []ast.Expression {
106+ var exprs []ast.Expression
107+
108+ if ! p .expect (token .LPAREN ) {
109+ return exprs
110+ }
111+
112+ for ! p .currentIs (token .RPAREN ) && ! p .currentIs (token .EOF ) {
113+ // Each element in GROUPING SETS is a tuple or a single expression
114+ if p .currentIs (token .LPAREN ) {
115+ // Parse as tuple
116+ tuple := p .parseGroupedOrTuple ()
117+ exprs = append (exprs , tuple )
118+ } else {
119+ // Single expression
120+ expr := p .parseExpression (LOWEST )
121+ if expr != nil {
122+ exprs = append (exprs , expr )
123+ }
124+ }
125+
126+ // Skip comma if present
127+ if p .currentIs (token .COMMA ) {
128+ p .nextToken ()
129+ }
130+ }
131+
132+ p .expect (token .RPAREN )
133+ return exprs
134+ }
135+
104136// parseFunctionArgumentList parses arguments for function calls, stopping at SETTINGS
105137func (p * Parser ) parseFunctionArgumentList () []ast.Expression {
106138 var exprs []ast.Expression
@@ -263,8 +295,10 @@ func (p *Parser) parseInfixExpression(left ast.Expression) ast.Expression {
263295 return p .parseTernary (left )
264296 case token .LIKE , token .ILIKE :
265297 return p .parseLikeExpression (left , false )
298+ case token .REGEXP :
299+ return p .parseRegexpExpression (left , false )
266300 case token .NOT :
267- // NOT IN, NOT LIKE, NOT BETWEEN, IS NOT
301+ // NOT IN, NOT LIKE, NOT BETWEEN, NOT REGEXP, IS NOT
268302 p .nextToken ()
269303 switch p .current .Token {
270304 case token .IN :
@@ -273,6 +307,8 @@ func (p *Parser) parseInfixExpression(left ast.Expression) ast.Expression {
273307 return p .parseLikeExpression (left , true )
274308 case token .ILIKE :
275309 return p .parseLikeExpression (left , true )
310+ case token .REGEXP :
311+ return p .parseRegexpExpression (left , true )
276312 case token .BETWEEN :
277313 return p .parseBetweenExpression (left , true )
278314 default :
@@ -674,7 +710,7 @@ func (p *Parser) parseGroupedOrTuple() ast.Expression {
674710 }
675711 }
676712
677- // Check for subquery
713+ // Check for subquery (SELECT, WITH, or EXPLAIN)
678714 if p .currentIs (token .SELECT ) || p .currentIs (token .WITH ) {
679715 subquery := p .parseSelectWithUnion ()
680716 p .expect (token .RPAREN )
@@ -683,6 +719,15 @@ func (p *Parser) parseGroupedOrTuple() ast.Expression {
683719 Query : subquery ,
684720 }
685721 }
722+ // EXPLAIN as subquery
723+ if p .currentIs (token .EXPLAIN ) {
724+ explain := p .parseExplain ()
725+ p .expect (token .RPAREN )
726+ return & ast.Subquery {
727+ Position : pos ,
728+ Query : explain ,
729+ }
730+ }
686731
687732 // Parse first expression
688733 first := p .parseExpression (LOWEST )
@@ -1075,6 +1120,30 @@ func (p *Parser) parseLikeExpression(left ast.Expression, not bool) ast.Expressi
10751120 return expr
10761121}
10771122
1123+ func (p * Parser ) parseRegexpExpression (left ast.Expression , not bool ) ast.Expression {
1124+ pos := p .current .Pos
1125+ p .nextToken () // skip REGEXP
1126+
1127+ pattern := p .parseExpression (COMPARE )
1128+
1129+ // REGEXP translates to match(expr, pattern) function
1130+ fnCall := & ast.FunctionCall {
1131+ Position : pos ,
1132+ Name : "match" ,
1133+ Arguments : []ast.Expression {left , pattern },
1134+ }
1135+
1136+ if not {
1137+ // NOT REGEXP uses NOT match(...)
1138+ return & ast.UnaryExpr {
1139+ Position : pos ,
1140+ Op : "NOT" ,
1141+ Operand : fnCall ,
1142+ }
1143+ }
1144+ return fnCall
1145+ }
1146+
10781147func (p * Parser ) parseInExpression (left ast.Expression , not bool ) ast.Expression {
10791148 expr := & ast.InExpr {
10801149 Position : p .current .Pos ,
@@ -1478,7 +1547,11 @@ func (p *Parser) parseKeywordAsFunction() ast.Expression {
14781547 }
14791548
14801549 var args []ast.Expression
1481- if ! p .currentIs (token .RPAREN ) {
1550+ // Handle view() and similar functions that take a subquery as argument
1551+ if name == "view" && (p .currentIs (token .SELECT ) || p .currentIs (token .WITH )) {
1552+ subquery := p .parseSelectWithUnion ()
1553+ args = []ast.Expression {& ast.Subquery {Position : pos , Query : subquery }}
1554+ } else if ! p .currentIs (token .RPAREN ) {
14821555 args = p .parseExpressionList ()
14831556 }
14841557
0 commit comments