org.apache.calcite.rel.core.Correlate Java Examples
The following examples show how to use
org.apache.calcite.rel.core.Correlate.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: RelMetadataTest.java From calcite with Apache License 2.0 | 6 votes |
@Test void testCorrelateUniqueKeys() { final String sql = "select *\n" + "from (select distinct deptno from emp) as e,\n" + " lateral (\n" + " select * from dept where dept.deptno = e.deptno)"; final RelNode rel = convertSql(sql); final RelMetadataQuery mq = rel.getCluster().getMetadataQuery(); assertThat(rel, isA((Class) Project.class)); final Project project = (Project) rel; final Set<ImmutableBitSet> result = mq.getUniqueKeys(project); assertThat(result, sortsAs("[{0}]")); if (false) { assertUniqueConsistent(project); } assertThat(project.getInput(), isA((Class) Correlate.class)); final Correlate correlate = (Correlate) project.getInput(); final Set<ImmutableBitSet> result2 = mq.getUniqueKeys(correlate); assertThat(result2, sortsAs("[{0}]")); if (false) { assertUniqueConsistent(correlate); } }
Example #2
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 6 votes |
private Function2<RelNode, RelNode, Void> createCopyHook() { return (oldNode, newNode) -> { if (cm.mapRefRelToCorRef.containsKey(oldNode)) { cm.mapRefRelToCorRef.putAll(newNode, cm.mapRefRelToCorRef.get(oldNode)); } if (oldNode instanceof Correlate && newNode instanceof Correlate) { Correlate oldCor = (Correlate) oldNode; CorrelationId c = oldCor.getCorrelationId(); if (cm.mapCorToCorRel.get(c) == oldNode) { cm.mapCorToCorRel.put(c, newNode); } if (generatedCorRels.contains(oldNode)) { generatedCorRels.add((Correlate) newNode); } } return null; }; }
Example #3
Source File: RelToSqlConverter.java From calcite with Apache License 2.0 | 6 votes |
/** @see #dispatch */ public Result visit(Correlate e) { final Result leftResult = visitChild(0, e.getLeft()) .resetAlias(e.getCorrelVariable(), e.getRowType()); parseCorrelTable(e, leftResult); final Result rightResult = visitChild(1, e.getRight()); final SqlNode rightLateral = SqlStdOperatorTable.LATERAL.createCall(POS, rightResult.node); final SqlNode rightLateralAs = SqlStdOperatorTable.AS.createCall(POS, rightLateral, new SqlIdentifier(rightResult.neededAlias, POS)); final SqlNode join = new SqlJoin(POS, leftResult.asFrom(), SqlLiteral.createBoolean(false, POS), JoinType.COMMA.symbol(POS), rightLateralAs, JoinConditionType.NONE.symbol(POS), null); return result(join, leftResult, rightResult); }
Example #4
Source File: FilterCorrelateRule.java From Bats with Apache License 2.0 | 5 votes |
/** * Creates a FilterCorrelateRule. */ public FilterCorrelateRule(RelBuilderFactory builderFactory) { super( operand(Filter.class, operand(Correlate.class, RelOptRule.any())), builderFactory, "FilterCorrelateRule"); }
Example #5
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 5 votes |
@Override public RelNode visit(RelNode other) { if (other instanceof Join) { Join join = (Join) other; try { stack.push(join); join.getCondition().accept(rexVisitor(join)); } finally { stack.pop(); } return visitJoin(join); } else if (other instanceof Correlate) { Correlate correlate = (Correlate) other; mapCorToCorRel.put(correlate.getCorrelationId(), correlate); return visitJoin(correlate); } else if (other instanceof Filter) { Filter filter = (Filter) other; try { stack.push(filter); filter.getCondition().accept(rexVisitor(filter)); } finally { stack.pop(); } } else if (other instanceof Project) { Project project = (Project) other; try { stack.push(project); for (RexNode node : project.getProjects()) { node.accept(rexVisitor(project)); } } finally { stack.pop(); } } return super.visit(other); }
Example #6
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 5 votes |
AdjustProjectForCountAggregateRule(boolean flavor, RelBuilderFactory relBuilderFactory) { super( flavor ? operand(Correlate.class, operand(RelNode.class, any()), operand(Project.class, operand(Aggregate.class, any()))) : operand(Correlate.class, operand(RelNode.class, any()), operand(Aggregate.class, any())), relBuilderFactory, null); this.flavor = flavor; }
Example #7
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 5 votes |
RemoveCorrelationForScalarAggregateRule(RelBuilderFactory relBuilderFactory) { super( operand(Correlate.class, operand(RelNode.class, any()), operand(Project.class, operandJ(Aggregate.class, null, Aggregate::isSimple, operand(Project.class, operand(RelNode.class, any()))))), relBuilderFactory, null); }
Example #8
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 5 votes |
RemoveCorrelationForScalarProjectRule(RelBuilderFactory relBuilderFactory) { super( operand(Correlate.class, operand(RelNode.class, any()), operand(Aggregate.class, operand(Project.class, operand(RelNode.class, any())))), relBuilderFactory, null); }
Example #9
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 5 votes |
@Override public RexNode visitInputRef(RexInputRef inputRef) { if (currentRel instanceof Correlate) { // if this rel references corVar // and now it needs to be rewritten // it must have been pulled above the Correlate // replace the input ref to account for the LHS of the // Correlate final int leftInputFieldCount = ((Correlate) currentRel).getLeft().getRowType() .getFieldCount(); RelDataType newType = inputRef.getType(); if (projectPulledAboveLeftCorrelator) { newType = typeFactory.createTypeWithNullability(newType, true); } int pos = inputRef.getIndex(); RexInputRef newInputRef = new RexInputRef(leftInputFieldCount + pos, newType); if ((isCount != null) && isCount.contains(pos)) { return createCaseExpression( newInputRef, rexBuilder.makeExactLiteral(BigDecimal.ZERO), newInputRef); } else { return newInputRef; } } return inputRef; }
Example #10
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 5 votes |
/** * Pulls a {@link Project} above a {@link Correlate} from its RHS input. * Enforces nullability for join output. * * @param correlate Correlate * @param project the original project as the RHS input of the join * @param isCount Positions which are calls to the <code>COUNT</code> * aggregation function * @return the subtree with the new Project at the root */ private RelNode aggregateCorrelatorOutput( Correlate correlate, Project project, Set<Integer> isCount) { final RelNode left = correlate.getLeft(); final JoinRelType joinType = correlate.getJoinType(); // now create the new project final List<Pair<RexNode, String>> newProjects = new ArrayList<>(); // Project everything from the LHS and then those from the original // project final List<RelDataTypeField> leftInputFields = left.getRowType().getFieldList(); for (int i = 0; i < leftInputFields.size(); i++) { newProjects.add(RexInputRef.of2(i, leftInputFields)); } // Marked where the projected expr is coming from so that the types will // become nullable for the original projections which are now coming out // of the nullable side of the OJ. boolean projectPulledAboveLeftCorrelator = joinType.generatesNullsOnRight(); for (Pair<RexNode, String> pair : project.getNamedProjects()) { RexNode newProjExpr = removeCorrelationExpr( pair.left, projectPulledAboveLeftCorrelator, isCount); newProjects.add(Pair.of(newProjExpr, pair.right)); } return relBuilder.push(correlate) .projectNamed(Pair.left(newProjects), Pair.right(newProjects), true) .build(); }
Example #11
Source File: ProjectCorrelateTransposeRule.java From calcite with Apache License 2.0 | 5 votes |
public ProjectCorrelateTransposeRule( PushProjector.ExprCondition preserveExprCondition, RelBuilderFactory relFactory) { super( operand(Project.class, operand(Correlate.class, any())), relFactory, null); this.preserveExprCondition = preserveExprCondition; }
Example #12
Source File: FilterCorrelateRule.java From calcite with Apache License 2.0 | 5 votes |
/** * Creates a FilterCorrelateRule. */ public FilterCorrelateRule(RelBuilderFactory builderFactory) { super( operand(Filter.class, operand(Correlate.class, RelOptRule.any())), builderFactory, "FilterCorrelateRule"); }
Example #13
Source File: PostOrderRelNodeVisitor.java From streamline with Apache License 2.0 | 5 votes |
public final T traverse(RelNode n) throws Exception { List<T> inputStreams = new ArrayList<>(); for (RelNode input : n.getInputs()) { inputStreams.add(traverse(input)); } if (n instanceof Aggregate) { return visitAggregate((Aggregate) n, inputStreams); } else if (n instanceof Calc) { return visitCalc((Calc) n, inputStreams); } else if (n instanceof Collect) { return visitCollect((Collect) n, inputStreams); } else if (n instanceof Correlate) { return visitCorrelate((Correlate) n, inputStreams); } else if (n instanceof Delta) { return visitDelta((Delta) n, inputStreams); } else if (n instanceof Exchange) { return visitExchange((Exchange) n, inputStreams); } else if (n instanceof Project) { return visitProject((Project) n, inputStreams); } else if (n instanceof Filter) { return visitFilter((Filter) n, inputStreams); } else if (n instanceof Sample) { return visitSample((Sample) n, inputStreams); } else if (n instanceof Sort) { return visitSort((Sort) n, inputStreams); } else if (n instanceof TableModify) { return visitTableModify((TableModify) n, inputStreams); } else if (n instanceof TableScan) { return visitTableScan((TableScan) n, inputStreams); } else if (n instanceof Uncollect) { return visitUncollect((Uncollect) n, inputStreams); } else if (n instanceof Window) { return visitWindow((Window) n, inputStreams); } else if (n instanceof Join) { return visitJoin((Join) n, inputStreams); } else { return defaultValue(n, inputStreams); } }
Example #14
Source File: RelDecorrelator.java From flink with Apache License 2.0 | 5 votes |
/** * Pulls a {@link Project} above a {@link Correlate} from its RHS input. * Enforces nullability for join output. * * @param correlate Correlate * @param project the original project as the RHS input of the join * @param isCount Positions which are calls to the <code>COUNT</code> * aggregation function * @return the subtree with the new Project at the root */ private RelNode aggregateCorrelatorOutput( Correlate correlate, LogicalProject project, Set<Integer> isCount) { final RelNode left = correlate.getLeft(); final JoinRelType joinType = correlate.getJoinType(); // now create the new project final List<Pair<RexNode, String>> newProjects = new ArrayList<>(); // Project everything from the LHS and then those from the original // project final List<RelDataTypeField> leftInputFields = left.getRowType().getFieldList(); for (int i = 0; i < leftInputFields.size(); i++) { newProjects.add(RexInputRef.of2(i, leftInputFields)); } // Marked where the projected expr is coming from so that the types will // become nullable for the original projections which are now coming out // of the nullable side of the OJ. boolean projectPulledAboveLeftCorrelator = joinType.generatesNullsOnRight(); for (Pair<RexNode, String> pair : project.getNamedProjects()) { RexNode newProjExpr = removeCorrelationExpr( pair.left, projectPulledAboveLeftCorrelator, isCount); newProjects.add(Pair.of(newProjExpr, pair.right)); } return relBuilder.push(correlate) .projectNamed(Pair.left(newProjects), Pair.right(newProjects), true) .build(); }
Example #15
Source File: RelDecorrelator.java From flink with Apache License 2.0 | 5 votes |
/** * Pulls a {@link Project} above a {@link Correlate} from its RHS input. * Enforces nullability for join output. * * @param correlate Correlate * @param project the original project as the RHS input of the join * @param isCount Positions which are calls to the <code>COUNT</code> * aggregation function * @return the subtree with the new Project at the root */ private RelNode aggregateCorrelatorOutput( Correlate correlate, LogicalProject project, Set<Integer> isCount) { final RelNode left = correlate.getLeft(); final JoinRelType joinType = correlate.getJoinType(); // now create the new project final List<Pair<RexNode, String>> newProjects = new ArrayList<>(); // Project everything from the LHS and then those from the original // project final List<RelDataTypeField> leftInputFields = left.getRowType().getFieldList(); for (int i = 0; i < leftInputFields.size(); i++) { newProjects.add(RexInputRef.of2(i, leftInputFields)); } // Marked where the projected expr is coming from so that the types will // become nullable for the original projections which are now coming out // of the nullable side of the OJ. boolean projectPulledAboveLeftCorrelator = joinType.generatesNullsOnRight(); for (Pair<RexNode, String> pair : project.getNamedProjects()) { RexNode newProjExpr = removeCorrelationExpr( pair.left, projectPulledAboveLeftCorrelator, isCount); newProjects.add(Pair.of(newProjExpr, pair.right)); } return relBuilder.push(correlate) .projectNamed(Pair.left(newProjects), Pair.right(newProjects), true) .build(); }
Example #16
Source File: RelDecorrelator.java From Bats with Apache License 2.0 | 5 votes |
/** * Pulls a {@link Project} above a {@link Correlate} from its RHS input. * Enforces nullability for join output. * * @param correlate Correlate * @param project the original project as the RHS input of the join * @param isCount Positions which are calls to the <code>COUNT</code> * aggregation function * @return the subtree with the new Project at the root */ private RelNode aggregateCorrelatorOutput(Correlate correlate, LogicalProject project, Set<Integer> isCount) { final RelNode left = correlate.getLeft(); final JoinRelType joinType = correlate.getJoinType().toJoinType(); // now create the new project final List<Pair<RexNode, String>> newProjects = new ArrayList<>(); // Project everything from the LHS and then those from the original // project final List<RelDataTypeField> leftInputFields = left.getRowType().getFieldList(); for (int i = 0; i < leftInputFields.size(); i++) { newProjects.add(RexInputRef.of2(i, leftInputFields)); } // Marked where the projected expr is coming from so that the types will // become nullable for the original projections which are now coming out // of the nullable side of the OJ. boolean projectPulledAboveLeftCorrelator = joinType.generatesNullsOnRight(); for (Pair<RexNode, String> pair : project.getNamedProjects()) { RexNode newProjExpr = removeCorrelationExpr(pair.left, projectPulledAboveLeftCorrelator, isCount); newProjects.add(Pair.of(newProjExpr, pair.right)); } return relBuilder.push(correlate).projectNamed(Pair.left(newProjects), Pair.right(newProjects), true).build(); }
Example #17
Source File: DrillProjectLateralJoinTransposeRule.java From Bats with Apache License 2.0 | 5 votes |
@Override public boolean matches(RelOptRuleCall call) { Correlate correlate = call.rel(1); // No need to call ProjectCorrelateTransposeRule if the current lateralJoin contains excludeCorrelationColumn set to true. // This is needed as the project push into Lateral join rule changes the output row type which will fail assertions in ProjectCorrelateTransposeRule. if (correlate instanceof DrillLateralJoinRel && ((DrillLateralJoinRel)correlate).excludeCorrelateColumn) { return false; } return true; }
Example #18
Source File: LateralJoinPrel.java From Bats with Apache License 2.0 | 5 votes |
@Override public Correlate copy(RelTraitSet traitSet, RelNode left, RelNode right, CorrelationId correlationId, ImmutableBitSet requiredColumns, SemiJoinType joinType) { return new LateralJoinPrel(this.getCluster(), this.getTraitSet(), left, right, this.excludeCorrelateColumn, correlationId, requiredColumns, this.getJoinType()); }
Example #19
Source File: CorrelateRel.java From dremio-oss with Apache License 2.0 | 5 votes |
@Override public Correlate copy(RelTraitSet traitSet, RelNode left, RelNode right, CorrelationId correlationId, ImmutableBitSet requiredColumns, SemiJoinType joinType) { return new CorrelateRel(getCluster(), traitSet, left, right, correlationId, requiredColumns, joinType); }
Example #20
Source File: DrillLateralJoinRel.java From Bats with Apache License 2.0 | 5 votes |
@Override public Correlate copy(RelTraitSet traitSet, RelNode left, RelNode right, CorrelationId correlationId, ImmutableBitSet requiredColumns, SemiJoinType joinType) { return new DrillLateralJoinRel(this.getCluster(), this.getTraitSet(), left, right, this.excludeCorrelateColumn, correlationId, requiredColumns, this.getJoinType()); }
Example #21
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 4 votes |
public Frame decorrelateRel(LogicalCorrelate rel) { return decorrelateRel((Correlate) rel); }
Example #22
Source File: RelMdUniqueKeys.java From Bats with Apache License 2.0 | 4 votes |
public Set<ImmutableBitSet> getUniqueKeys(Correlate rel, RelMetadataQuery mq, boolean ignoreNulls) { return mq.getUniqueKeys(rel.getLeft(), ignoreNulls); }
Example #23
Source File: SqlToRelTestBase.java From calcite with Apache License 2.0 | 4 votes |
@Override public Correlate copy(RelTraitSet traitSet, RelNode left, RelNode right, CorrelationId correlationId, ImmutableBitSet requiredColumns, JoinRelType joinType) { return new CustomCorrelate(getCluster(), traitSet, left, right, correlationId, requiredColumns, joinType); }
Example #24
Source File: FilterCorrelateRule.java From Bats with Apache License 2.0 | 4 votes |
public void onMatch(RelOptRuleCall call) { final Filter filter = call.rel(0); final Correlate corr = call.rel(1); final List<RexNode> aboveFilters = RelOptUtil.conjunctions(filter.getCondition()); final List<RexNode> leftFilters = new ArrayList<>(); final List<RexNode> rightFilters = new ArrayList<>(); // Try to push down above filters. These are typically where clause // filters. They can be pushed down if they are not on the NULL // generating side. RelOptUtil.classifyFilters( corr, aboveFilters, JoinRelType.INNER, false, !corr.getJoinType().toJoinType().generatesNullsOnLeft(), !corr.getJoinType().toJoinType().generatesNullsOnRight(), aboveFilters, leftFilters, rightFilters); if (leftFilters.isEmpty() && rightFilters.isEmpty()) { // no filters got pushed return; } // Create Filters on top of the children if any filters were // pushed to them. final RexBuilder rexBuilder = corr.getCluster().getRexBuilder(); final RelBuilder relBuilder = call.builder(); final RelNode leftRel = relBuilder.push(corr.getLeft()).filter(leftFilters).build(); final RelNode rightRel = relBuilder.push(corr.getRight()).filter(rightFilters).build(); // Create the new Correlate RelNode newCorrRel = corr.copy(corr.getTraitSet(), ImmutableList.of(leftRel, rightRel)); call.getPlanner().onCopy(corr, newCorrRel); if (!leftFilters.isEmpty()) { call.getPlanner().onCopy(filter, leftRel); } if (!rightFilters.isEmpty()) { call.getPlanner().onCopy(filter, rightRel); } // Create a Filter on top of the join if needed relBuilder.push(newCorrRel); relBuilder.filter( RexUtil.fixUp(rexBuilder, aboveFilters, RelOptUtil.getFieldTypeList(relBuilder.peek().getRowType()))); call.transformTo(relBuilder.build()); }
Example #25
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 4 votes |
private void onMatch2( RelOptRuleCall call, Correlate correlate, RelNode leftInput, Project aggOutputProject, Aggregate aggregate) { if (generatedCorRels.contains(correlate)) { // This Correlate was generated by a previous invocation of // this rule. No further work to do. return; } setCurrent(call.getPlanner().getRoot(), correlate); // check for this pattern // The pattern matching could be simplified if rules can be applied // during decorrelation, // // CorrelateRel(left correlation, condition = true) // leftInput // Project-A (a RexNode) // Aggregate (groupby (0), agg0(), agg1()...) // check aggOutputProj projects only one expression List<RexNode> aggOutputProjExprs = aggOutputProject.getProjects(); if (aggOutputProjExprs.size() != 1) { return; } JoinRelType joinType = correlate.getJoinType(); // corRel.getCondition was here, however Correlate was updated so it // never includes a join condition. The code was not modified for brevity. RexNode joinCond = relBuilder.literal(true); if ((joinType != JoinRelType.LEFT) || (joinCond != relBuilder.literal(true))) { return; } // check that the agg is on the entire input if (!aggregate.getGroupSet().isEmpty()) { return; } List<AggregateCall> aggCalls = aggregate.getAggCallList(); Set<Integer> isCount = new HashSet<>(); // remember the count() positions int i = -1; for (AggregateCall aggCall : aggCalls) { ++i; if (aggCall.getAggregation() instanceof SqlCountAggFunction) { isCount.add(i); } } // now rewrite the plan to // // Project-A' (all LHS plus transformed original projections, // replacing references to count() with case statement) // Correlate(left correlation, condition = true) // leftInput // Aggregate(groupby (0), agg0(), agg1()...) // List<RexNode> requiredNodes = correlate.getRequiredColumns().asList().stream() .map(ord -> relBuilder.getRexBuilder().makeInputRef(correlate, ord)) .collect(Collectors.toList()); Correlate newCorrelate = (Correlate) relBuilder.push(leftInput) .push(aggregate).correlate(correlate.getJoinType(), correlate.getCorrelationId(), requiredNodes).build(); // remember this rel so we don't fire rule on it again // REVIEW jhyde 29-Oct-2007: rules should not save state; rule // should recognize patterns where it does or does not need to do // work generatedCorRels.add(newCorrelate); // need to update the mapCorToCorRel Update the output position // for the corVars: only pass on the corVars that are not used in // the join key. if (cm.mapCorToCorRel.get(correlate.getCorrelationId()) == correlate) { cm.mapCorToCorRel.put(correlate.getCorrelationId(), newCorrelate); } RelNode newOutput = aggregateCorrelatorOutput(newCorrelate, aggOutputProject, isCount); call.transformTo(newOutput); }
Example #26
Source File: ProjectCorrelateTransposeRule.java From Bats with Apache License 2.0 | 4 votes |
public ProjectCorrelateTransposeRule(PushProjector.ExprCondition preserveExprCondition, RelBuilderFactory relFactory) { super(operand(Project.class, operand(Correlate.class, any())), relFactory, null); this.preserveExprCondition = preserveExprCondition; }
Example #27
Source File: ProjectCorrelateTransposeRule.java From Bats with Apache License 2.0 | 4 votes |
@Override public void onMatch(RelOptRuleCall call) { Project origProj = call.rel(0); final Correlate corr = call.rel(1); // locate all fields referenced in the projection // determine which inputs are referenced in the projection; // if all fields are being referenced and there are no // special expressions, no point in proceeding any further PushProjector pushProject = new PushProjector(origProj, call.builder().literal(true), corr, preserveExprCondition, call.builder()); if (pushProject.locateAllRefs()) { return; } // create left and right projections, projecting only those // fields referenced on each side RelNode leftProjRel = pushProject.createProjectRefsAndExprs(corr.getLeft(), true, false); RelNode rightProjRel = pushProject.createProjectRefsAndExprs(corr.getRight(), true, true); Map<Integer, Integer> requiredColsMap = new HashMap<>(); // adjust requiredColumns that reference the projected columns int[] adjustments = pushProject.getAdjustments(); BitSet updatedBits = new BitSet(); for (Integer col : corr.getRequiredColumns()) { int newCol = col + adjustments[col]; updatedBits.set(newCol); requiredColsMap.put(col, newCol); } RexBuilder rexBuilder = call.builder().getRexBuilder(); CorrelationId correlationId = corr.getCluster().createCorrel(); RexCorrelVariable rexCorrel = (RexCorrelVariable) rexBuilder.makeCorrel(leftProjRel.getRowType(), correlationId); // updates RexCorrelVariable and sets actual RelDataType for RexFieldAccess rightProjRel = rightProjRel.accept(new RelNodesExprsHandler( new RexFieldAccessReplacer(corr.getCorrelationId(), rexCorrel, rexBuilder, requiredColsMap))); // create a new correlate with the projected children Correlate newCorrRel = corr.copy(corr.getTraitSet(), leftProjRel, rightProjRel, correlationId, ImmutableBitSet.of(BitSets.toIter(updatedBits)), corr.getJoinType()); // put the original project on top of the correlate, converting it to // reference the modified projection list RelNode topProject = pushProject.createNewProject(newCorrRel, adjustments); call.transformTo(topProject); }
Example #28
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 4 votes |
/** * Remove correlated variables from the tree at root corRel * * @param correlate Correlate */ private void removeCorVarFromTree(Correlate correlate) { if (cm.mapCorToCorRel.get(correlate.getCorrelationId()) == correlate) { cm.mapCorToCorRel.remove(correlate.getCorrelationId()); } }
Example #29
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 4 votes |
/** * Checks whether the correlations in projRel and filter are related to * the correlated variables provided by corRel. * * @param correlate Correlate * @param project The original Project as the RHS input of the join * @param filter Filter * @param correlatedJoinKeys Correlated join keys * @return true if filter and proj only references corVar provided by corRel */ private boolean checkCorVars( Correlate correlate, Project project, Filter filter, List<RexFieldAccess> correlatedJoinKeys) { if (filter != null) { assert correlatedJoinKeys != null; // check that all correlated refs in the filter condition are // used in the join(as field access). Set<CorRef> corVarInFilter = Sets.newHashSet(cm.mapRefRelToCorRef.get(filter)); for (RexFieldAccess correlatedJoinKey : correlatedJoinKeys) { corVarInFilter.remove(cm.mapFieldAccessToCorRef.get(correlatedJoinKey)); } if (!corVarInFilter.isEmpty()) { return false; } // Check that the correlated variables referenced in these // comparisons do come from the Correlate. corVarInFilter.addAll(cm.mapRefRelToCorRef.get(filter)); for (CorRef corVar : corVarInFilter) { if (cm.mapCorToCorRel.get(corVar.corr) != correlate) { return false; } } } // if project has any correlated reference, make sure they are also // provided by the current correlate. They will be projected out of the LHS // of the correlate. if ((project != null) && cm.mapRefRelToCorRef.containsKey(project)) { for (CorRef corVar : cm.mapRefRelToCorRef.get(project)) { if (cm.mapCorToCorRel.get(corVar.corr) != correlate) { return false; } } } return true; }
Example #30
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 4 votes |
public Frame decorrelateRel(Correlate rel) { // // Rewrite logic: // // The original left input will be joined with the new right input that // has generated correlated variables propagated up. For any generated // corVars that are not used in the join key, pass them along to be // joined later with the Correlates that produce them. // // the right input to Correlate should produce correlated variables final RelNode oldLeft = rel.getInput(0); final RelNode oldRight = rel.getInput(1); final Frame leftFrame = getInvoke(oldLeft, rel); final Frame rightFrame = getInvoke(oldRight, rel); if (leftFrame == null || rightFrame == null) { // If any input has not been rewritten, do not rewrite this rel. return null; } if (rightFrame.corDefOutputs.isEmpty()) { return null; } assert rel.getRequiredColumns().cardinality() <= rightFrame.corDefOutputs.keySet().size(); // Change correlator rel into a join. // Join all the correlated variables produced by this correlator rel // with the values generated and propagated from the right input final SortedMap<CorDef, Integer> corDefOutputs = new TreeMap<>(rightFrame.corDefOutputs); final List<RexNode> conditions = new ArrayList<>(); final List<RelDataTypeField> newLeftOutput = leftFrame.r.getRowType().getFieldList(); int newLeftFieldCount = newLeftOutput.size(); final List<RelDataTypeField> newRightOutput = rightFrame.r.getRowType().getFieldList(); for (Map.Entry<CorDef, Integer> rightOutput : new ArrayList<>(corDefOutputs.entrySet())) { final CorDef corDef = rightOutput.getKey(); if (!corDef.corr.equals(rel.getCorrelationId())) { continue; } final int newLeftPos = leftFrame.oldToNewOutputs.get(corDef.field); final int newRightPos = rightOutput.getValue(); conditions.add( relBuilder.call(SqlStdOperatorTable.EQUALS, RexInputRef.of(newLeftPos, newLeftOutput), new RexInputRef(newLeftFieldCount + newRightPos, newRightOutput.get(newRightPos).getType()))); // remove this corVar from output position mapping corDefOutputs.remove(corDef); } // Update the output position for the corVars: only pass on the cor // vars that are not used in the join key. for (CorDef corDef : corDefOutputs.keySet()) { int newPos = corDefOutputs.get(corDef) + newLeftFieldCount; corDefOutputs.put(corDef, newPos); } // then add any corVar from the left input. Do not need to change // output positions. corDefOutputs.putAll(leftFrame.corDefOutputs); // Create the mapping between the output of the old correlation rel // and the new join rel final Map<Integer, Integer> mapOldToNewOutputs = new HashMap<>(); int oldLeftFieldCount = oldLeft.getRowType().getFieldCount(); int oldRightFieldCount = oldRight.getRowType().getFieldCount(); //noinspection AssertWithSideEffects assert rel.getRowType().getFieldCount() == oldLeftFieldCount + oldRightFieldCount; // Left input positions are not changed. mapOldToNewOutputs.putAll(leftFrame.oldToNewOutputs); // Right input positions are shifted by newLeftFieldCount. for (int i = 0; i < oldRightFieldCount; i++) { mapOldToNewOutputs.put(i + oldLeftFieldCount, rightFrame.oldToNewOutputs.get(i) + newLeftFieldCount); } final RexNode condition = RexUtil.composeConjunction(relBuilder.getRexBuilder(), conditions); RelNode newJoin = relBuilder.push(leftFrame.r).push(rightFrame.r) .join(rel.getJoinType(), condition).build(); return register(rel, newJoin, mapOldToNewOutputs, corDefOutputs); }