silundong commented on code in PR #4619:
URL: https://github.com/apache/calcite/pull/4619#discussion_r2502397497
##########
core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java:
##########
@@ -1056,6 +1057,101 @@ private static void matchJoin(SubQueryRemoveRule rule,
RelOptRuleCall call) {
call.transformTo(builder.build());
}
+ private static void matchFilterEnableMarkJoin(SubQueryRemoveRule rule,
RelOptRuleCall call) {
+ final Filter filter = call.rel(0);
+ final Set<CorrelationId> variablesSet = filter.getVariablesSet();
+ final RelBuilder builder = call.builder();
+ builder.push(filter.getInput());
+ List<RexNode> newCondition
+ = rule.applyEnableMarkJoin(variablesSet,
ImmutableList.of(filter.getCondition()), builder);
+ assert newCondition.size() == 1;
+ builder.filter(newCondition.get(0));
+ builder.project(fields(builder, filter.getRowType().getFieldCount()));
+ call.transformTo(builder.build());
+ }
+
+ private static void matchProjectEnableMarkJoin(SubQueryRemoveRule rule,
RelOptRuleCall call) {
+ final Project project = call.rel(0);
+ final Set<CorrelationId> variablesSet = project.getVariablesSet();
+ final RelBuilder builder = call.builder();
+ builder.push(project.getInput());
+ List<RexNode> newProjects
+ = rule.applyEnableMarkJoin(variablesSet, project.getProjects(),
builder);
+ builder.project(newProjects, project.getRowType().getFieldNames());
+ call.transformTo(builder.build());
+ }
+
+ private List<RexNode> applyEnableMarkJoin(Set<CorrelationId>
variablesSetOfRelNode,
+ List<RexNode> expressions, RelBuilder builder) {
+ List<RexNode> newExpressions = new ArrayList<>(expressions);
+ int count = 0;
+ while (true) {
+ final RexSubQuery e = RexUtil.SubQueryFinder.find(newExpressions);
+ if (e == null) {
+ assert count > 0;
+ break;
+ }
+ ++count;
+ final Set<CorrelationId> variablesSet =
RelOptUtil.getVariablesUsed(e.rel);
+ variablesSet.retainAll(variablesSetOfRelNode);
+
+ RexNode target;
+ switch (e.getKind()) {
+ case EXISTS:
+ case IN:
+ case SOME:
+ target =
+ rewriteToMarkJoin(e, variablesSet, builder,
+ builder.peek().getRowType().getFieldCount());
+ break;
+ case SCALAR_QUERY:
+ target =
+ rewriteScalarQuery(e, variablesSet, builder, 1,
+ builder.peek().getRowType().getFieldCount());
+ break;
+ case ARRAY_QUERY_CONSTRUCTOR:
+ case MAP_QUERY_CONSTRUCTOR:
+ case MULTISET_QUERY_CONSTRUCTOR:
+ target =
+ rewriteCollection(e, variablesSet, builder, 1,
+ builder.peek().getRowType().getFieldCount());
+ break;
+ case UNIQUE:
+ target = rewriteUnique(e, builder);
+ break;
+ default:
+ throw new AssertionError(e.getKind());
+ }
+ final RexShuttle shuttle = new ReplaceSubQueryShuttle(e, target);
+ newExpressions = shuttle.apply(newExpressions);
+ }
+ return newExpressions;
+ }
+
+ private static RexNode rewriteToMarkJoin(RexSubQuery e, Set<CorrelationId>
variablesSet,
+ RelBuilder builder, int offset) {
+ builder.push(e.rel);
+
+ final List<RexNode> rightShiftRef = RexUtil.shift(builder.fields(),
offset);
+ final List<RexNode> externalPredicate = new ArrayList<>();
+ final SqlOperator externalOperator;
+ if (e.getKind() == SqlKind.SOME) {
+ SqlQuantifyOperator op = (SqlQuantifyOperator) e.op;
+ externalOperator = RelOptUtil.op(op.comparisonKind,
SqlStdOperatorTable.EQUALS);
+ } else {
+ externalOperator = SqlStdOperatorTable.EQUALS;
Review Comment:
I did not use SINGLE join. For the rewrite of scalar subqueries, I still
reused the original logic to generate a left join and an aggregate with
single_value function (if necessary).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]