Skip to content

Commit

Permalink
fix(sql): don't fuse subsequent order by operations
Browse files Browse the repository at this point in the history
  • Loading branch information
kszucs committed Mar 11, 2024
1 parent e943667 commit 6140032
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 5 deletions.
16 changes: 11 additions & 5 deletions ibis/backends/sql/rewrites.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ def dtype(self):
return self.func.dtype


# TODO(kszucs): there is a better strategy to rewrite the relational operations
# to Select nodes by wrapping the leaf nodes in a Select node and then merging
# Project, Filter, Sort, etc. incrementally into the Select node. This way we
# can have tighter control over simplification logic.


@replace(p.Project)
def project_to_select(_, **kwargs):
"""Convert a Project node to a Select node."""
Expand Down Expand Up @@ -164,20 +170,20 @@ def merge_select_select(_, **kwargs):
for v in _.predicates:
if v.find((ops.ExistsSubquery, ops.InSubquery), filter=ops.Value):
return _
# cannot merge if the inner select has different order keys than the outer
if _.sort_keys and _.parent.sort_keys:
return _

subs = {ops.Field(_.parent, k): v for k, v in _.parent.values.items()}
selections = {k: v.replace(subs, filter=ops.Value) for k, v in _.selections.items()}
predicates = tuple(p.replace(subs, filter=ops.Value) for p in _.predicates)
sort_keys = tuple(s.replace(subs, filter=ops.Value) for s in _.sort_keys)

unique_predicates = toolz.unique(_.parent.predicates + predicates)
unique_sort_keys = {s.expr: s for s in _.parent.sort_keys + sort_keys}

return Select(
_.parent.parent,
selections=selections,
predicates=unique_predicates,
sort_keys=unique_sort_keys.values(),
predicates=toolz.unique(_.parent.predicates + predicates),
sort_keys=_.parent.sort_keys + sort_keys,
)


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
SELECT
"t1"."a",
"t1"."b"
FROM (
SELECT
"t0"."a",
"t0"."b"
FROM "t" AS "t0"
ORDER BY
"t0"."a" ASC
) AS "t1"
ORDER BY
"t1"."b" DESC
6 changes: 6 additions & 0 deletions ibis/backends/tests/sql/test_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,12 @@ def test_order_by_expr(snapshot):
snapshot.assert_match(to_sql(expr), "out.sql")


def test_double_order_by_not_fused(snapshot):
t = ibis.table(dict(a="int", b="string"), name="t")
expr = t.order_by(t.a).order_by(t.b.desc())
snapshot.assert_match(to_sql(expr), "out.sql")


def test_no_cartesian_join(snapshot):
customers = ibis.table(
dict(customer_id="int64", first_name="string", last_name="string"),
Expand Down

0 comments on commit 6140032

Please sign in to comment.