Skip to content

Commit

Permalink
Merge pull request #385 from mindsdb/fix-not-in
Browse files Browse the repository at this point in the history
Fix precedence of 'not in'
  • Loading branch information
ea-rus authored Jul 3, 2024
2 parents 5efa594 + 2862db9 commit 6780409
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 9 deletions.
3 changes: 2 additions & 1 deletion mindsdb_sql/parser/dialects/mindsdb/lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class MindsDBLexer(Lexer):
PLUS, MINUS, DIVIDE, MODULO,
EQUALS, NEQUALS, GREATER, GEQ, LESS, LEQ,
AND, OR, NOT, IS, IS_NOT,
IN, LIKE, NOT_LIKE, CONCAT, BETWEEN, WINDOW, OVER, PARTITION_BY,
IN, NOT_IN, LIKE, NOT_LIKE, CONCAT, BETWEEN, WINDOW, OVER, PARTITION_BY,
JSON_GET, JSON_GET_STR, INTERVAL,

# Data types
Expand Down Expand Up @@ -281,6 +281,7 @@ class MindsDBLexer(Lexer):
OR = r'\bOR\b'
IS_NOT = r'\bIS[\s]+NOT\b'
NOT_LIKE = r'\bNOT[\s]+LIKE\b'
NOT_IN = r'\bNOT[\s]+IN\b'
NOT = r'\bNOT\b'
IS = r'\bIS\b'
LIKE = r'\bLIKE\b'
Expand Down
10 changes: 3 additions & 7 deletions mindsdb_sql/parser/dialects/mindsdb/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class MindsDBParser(Parser):
('left', AND),
('right', UNOT),
('left', EQUALS, NEQUALS),
('nonassoc', LESS, LEQ, GREATER, GEQ, IN, BETWEEN, IS, IS_NOT, NOT_LIKE, LIKE),
('nonassoc', LESS, LEQ, GREATER, GEQ, IN, NOT_IN, BETWEEN, IS, IS_NOT, NOT_LIKE, LIKE),
('left', JSON_GET),
('left', PLUS, MINUS),
('left', STAR, DIVIDE),
Expand Down Expand Up @@ -1407,11 +1407,6 @@ def expr(self, p):
def star(self, p):
return Star()

@_('expr NOT IN expr')
def expr(self, p):
op = p[1] + ' ' + p[2]
return BinaryOperation(op=op, args=(p.expr0, p.expr1))

@_('expr PLUS expr',
'expr MINUS expr',
'expr STAR expr',
Expand All @@ -1435,7 +1430,8 @@ def expr(self, p):
'expr CONCAT expr',
'expr JSON_GET constant',
'expr JSON_GET_STR constant',
'expr IN expr')
'expr NOT_IN expr',
'expr IN expr',)
def expr(self, p):
if hasattr(p, 'LAST'):
arg1 = Last()
Expand Down
22 changes: 21 additions & 1 deletion tests/test_parser/test_base_sql/test_select_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ def test_window_function(self, dialect):
assert str(ast) == str(expected_ast)
assert ast.to_tree() == expected_ast.to_tree()

def test_where_precedence(self, dialect):
def test_is_not_precedence(self, dialect):
query = "select * from t1 where a is not null and b = c"
expected_ast = Select(
targets=[Star()],
Expand Down Expand Up @@ -1036,3 +1036,23 @@ def test_select_left(self):

assert ast.to_tree() == expected_ast.to_tree()
assert str(ast) == str(expected_ast)

def test_not_in_precedence(self):
query = "select * from t1 where a = 1 and b not in (1, 2)"
expected_ast = Select(
targets=[Star()],
from_table=Identifier('t1'),
where=BinaryOperation(op='and', args=[
BinaryOperation(op='=', args=[
Identifier('a'),
Constant(1)
]),
BinaryOperation(op='not in', args=[
Identifier('b'),
Tuple([Constant(1), Constant(2)])
]),
])
)
ast = parse_sql(query)
assert str(ast) == str(expected_ast)
assert ast.to_tree() == expected_ast.to_tree()

0 comments on commit 6780409

Please sign in to comment.