Skip to content

Commit 6900c56

Browse files
authored
Merge pull request #14 from mindsdb/support-with-rollup
Support WITH ROLLUP
2 parents fd589fd + 639041e commit 6900c56

File tree

5 files changed

+40
-6
lines changed

5 files changed

+40
-6
lines changed

mindsdb_sql_parser/ast/select/identifier.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def get_reserved_words():
3939

4040

4141
class Identifier(ASTNode):
42-
def __init__(self, path_str=None, parts=None, is_outer=False, *args, **kwargs):
42+
def __init__(self, path_str=None, parts=None, is_outer=False, with_rollup=False, *args, **kwargs):
4343
super().__init__(*args, **kwargs)
4444
assert path_str or parts, "Either path_str or parts must be provided for an Identifier"
4545
assert not (path_str and parts), "Provide either path_str or parts, but not both"
@@ -56,6 +56,7 @@ def __init__(self, path_str=None, parts=None, is_outer=False, *args, **kwargs):
5656
self.is_quoted: List[bool] = is_quoted
5757
# used to define type of implicit join in oracle
5858
self.is_outer: bool = is_outer
59+
self.with_rollup: bool = with_rollup
5960

6061
@classmethod
6162
def from_path_str(self, value, *args, **kwargs):

mindsdb_sql_parser/ast/select/select.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def to_tree(self, *args, level=0, **kwargs):
100100
return out_str
101101

102102
def get_string(self, *args, **kwargs):
103-
103+
from mindsdb_sql_parser.ast.select.identifier import Identifier
104104
out_str = ''
105105
if self.cte is not None:
106106
cte_str = ', '.join([out.to_string() for out in self.cte])
@@ -126,7 +126,13 @@ def get_string(self, *args, **kwargs):
126126
out_str += f' WHERE {self.where.to_string()}'
127127

128128
if self.group_by is not None:
129-
group_by_str = ', '.join([out.to_string() for out in self.group_by])
129+
parts = []
130+
for item in self.group_by:
131+
part = item.to_string()
132+
if isinstance(item, Identifier) and item.with_rollup:
133+
part += ' WITH ROLLUP'
134+
parts.append(part)
135+
group_by_str = ', '.join(parts)
130136
out_str += f' GROUP BY {group_by_str}'
131137

132138
if self.having is not None:
@@ -147,7 +153,7 @@ def get_string(self, *args, **kwargs):
147153
out_str += f' {self.mode}'
148154

149155
if self.using is not None:
150-
from mindsdb_sql_parser.ast.select.identifier import Identifier
156+
151157

152158
using_ar = []
153159
for key, value in self.using.items():

mindsdb_sql_parser/lexer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class MindsDBLexer(Lexer):
5151
WITH, SELECT, DISTINCT, FROM, WHERE, AS,
5252
LIMIT, OFFSET, ASC, DESC, NULLS_FIRST, NULLS_LAST,
5353
GROUP_BY, HAVING, ORDER_BY,
54-
STAR, FOR, UPDATE,
54+
STAR, FOR, UPDATE, ROLLUP,
5555

5656
JOIN, INNER, OUTER, CROSS, LEFT, RIGHT, ON, ASOF, LATERAL, IS_OUTER,
5757

@@ -233,6 +233,7 @@ class MindsDBLexer(Lexer):
233233
# FETCH FIRST and FETCH NEXT are the same
234234
FETCH_FIRST = r'\bFETCH[\s](FIRST|NEXT)\b'
235235
ROWS_ONLY = r'\bROWS[\s]ONLY\b'
236+
ROLLUP = r'\bROLLUP\b'
236237

237238
JOIN = r'\bJOIN\b'
238239
INNER = r'\bINNER\b'

mindsdb_sql_parser/parser.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,6 +1775,12 @@ def identifier(self, p):
17751775
def string(self, p):
17761776
return p[0]
17771777

1778+
@_('identifier WITH ROLLUP')
1779+
def identifier(self, p):
1780+
value = p[0]
1781+
value.with_rollup = True
1782+
return value
1783+
17781784
@_('identifier IS_OUTER')
17791785
def identifier(self, p):
17801786
value = p[0]
@@ -1899,6 +1905,9 @@ def function_name(self, p):
18991905
'EVALUATE',
19001906
'DETECTION',
19011907
'JOB',
1908+
'ASOF',
1909+
'LATERAL',
1910+
'ROLLUP',
19021911
# fixme
19031912
# 'EXCEPT',
19041913
# 'INTERSECT',

tests/test_mysql/test_mysql_parser.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from mindsdb_sql_parser import parse_sql
22
from mindsdb_sql_parser.ast import Select, Identifier, BinaryOperation, Star
3-
from mindsdb_sql_parser.ast import Variable
3+
from mindsdb_sql_parser.ast import Variable, Function
44
from mindsdb_sql_parser.parser import Show
55

66

@@ -64,3 +64,20 @@ def test_show_index_from_db(self):
6464
# assert str(ast).lower() == sql.lower()
6565
assert str(ast) == str(expected_ast)
6666
assert ast.to_tree() == expected_ast.to_tree()
67+
68+
def test_with_rollup(self):
69+
sql = "SELECT country, SUM(sales) FROM booksales GROUP BY country WITH ROLLUP"
70+
71+
ast = parse_sql(sql)
72+
expected_ast = Select(
73+
targets=[
74+
Identifier('country'),
75+
Function(op='SUM', args=[Identifier('sales')])
76+
],
77+
from_table=Identifier('booksales'),
78+
group_by=[Identifier('country', with_rollup=True)]
79+
)
80+
81+
assert str(ast).lower() == sql.lower()
82+
assert str(ast) == str(expected_ast)
83+
assert ast.to_tree() == expected_ast.to_tree()

0 commit comments

Comments
 (0)