Skip to content

Commit ed853a7

Browse files
committed
Fix NOT BETWEEN precedence in expression parsing
Infix NOT operators (NOT BETWEEN, NOT IN, NOT LIKE, NOT ILIKE, NOT REGEXP) should have COMPARE precedence (5), not NOT_PREC (4). This allows the parser to correctly parse expressions like `NOT number NOT BETWEEN 4 AND 6` as `NOT (number NOT BETWEEN 4 AND 6)` instead of `(NOT number) NOT BETWEEN 4 AND 6`. Updated precedenceForCurrent() to peek at the next token and return COMPARE precedence when the current token is NOT followed by BETWEEN, IN, LIKE, etc.
1 parent 5ac95e3 commit ed853a7

2 files changed

Lines changed: 10 additions & 5 deletions

File tree

parser/expression.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,19 @@ func (p *Parser) precedence(tok token.Token) int {
6767

6868
// precedenceForCurrent returns the precedence for the current token,
6969
// with special handling for tuple access (number starting with dot)
70+
// and infix NOT operators (NOT BETWEEN, NOT IN, NOT LIKE, etc.)
7071
func (p *Parser) precedenceForCurrent() int {
7172
if p.currentIs(token.NUMBER) && strings.HasPrefix(p.current.Value, ".") {
7273
return HIGHEST // Tuple access like t.1
7374
}
75+
// When NOT is followed by BETWEEN, IN, LIKE, ILIKE, or REGEXP,
76+
// it's an infix operator with COMPARE precedence, not prefix NOT
77+
if p.currentIs(token.NOT) {
78+
if p.peekIs(token.BETWEEN) || p.peekIs(token.IN) || p.peekIs(token.LIKE) ||
79+
p.peekIs(token.ILIKE) || p.peekIs(token.REGEXP) {
80+
return COMPARE
81+
}
82+
}
7483
return p.precedence(p.current.Token)
7584
}
7685

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt3": true
4-
}
5-
}
1+
{}

0 commit comments

Comments
 (0)