Skip to content

Commit cc5dba8

Browse files
committed
Refactor!!: remove recursion from optimizer.simplify
1 parent e7a1ad2 commit cc5dba8

File tree

2 files changed

+74
-69
lines changed

2 files changed

+74
-69
lines changed

sqlglot/executor/python.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from sqlglot.executor.context import Context
1010
from sqlglot.executor.env import ENV
1111
from sqlglot.executor.table import RowReader, Table
12-
from sqlglot.helper import csv_reader, ensure_list, subclasses
12+
from sqlglot.helper import csv_reader, subclasses
1313

1414

1515
class PythonExecutor:
@@ -370,8 +370,8 @@ def _rename(self, e):
370370
return self.func(e.key, *values)
371371

372372
if isinstance(e, exp.Func) and e.is_var_len_args:
373-
*head, tail = values
374-
return self.func(e.key, *head, *ensure_list(tail))
373+
args = itertools.chain.from_iterable(x if isinstance(x, list) else [x] for x in values)
374+
return self.func(e.key, *args)
375375

376376
return self.func(e.key, *values)
377377
except Exception as ex:

sqlglot/optimizer/simplify.py

Lines changed: 71 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -61,74 +61,79 @@ def simplify(
6161

6262
dialect = Dialect.get_or_raise(dialect)
6363

64-
def _simplify(expression, root=True):
65-
if (
66-
max_depth
67-
and isinstance(expression, exp.Connector)
68-
and not isinstance(expression.parent, exp.Connector)
69-
):
70-
depth = connector_depth(expression)
71-
if depth > max_depth:
72-
logger.info(
73-
f"Skipping simplification because connector depth {depth} exceeds max {max_depth}"
74-
)
75-
return expression
64+
def _simplify(expression):
65+
stack = []
7666

77-
if expression.meta.get(FINAL):
78-
return expression
67+
for node in expression.dfs(prune=lambda n: n.meta.get(FINAL)):
68+
if node.meta.get(FINAL):
69+
continue
70+
71+
# group by expressions cannot be simplified, for example
72+
# select x + 1 + 1 FROM y GROUP BY x + 1 + 1
73+
# the projection must exactly match the group by key
74+
group = node.args.get("group")
75+
76+
if group and hasattr(node, "selects"):
77+
groups = set(group.expressions)
78+
group.meta[FINAL] = True
79+
80+
for s in node.selects:
81+
for n in s.walk():
82+
if n in groups:
83+
s.meta[FINAL] = True
84+
break
85+
86+
having = node.args.get("having")
87+
if having:
88+
for n in having.walk():
89+
if n in groups:
90+
having.meta[FINAL] = True
91+
break
92+
93+
parent = node.parent
94+
root = node is expression
95+
96+
new_node = rewrite_between(node)
97+
new_node = uniq_sort(new_node, root)
98+
new_node = absorb_and_eliminate(new_node, root)
99+
new_node = simplify_concat(new_node)
100+
new_node = simplify_conditionals(new_node)
101+
102+
if constant_propagation:
103+
new_node = propagate_constants(new_node, root)
104+
105+
if new_node is not node:
106+
node.replace(new_node)
107+
108+
stack.append((new_node, parent))
109+
110+
while stack:
111+
node, parent = stack.pop()
112+
root = node is expression
113+
114+
# Resets parent, arg_key, index pointers
115+
exp.replace_children(node, lambda n: n)
116+
117+
# Post-order transformations
118+
new_node = simplify_not(node)
119+
new_node = flatten(new_node)
120+
new_node = simplify_connectors(new_node, root)
121+
new_node = remove_complements(new_node, root)
122+
new_node = simplify_coalesce(new_node, dialect)
123+
124+
new_node.parent = parent
125+
126+
new_node = simplify_literals(new_node, root)
127+
new_node = simplify_equality(new_node)
128+
new_node = simplify_parens(new_node)
129+
new_node = simplify_datetrunc(new_node, dialect)
130+
new_node = sort_comparison(new_node)
131+
new_node = simplify_startswith(new_node)
132+
133+
if new_node is not node:
134+
node.replace(new_node)
79135

80-
# group by expressions cannot be simplified, for example
81-
# select x + 1 + 1 FROM y GROUP BY x + 1 + 1
82-
# the projection must exactly match the group by key
83-
group = expression.args.get("group")
84-
85-
if group and hasattr(expression, "selects"):
86-
groups = set(group.expressions)
87-
group.meta[FINAL] = True
88-
89-
for e in expression.selects:
90-
for node in e.walk():
91-
if node in groups:
92-
e.meta[FINAL] = True
93-
break
94-
95-
having = expression.args.get("having")
96-
if having:
97-
for node in having.walk():
98-
if node in groups:
99-
having.meta[FINAL] = True
100-
break
101-
102-
# Pre-order transformations
103-
node = expression
104-
node = rewrite_between(node)
105-
node = uniq_sort(node, root)
106-
node = absorb_and_eliminate(node, root)
107-
node = simplify_concat(node)
108-
node = simplify_conditionals(node)
109-
110-
if constant_propagation:
111-
node = propagate_constants(node, root)
112-
113-
exp.replace_children(node, lambda e: _simplify(e, False))
114-
115-
# Post-order transformations
116-
node = simplify_not(node)
117-
node = flatten(node)
118-
node = simplify_connectors(node, root)
119-
node = remove_complements(node, root)
120-
node = simplify_coalesce(node, dialect)
121-
node.parent = expression.parent
122-
node = simplify_literals(node, root)
123-
node = simplify_equality(node)
124-
node = simplify_parens(node)
125-
node = simplify_datetrunc(node, dialect)
126-
node = sort_comparison(node)
127-
node = simplify_startswith(node)
128-
129-
if root:
130-
expression.replace(node)
131-
return node
136+
return new_node
132137

133138
expression = while_changing(expression, _simplify)
134139
remove_where_true(expression)

0 commit comments

Comments
 (0)