Repository navigation
HIVE-30146: Prevent outer join input swapping in semi-join rule - #6885
ryukobayashi wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
+1, pending tests
@ryukobayashi , please check nothing important in sonar report
| t2 as | ||
| (select stack(4, 1, 1, 3, 4) as (k)) | ||
| select count(*) | ||
| from (select distinct k from t1) a |
There was a problem hiding this comment.
nit: could adding coverage for GROUP BY or UNION (referenced in the story) be beneficial?
There was a problem hiding this comment.
The new testAggregateLeftJoinWithAggregateOnLeftIsNotRewritten covers the Aggregate form: the left input is grouped on the join key, and an Aggregate is placed above the join. UNION is not directly matched by HiveSemiJoinRule, whose operands require a Project or Aggregate directly above the Join. Therefore, I kept this regression test focused on the affected rule shape.
| fixture.getPlanner().setRoot(plan); | ||
| RelNode optimizedPlan = fixture.getPlanner().findBestExp(); | ||
|
|
||
| assertTrue(RelOptUtil.toString(optimizedPlan).contains("HiveSemiJoin")); |
There was a problem hiding this comment.
nit: perhaps more detailed plan validation similarly to
would provide more consistent coverage?There was a problem hiding this comment.
I updated testProjectInnerJoinWithAggregateOnLeftIsRewritten to use assertPlans with explicit pre- and post-optimization plans. The test now validates the complete plan structure, including the join condition and type, the HiveSemiJoin, projections, aggregate, and table scans. This also makes the coverage consistent with TestHiveAntiSemiJoinRule.
|
would it also make sense to add negative tests for RIGHT and FULL joins with an aggregate on the left, grouped on the join key? The ticket says these were never affected because perform() returns early for anything other than INNER or LEFT. The new guard now blocks them one step earlier, in onMatch. Pin both paths so a future change to either can't silently start rewriting these joins. The test could follow the assertUnchanged pattern used by the LEFT tests, with RIGHT and FULL as the join types. Note that the aggregate-on-right case (RIGHT/FULL with the aggregate on the right) is still guarded only by perform()'s early return, since the new check is on the swap rule. A test for that orientation would cover it too. |
|
@konstantinb Thanks for the suggestion. I added regression coverage for I also added coverage for the aggregate-on-right orientation to exercise the existing early return in |
|
|
@deniskuzZ The fixes and tests are complete, could you please check it? |
|
@konstantinb, please review if all your comments were addressed and we could merge |



What changes were proposed in this pull request?
HiveToSemiJoinRuleSwapInputsis intended to swap inputs only forINNER JOINplans that can be converted to a semi-join. However, the rule did not check the join type before swapping inputs.This patch adds an explicit
JoinRelType.INNERcheck before input swapping. It also adds:LEFT JOINandINNER JOINWhy are the changes needed?
Without this check, a
LEFT JOINwith an aggregate on the left side could have its inputs swapped while retaining theLEFTjoin type. The subsequent semi-join rule processing could then remove the original left input, changing the preserved-side semantics and producing incorrect results.For the HIVE-30146 reproduction:
COUNT(*)returned4, and the right-side values were1, 1, 3, 4COUNT(*)returns3, and the right-side values are1, 1, NULLDoes this PR introduce any user-facing change?
Yes. Queries affected by this optimizer rule now return the correct
LEFT JOINresults. There are no SQL syntax, API, or configuration changes.How was this patch tested?
TestHiveSemiJoinRuleLEFT JOINplans are not rewritten by the swapped-input rulesINNER JOINsemi-join conversion still workshive_30146_left_join.qwithTestMiniLlapLocalCliDriver