-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CALCITE-4686] SubQueryRemoveRule.matchJoin should correctly rewrite all sub-queries #2385
base: main
Are you sure you want to change the base?
Changes from 1 commit
803d5f0
1940109
932975f
3b244cf
15a833d
f1a714a
f3013ae
3204e0e
6ef7e72
a945fa4
4937fa2
eb46552
9ef2b51
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Turn back on RelOptRulesTest.testExpandJoinIn and testExpandJoinInComposite.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ | |
import org.apache.calcite.rel.core.Project; | ||
import org.apache.calcite.rel.metadata.RelMetadataQuery; | ||
import org.apache.calcite.rex.LogicVisitor; | ||
import org.apache.calcite.rex.RexBuilder; | ||
import org.apache.calcite.rex.RexCorrelVariable; | ||
import org.apache.calcite.rex.RexInputRef; | ||
import org.apache.calcite.rex.RexLiteral; | ||
|
@@ -47,6 +48,7 @@ | |
import org.apache.calcite.util.Util; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.collect.ImmutableSet; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
@@ -638,23 +640,46 @@ private static void matchFilter(SubQueryRemoveRule rule, | |
|
||
private static void matchJoin(SubQueryRemoveRule rule, RelOptRuleCall call) { | ||
final Join join = call.rel(0); | ||
switch (join.getJoinType()) { | ||
case INNER: | ||
case LEFT: | ||
case ANTI: | ||
case SEMI: | ||
break; | ||
default: | ||
//Incorrect queries will be produced for full and right joins. | ||
return; | ||
} | ||
final RexBuilder rexBuilder = call.builder().getRexBuilder(); | ||
final RelBuilder builder = call.builder(); | ||
final RexSubQuery e = | ||
RexUtil.SubQueryFinder.find(join.getCondition()); | ||
assert e != null; | ||
final RelOptUtil.Logic logic = | ||
LogicVisitor.find(RelOptUtil.Logic.TRUE, | ||
ImmutableList.of(join.getCondition()), e); | ||
builder.push(join.getLeft()); | ||
builder.push(join.getRight()); | ||
final int fieldCount = join.getRowType().getFieldCount(); | ||
final Set<CorrelationId> variablesSet = | ||
RelOptUtil.getVariablesUsed(e.rel); | ||
final RexNode target = rule.apply(e, variablesSet, | ||
logic, builder, 2, fieldCount); | ||
final RexShuttle shuttle = new ReplaceSubQueryShuttle(e, target); | ||
builder.join(join.getJoinType(), shuttle.apply(join.getCondition())); | ||
builder.project(fields(builder, join.getRowType().getFieldCount())); | ||
builder | ||
.push(join.getLeft()) | ||
.push(join.getRight()); | ||
CorrelationId id = join.getCluster().createCorrel(); | ||
RexNode condition = RelOptUtil.correlateLeftShiftRight(rexBuilder, | ||
join.getLeft(), id, join.getRight(), join.getCondition()); | ||
boolean found = false; | ||
while (true) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've seen that |
||
final RexSubQuery subQuery = RexUtil.SubQueryFinder.find(condition); | ||
if (subQuery == null) { | ||
assert found; | ||
break; | ||
} | ||
found = true; | ||
final Set<CorrelationId> variablesSet = | ||
RelOptUtil.getVariablesUsed(subQuery.rel); | ||
final RelOptUtil.Logic logic = | ||
LogicVisitor.find(RelOptUtil.Logic.TRUE, ImmutableList.of(condition), subQuery); | ||
int offset = builder.peek().getRowType().getFieldCount(); | ||
final RexNode target = rule.apply(subQuery, variablesSet, logic, | ||
builder, 1, offset); | ||
final RexShuttle shuttle = new ReplaceSubQueryShuttle(subQuery, target); | ||
condition = shuttle.apply(condition); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT: The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am normally not a big fan of final in this localized of context when all variables are treated as immutable, but when some variables are mutated, having final on all the immutable variables signals that the mutable variables are in fact mutable. I will try to shift things to a single where possible. |
||
} | ||
builder | ||
.filter(condition) | ||
.join(join.getJoinType(), rexBuilder.makeLiteral(true), ImmutableSet.of(id)) | ||
.project(fields(builder, join.getRowType().getFieldCount())); | ||
call.transformTo(builder.build()); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we cannot treat
RIGHT
andFULL
outer joins I think it makes sense to skip callingonMatch
method altogether. Is it possible to move the check as rule predicate or apply the check as part ofRelOptRule#matches
?