Skip to content

fix(optimizer): don't merge a derived table with a set-returning projection [CLAUDE] - #8323

Open
ebarkhordar wants to merge 1 commit into
tobymao:mainfrom
ebarkhordar:fix/merge-subqueries-set-returning-projection
Open

fix(optimizer): don't merge a derived table with a set-returning projection [CLAUDE]#8323
ebarkhordar wants to merge 1 commit into
tobymao:mainfrom
ebarkhordar:fix/merge-subqueries-set-returning-projection

Conversation

@ebarkhordar

Copy link
Copy Markdown
Contributor

Follow-on from #8314. merge_subqueries has its own copy of the set-returning check one rule later, and it still only matches exp.Explode, so a projection pushdown just kept gets dropped again when the derived table is merged.

SELECT t.a FROM (SELECT a, GENERATE_SERIES(1, 3) AS s FROM x) AS t
main:  SELECT "x"."a" AS "a" FROM "x" AS "x"

INLINE goes the same way now that #8314 made it a UDTF. Widened the guard to exp.UDTF and exp.ExplodingGenerateSeries; Explode is a UDTF so it stays covered. Both cases are in optimizer.sql and fail on main.

I left exp.Anonymous out. Here it would block the merge for every unknown function, which is a lot more expensive than keeping a projection was in pushdown, and it breaks the two FROM_JSON fixtures. So the STACK case from the #8314 review is still broken. Can add it if you'd rather be conservative, that one seems like your call.

make unit is green. Pure Python only, I didn't run make testc.

…ection

The guard in _mergeable only matched exp.Explode, so INLINE and
GENERATE_SERIES projections were dropped when the derived table was
merged, collapsing the row count. Match exp.UDTF and
exp.ExplodingGenerateSeries instead; Explode is a UDTF so it stays
covered.
Comment on lines +78 to +80
# An inner projection of one of these types blocks the merge. A set-returning function
# multiplies the inner rows, so merging drops a projection the outer row count depends on.
UNMERGABLE_PROJECTIONS = (exp.AggFunc, exp.Select, exp.UDTF, exp.ExplodingGenerateSeries)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there a split between this and the constant in pushdown_projections? It seems like the branching is made based on whether we encounter a set-returning function in both (more or less). This is a bit confusing. The fact that we deal with Anonymous differently is also problematic, let's change that to be consistent. The safest of the two is what we already do for pushdown projections, because you can't determine whether an Anonymous function is set-returning.

# title: derived table with INLINE cannot be merged
# dialect: spark
# execute: false
SELECT t.a FROM (SELECT a, INLINE(b) AS s FROM x) AS t;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is invalid Spark SQL, you need two names for INLINE's alias, since it produces two columns. Let's change the fixture to use INLINE(b) AS (c1, c2) or something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants