Java Code Examples for org.apache.calcite.tools.RelBuilder#union()
The following examples show how to use
org.apache.calcite.tools.RelBuilder#union() .
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: AbstractMaterializedViewRule.java From Bats with Apache License 2.0 | 6 votes |
@Override protected RelNode createUnion(RelBuilder relBuilder, RexBuilder rexBuilder, RelNode topProject, RelNode unionInputQuery, RelNode unionInputView) { relBuilder.push(unionInputQuery); relBuilder.push(unionInputView); relBuilder.union(true); List<RexNode> exprList = new ArrayList<>(relBuilder.peek().getRowType().getFieldCount()); List<String> nameList = new ArrayList<>(relBuilder.peek().getRowType().getFieldCount()); for (int i = 0; i < relBuilder.peek().getRowType().getFieldCount(); i++) { // We can take unionInputQuery as it is query based. RelDataTypeField field = unionInputQuery.getRowType().getFieldList().get(i); exprList.add( rexBuilder.ensureType(field.getType(), rexBuilder.makeInputRef(relBuilder.peek(), i), true)); nameList.add(field.getName()); } relBuilder.project(exprList, nameList); return relBuilder.build(); }
Example 2
Source File: MaterializedViewJoinRule.java From calcite with Apache License 2.0 | 6 votes |
@Override protected RelNode createUnion(RelBuilder relBuilder, RexBuilder rexBuilder, RelNode topProject, RelNode unionInputQuery, RelNode unionInputView) { relBuilder.push(unionInputQuery); relBuilder.push(unionInputView); relBuilder.union(true); List<RexNode> exprList = new ArrayList<>(relBuilder.peek().getRowType().getFieldCount()); List<String> nameList = new ArrayList<>(relBuilder.peek().getRowType().getFieldCount()); for (int i = 0; i < relBuilder.peek().getRowType().getFieldCount(); i++) { // We can take unionInputQuery as it is query based. RelDataTypeField field = unionInputQuery.getRowType().getFieldList().get(i); exprList.add( rexBuilder.ensureType( field.getType(), rexBuilder.makeInputRef(relBuilder.peek(), i), true)); nameList.add(field.getName()); } relBuilder.project(exprList, nameList); return relBuilder.build(); }
Example 3
Source File: UnionToDistinctRule.java From Bats with Apache License 2.0 | 5 votes |
public void onMatch(RelOptRuleCall call) { final Union union = call.rel(0); if (union.all) { return; // nothing to do } final RelBuilder relBuilder = call.builder(); relBuilder.pushAll(union.getInputs()); relBuilder.union(true, union.getInputs().size()); relBuilder.distinct(); call.transformTo(relBuilder.build()); }
Example 4
Source File: AggregateUnionAggregateRule.java From Bats with Apache License 2.0 | 5 votes |
public void onMatch(RelOptRuleCall call) { final Aggregate topAggRel = call.rel(0); final Union union = call.rel(1); // If distincts haven't been removed yet, defer invoking this rule if (!union.all) { return; } final RelBuilder relBuilder = call.builder(); final Aggregate bottomAggRel; if (call.rel(3) instanceof Aggregate) { // Aggregate is the second input bottomAggRel = call.rel(3); relBuilder.push(call.rel(2)) .push(call.rel(3).getInput(0)); } else if (call.rel(2) instanceof Aggregate) { // Aggregate is the first input bottomAggRel = call.rel(2); relBuilder.push(call.rel(2).getInput(0)) .push(call.rel(3)); } else { return; } // Only pull up aggregates if they are there just to remove distincts if (!topAggRel.getAggCallList().isEmpty() || !bottomAggRel.getAggCallList().isEmpty()) { return; } relBuilder.union(true); relBuilder.aggregate(relBuilder.groupKey(topAggRel.getGroupSet()), topAggRel.getAggCallList()); call.transformTo(relBuilder.build()); }
Example 5
Source File: UnionToDistinctRule.java From calcite with Apache License 2.0 | 5 votes |
public void onMatch(RelOptRuleCall call) { final Union union = call.rel(0); final RelBuilder relBuilder = call.builder(); relBuilder.pushAll(union.getInputs()); relBuilder.union(true, union.getInputs().size()); relBuilder.distinct(); call.transformTo(relBuilder.build()); }
Example 6
Source File: AggregateUnionAggregateRule.java From calcite with Apache License 2.0 | 5 votes |
public void onMatch(RelOptRuleCall call) { final Aggregate topAggRel = call.rel(0); final Union union = call.rel(1); // If distincts haven't been removed yet, defer invoking this rule if (!union.all) { return; } final RelBuilder relBuilder = call.builder(); final Aggregate bottomAggRel; if (call.rel(3) instanceof Aggregate) { // Aggregate is the second input bottomAggRel = call.rel(3); relBuilder.push(call.rel(2)) .push(getInputWithSameRowType(bottomAggRel)); } else if (call.rel(2) instanceof Aggregate) { // Aggregate is the first input bottomAggRel = call.rel(2); relBuilder.push(getInputWithSameRowType(bottomAggRel)) .push(call.rel(3)); } else { return; } // Only pull up aggregates if they are there just to remove distincts if (!topAggRel.getAggCallList().isEmpty() || !bottomAggRel.getAggCallList().isEmpty()) { return; } relBuilder.union(true); relBuilder.rename(union.getRowType().getFieldNames()); relBuilder.aggregate(relBuilder.groupKey(topAggRel.getGroupSet()), topAggRel.getAggCallList()); call.transformTo(relBuilder.build()); }
Example 7
Source File: AbstractMaterializedViewRule.java From Bats with Apache License 2.0 | 4 votes |
@Override protected RelNode createUnion(RelBuilder relBuilder, RexBuilder rexBuilder, RelNode topProject, RelNode unionInputQuery, RelNode unionInputView) { // Union relBuilder.push(unionInputQuery); relBuilder.push(unionInputView); relBuilder.union(true); List<RexNode> exprList = new ArrayList<>(relBuilder.peek().getRowType().getFieldCount()); List<String> nameList = new ArrayList<>(relBuilder.peek().getRowType().getFieldCount()); for (int i = 0; i < relBuilder.peek().getRowType().getFieldCount(); i++) { // We can take unionInputQuery as it is query based. RelDataTypeField field = unionInputQuery.getRowType().getFieldList().get(i); exprList.add( rexBuilder.ensureType(field.getType(), rexBuilder.makeInputRef(relBuilder.peek(), i), true)); nameList.add(field.getName()); } relBuilder.project(exprList, nameList); // Rollup aggregate Aggregate aggregate = (Aggregate) unionInputQuery; final ImmutableBitSet groupSet = ImmutableBitSet.range(aggregate.getGroupCount()); final List<AggCall> aggregateCalls = new ArrayList<>(); for (int i = 0; i < aggregate.getAggCallList().size(); i++) { AggregateCall aggCall = aggregate.getAggCallList().get(i); if (aggCall.isDistinct()) { // Cannot ROLLUP distinct return null; } SqlAggFunction rollupAgg = getRollup(aggCall.getAggregation()); if (rollupAgg == null) { // Cannot rollup this aggregate, bail out return null; } final RexInputRef operand = rexBuilder.makeInputRef(relBuilder.peek(), aggregate.getGroupCount() + i); aggregateCalls.add( // TODO: handle aggregate ordering relBuilder.aggregateCall(rollupAgg, operand).distinct(aggCall.isDistinct()) .approximate(aggCall.isApproximate()).as(aggCall.name)); } RelNode prevNode = relBuilder.peek(); RelNode result = relBuilder.aggregate(relBuilder.groupKey(groupSet), aggregateCalls).build(); if (prevNode == result && groupSet.cardinality() != result.getRowType().getFieldCount()) { // Aggregate was not inserted but we need to prune columns result = relBuilder.push(result).project(relBuilder.fields(groupSet.asList())).build(); } if (topProject != null) { // Top project return topProject.copy(topProject.getTraitSet(), ImmutableList.of(result)); } // Result return result; }
Example 8
Source File: UnionPullUpConstantsRule.java From Bats with Apache License 2.0 | 4 votes |
@Override public void onMatch(RelOptRuleCall call) { final Union union = call.rel(0); final int count = union.getRowType().getFieldCount(); if (count == 1) { // No room for optimization since we cannot create an empty Project // operator. If we created a Project with one column, this rule would // cycle. return; } final RexBuilder rexBuilder = union.getCluster().getRexBuilder(); final RelMetadataQuery mq = call.getMetadataQuery(); final RelOptPredicateList predicates = mq.getPulledUpPredicates(union); if (predicates == null) { return; } final Map<Integer, RexNode> constants = new HashMap<>(); for (Map.Entry<RexNode, RexNode> e : predicates.constantMap.entrySet()) { if (e.getKey() instanceof RexInputRef) { constants.put(((RexInputRef) e.getKey()).getIndex(), e.getValue()); } } // None of the expressions are constant. Nothing to do. if (constants.isEmpty()) { return; } // Create expressions for Project operators before and after the Union List<RelDataTypeField> fields = union.getRowType().getFieldList(); List<RexNode> topChildExprs = new ArrayList<>(); List<String> topChildExprsFields = new ArrayList<>(); List<RexNode> refs = new ArrayList<>(); ImmutableBitSet.Builder refsIndexBuilder = ImmutableBitSet.builder(); for (RelDataTypeField field : fields) { final RexNode constant = constants.get(field.getIndex()); if (constant != null) { topChildExprs.add(constant); topChildExprsFields.add(field.getName()); } else { final RexNode expr = rexBuilder.makeInputRef(union, field.getIndex()); topChildExprs.add(expr); topChildExprsFields.add(field.getName()); refs.add(expr); refsIndexBuilder.set(field.getIndex()); } } ImmutableBitSet refsIndex = refsIndexBuilder.build(); // Update top Project positions final Mappings.TargetMapping mapping = RelOptUtil.permutation(refs, union.getInput(0).getRowType()).inverse(); topChildExprs = ImmutableList.copyOf(RexUtil.apply(mapping, topChildExprs)); // Create new Project-Union-Project sequences final RelBuilder relBuilder = call.builder(); for (RelNode input : union.getInputs()) { List<Pair<RexNode, String>> newChildExprs = new ArrayList<>(); for (int j : refsIndex) { newChildExprs.add( Pair.of(rexBuilder.makeInputRef(input, j), input.getRowType().getFieldList().get(j).getName())); } if (newChildExprs.isEmpty()) { // At least a single item in project is required. newChildExprs.add( Pair.of(topChildExprs.get(0), topChildExprsFields.get(0))); } // Add the input with project on top relBuilder.push(input); relBuilder.project(Pair.left(newChildExprs), Pair.right(newChildExprs)); } relBuilder.union(union.all, union.getInputs().size()); // Create top Project fixing nullability of fields relBuilder.project(topChildExprs, topChildExprsFields); relBuilder.convert(union.getRowType(), false); call.transformTo(relBuilder.build()); }
Example 9
Source File: AggregateUnionTransposeRule.java From Bats with Apache License 2.0 | 4 votes |
public void onMatch(RelOptRuleCall call) { Aggregate aggRel = call.rel(0); Union union = call.rel(1); if (!union.all) { // This transformation is only valid for UNION ALL. // Consider t1(i) with rows (5), (5) and t2(i) with // rows (5), (10), and the query // select sum(i) from (select i from t1) union (select i from t2). // The correct answer is 15. If we apply the transformation, // we get // select sum(i) from // (select sum(i) as i from t1) union (select sum(i) as i from t2) // which yields 25 (incorrect). return; } int groupCount = aggRel.getGroupSet().cardinality(); List<AggregateCall> transformedAggCalls = transformAggCalls( aggRel.copy(aggRel.getTraitSet(), aggRel.getInput(), false, aggRel.getGroupSet(), null, aggRel.getAggCallList()), groupCount, aggRel.getAggCallList()); if (transformedAggCalls == null) { // we've detected the presence of something like AVG, // which we can't handle return; } // create corresponding aggregates on top of each union child final RelBuilder relBuilder = call.builder(); int transformCount = 0; final RelMetadataQuery mq = call.getMetadataQuery(); for (RelNode input : union.getInputs()) { boolean alreadyUnique = RelMdUtil.areColumnsDefinitelyUnique(mq, input, aggRel.getGroupSet()); relBuilder.push(input); if (!alreadyUnique) { ++transformCount; relBuilder.aggregate(relBuilder.groupKey(aggRel.getGroupSet()), aggRel.getAggCallList()); } } if (transformCount == 0) { // none of the children could benefit from the push-down, // so bail out (preventing the infinite loop to which most // planners would succumb) return; } // create a new union whose children are the aggregates created above relBuilder.union(true, union.getInputs().size()); relBuilder.aggregate( relBuilder.groupKey(aggRel.getGroupSet(), aggRel.getGroupSets()), transformedAggCalls); call.transformTo(relBuilder.build()); }
Example 10
Source File: UnionMergeRule.java From Bats with Apache License 2.0 | 4 votes |
public void onMatch(RelOptRuleCall call) { final SetOp topOp = call.rel(0); @SuppressWarnings("unchecked") final Class<? extends SetOp> setOpClass = (Class) operands.get(0).getMatchedClass(); // For Union and Intersect, we want to combine the set-op that's in the // second input first. // // For example, we reduce // Union(Union(a, b), Union(c, d)) // to // Union(Union(a, b), c, d) // in preference to // Union(a, b, Union(c, d)) // // But for Minus, we can only reduce the left input. It is not valid to // reduce // Minus(a, Minus(b, c)) // to // Minus(a, b, c) // // Hence, that's why the rule pattern matches on generic RelNodes rather // than explicit sub-classes of SetOp. By doing so, and firing this rule // in a bottom-up order, it allows us to only specify a single // pattern for this rule. final SetOp bottomOp; if (setOpClass.isInstance(call.rel(2)) && !Minus.class.isAssignableFrom(setOpClass)) { bottomOp = call.rel(2); } else if (setOpClass.isInstance(call.rel(1))) { bottomOp = call.rel(1); } else { return; } // Can only combine (1) if all operators are ALL, // or (2) top operator is DISTINCT (i.e. not ALL). // In case (2), all operators become DISTINCT. if (topOp.all && !bottomOp.all) { return; } // Combine the inputs from the bottom set-op with the other inputs from // the top set-op. final RelBuilder relBuilder = call.builder(); if (setOpClass.isInstance(call.rel(2)) && !Minus.class.isAssignableFrom(setOpClass)) { relBuilder.push(topOp.getInput(0)); relBuilder.pushAll(bottomOp.getInputs()); // topOp.getInputs().size() may be more than 2 for (int index = 2; index < topOp.getInputs().size(); index++) { relBuilder.push(topOp.getInput(index)); } } else { relBuilder.pushAll(bottomOp.getInputs()); relBuilder.pushAll(Util.skip(topOp.getInputs())); } int n = bottomOp.getInputs().size() + topOp.getInputs().size() - 1; if (topOp instanceof Union) { relBuilder.union(topOp.all, n); } else if (topOp instanceof Intersect) { relBuilder.intersect(topOp.all, n); } else if (topOp instanceof Minus) { relBuilder.minus(topOp.all, n); } call.transformTo(relBuilder.build()); }
Example 11
Source File: MaterializedViewAggregateRule.java From calcite with Apache License 2.0 | 4 votes |
@Override protected RelNode createUnion(RelBuilder relBuilder, RexBuilder rexBuilder, RelNode topProject, RelNode unionInputQuery, RelNode unionInputView) { // Union relBuilder.push(unionInputQuery); relBuilder.push(unionInputView); relBuilder.union(true); List<RexNode> exprList = new ArrayList<>(relBuilder.peek().getRowType().getFieldCount()); List<String> nameList = new ArrayList<>(relBuilder.peek().getRowType().getFieldCount()); for (int i = 0; i < relBuilder.peek().getRowType().getFieldCount(); i++) { // We can take unionInputQuery as it is query based. RelDataTypeField field = unionInputQuery.getRowType().getFieldList().get(i); exprList.add( rexBuilder.ensureType( field.getType(), rexBuilder.makeInputRef(relBuilder.peek(), i), true)); nameList.add(field.getName()); } relBuilder.project(exprList, nameList); // Rollup aggregate Aggregate aggregate = (Aggregate) unionInputQuery; final ImmutableBitSet groupSet = ImmutableBitSet.range(aggregate.getGroupCount()); final List<AggCall> aggregateCalls = new ArrayList<>(); for (int i = 0; i < aggregate.getAggCallList().size(); i++) { AggregateCall aggCall = aggregate.getAggCallList().get(i); if (aggCall.isDistinct()) { // Cannot ROLLUP distinct return null; } SqlAggFunction rollupAgg = getRollup(aggCall.getAggregation()); if (rollupAgg == null) { // Cannot rollup this aggregate, bail out return null; } final RexInputRef operand = rexBuilder.makeInputRef(relBuilder.peek(), aggregate.getGroupCount() + i); aggregateCalls.add( relBuilder.aggregateCall(rollupAgg, operand) .distinct(aggCall.isDistinct()) .approximate(aggCall.isApproximate()) .as(aggCall.name)); } RelNode prevNode = relBuilder.peek(); RelNode result = relBuilder .aggregate(relBuilder.groupKey(groupSet), aggregateCalls) .build(); if (prevNode == result && groupSet.cardinality() != result.getRowType().getFieldCount()) { // Aggregate was not inserted but we need to prune columns result = relBuilder .push(result) .project(relBuilder.fields(groupSet)) .build(); } if (topProject != null) { // Top project return topProject.copy(topProject.getTraitSet(), ImmutableList.of(result)); } // Result return result; }
Example 12
Source File: UnionPullUpConstantsRule.java From calcite with Apache License 2.0 | 4 votes |
@Override public void onMatch(RelOptRuleCall call) { final Union union = call.rel(0); final RexBuilder rexBuilder = union.getCluster().getRexBuilder(); final RelMetadataQuery mq = call.getMetadataQuery(); final RelOptPredicateList predicates = mq.getPulledUpPredicates(union); if (predicates == null) { return; } final Map<Integer, RexNode> constants = new HashMap<>(); for (Map.Entry<RexNode, RexNode> e : predicates.constantMap.entrySet()) { if (e.getKey() instanceof RexInputRef) { constants.put(((RexInputRef) e.getKey()).getIndex(), e.getValue()); } } // None of the expressions are constant. Nothing to do. if (constants.isEmpty()) { return; } // Create expressions for Project operators before and after the Union List<RelDataTypeField> fields = union.getRowType().getFieldList(); List<RexNode> topChildExprs = new ArrayList<>(); List<String> topChildExprsFields = new ArrayList<>(); List<RexNode> refs = new ArrayList<>(); ImmutableBitSet.Builder refsIndexBuilder = ImmutableBitSet.builder(); for (RelDataTypeField field : fields) { final RexNode constant = constants.get(field.getIndex()); if (constant != null) { topChildExprs.add(constant); topChildExprsFields.add(field.getName()); } else { final RexNode expr = rexBuilder.makeInputRef(union, field.getIndex()); topChildExprs.add(expr); topChildExprsFields.add(field.getName()); refs.add(expr); refsIndexBuilder.set(field.getIndex()); } } ImmutableBitSet refsIndex = refsIndexBuilder.build(); // Update top Project positions final Mappings.TargetMapping mapping = RelOptUtil.permutation(refs, union.getInput(0).getRowType()).inverse(); topChildExprs = RexUtil.apply(mapping, topChildExprs); // Create new Project-Union-Project sequences final RelBuilder relBuilder = call.builder(); for (RelNode input : union.getInputs()) { List<Pair<RexNode, String>> newChildExprs = new ArrayList<>(); for (int j : refsIndex) { newChildExprs.add( Pair.of(rexBuilder.makeInputRef(input, j), input.getRowType().getFieldList().get(j).getName())); } if (newChildExprs.isEmpty()) { // At least a single item in project is required. newChildExprs.add( Pair.of(topChildExprs.get(0), topChildExprsFields.get(0))); } // Add the input with project on top relBuilder.push(input); relBuilder.project(Pair.left(newChildExprs), Pair.right(newChildExprs)); } relBuilder.union(union.all, union.getInputs().size()); // Create top Project fixing nullability of fields relBuilder.project(topChildExprs, topChildExprsFields); relBuilder.convert(union.getRowType(), false); call.transformTo(relBuilder.build()); }
Example 13
Source File: AggregateUnionTransposeRule.java From calcite with Apache License 2.0 | 4 votes |
public void onMatch(RelOptRuleCall call) { Aggregate aggRel = call.rel(0); Union union = call.rel(1); if (!union.all) { // This transformation is only valid for UNION ALL. // Consider t1(i) with rows (5), (5) and t2(i) with // rows (5), (10), and the query // select sum(i) from (select i from t1) union (select i from t2). // The correct answer is 15. If we apply the transformation, // we get // select sum(i) from // (select sum(i) as i from t1) union (select sum(i) as i from t2) // which yields 25 (incorrect). return; } int groupCount = aggRel.getGroupSet().cardinality(); List<AggregateCall> transformedAggCalls = transformAggCalls( aggRel.copy(aggRel.getTraitSet(), aggRel.getInput(), aggRel.getGroupSet(), null, aggRel.getAggCallList()), groupCount, aggRel.getAggCallList()); if (transformedAggCalls == null) { // we've detected the presence of something like AVG, // which we can't handle return; } // create corresponding aggregates on top of each union child final RelBuilder relBuilder = call.builder(); int transformCount = 0; final RelMetadataQuery mq = call.getMetadataQuery(); for (RelNode input : union.getInputs()) { boolean alreadyUnique = RelMdUtil.areColumnsDefinitelyUnique(mq, input, aggRel.getGroupSet()); relBuilder.push(input); if (!alreadyUnique) { ++transformCount; relBuilder.aggregate(relBuilder.groupKey(aggRel.getGroupSet()), aggRel.getAggCallList()); } } if (transformCount == 0) { // none of the children could benefit from the push-down, // so bail out (preventing the infinite loop to which most // planners would succumb) return; } // create a new union whose children are the aggregates created above relBuilder.union(true, union.getInputs().size()); relBuilder.aggregate( relBuilder.groupKey(aggRel.getGroupSet(), (Iterable<ImmutableBitSet>) aggRel.getGroupSets()), transformedAggCalls); call.transformTo(relBuilder.build()); }
Example 14
Source File: UnionMergeRule.java From calcite with Apache License 2.0 | 4 votes |
public void onMatch(RelOptRuleCall call) { final SetOp topOp = call.rel(0); @SuppressWarnings("unchecked") final Class<? extends SetOp> setOpClass = (Class) operands.get(0).getMatchedClass(); // For Union and Intersect, we want to combine the set-op that's in the // second input first. // // For example, we reduce // Union(Union(a, b), Union(c, d)) // to // Union(Union(a, b), c, d) // in preference to // Union(a, b, Union(c, d)) // // But for Minus, we can only reduce the left input. It is not valid to // reduce // Minus(a, Minus(b, c)) // to // Minus(a, b, c) // // Hence, that's why the rule pattern matches on generic RelNodes rather // than explicit sub-classes of SetOp. By doing so, and firing this rule // in a bottom-up order, it allows us to only specify a single // pattern for this rule. final SetOp bottomOp; if (setOpClass.isInstance(call.rel(2)) && !Minus.class.isAssignableFrom(setOpClass)) { bottomOp = call.rel(2); } else if (setOpClass.isInstance(call.rel(1))) { bottomOp = call.rel(1); } else { return; } // Can only combine (1) if all operators are ALL, // or (2) top operator is DISTINCT (i.e. not ALL). // In case (2), all operators become DISTINCT. if (topOp.all && !bottomOp.all) { return; } // Combine the inputs from the bottom set-op with the other inputs from // the top set-op. final RelBuilder relBuilder = call.builder(); if (setOpClass.isInstance(call.rel(2)) && !Minus.class.isAssignableFrom(setOpClass)) { relBuilder.push(topOp.getInput(0)); relBuilder.pushAll(bottomOp.getInputs()); // topOp.getInputs().size() may be more than 2 for (int index = 2; index < topOp.getInputs().size(); index++) { relBuilder.push(topOp.getInput(index)); } } else { relBuilder.pushAll(bottomOp.getInputs()); relBuilder.pushAll(Util.skip(topOp.getInputs())); } int n = bottomOp.getInputs().size() + topOp.getInputs().size() - 1; if (topOp instanceof Union) { relBuilder.union(topOp.all, n); } else if (topOp instanceof Intersect) { relBuilder.intersect(topOp.all, n); } else if (topOp instanceof Minus) { relBuilder.minus(topOp.all, n); } call.transformTo(relBuilder.build()); }