Java Code Examples for org.apache.calcite.plan.RelOptUtil#pushPastProject()
The following examples show how to use
org.apache.calcite.plan.RelOptUtil#pushPastProject() .
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: RelMdSelectivity.java From Bats with Apache License 2.0 | 5 votes |
public Double getSelectivity(Project rel, RelMetadataQuery mq, RexNode predicate) { final List<RexNode> notPushable = new ArrayList<>(); final List<RexNode> pushable = new ArrayList<>(); RelOptUtil.splitFilters( ImmutableBitSet.range(rel.getRowType().getFieldCount()), predicate, pushable, notPushable); final RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); RexNode childPred = RexUtil.composeConjunction(rexBuilder, pushable, true); RexNode modifiedPred; if (childPred == null) { modifiedPred = null; } else { modifiedPred = RelOptUtil.pushPastProject(childPred, rel); } Double selectivity = mq.getSelectivity(rel.getInput(), modifiedPred); if (selectivity == null) { return null; } else { RexNode pred = RexUtil.composeConjunction(rexBuilder, notPushable, true); return selectivity * RelMdUtil.guessSelectivity(pred); } }
Example 2
Source File: FilterProjectTransposeRule.java From Bats with Apache License 2.0 | 5 votes |
public void onMatch(RelOptRuleCall call) { final Filter filter = call.rel(0); final Project project = call.rel(1); if (RexOver.containsOver(project.getProjects(), null)) { // In general a filter cannot be pushed below a windowing calculation. // Applying the filter before the aggregation function changes // the results of the windowing invocation. // // When the filter is on the PARTITION BY expression of the OVER clause // it can be pushed down. For now we don't support this. return; } // convert the filter to one that references the child of the project RexNode newCondition = RelOptUtil.pushPastProject(filter.getCondition(), project); final RelBuilder relBuilder = call.builder(); RelNode newFilterRel; if (copyFilter) { newFilterRel = filter.copy(filter.getTraitSet(), project.getInput(), simplifyFilterCondition(newCondition, call)); } else { newFilterRel = relBuilder.push(project.getInput()).filter(newCondition).build(); } RelNode newProjRel = copyProject ? project.copy(project.getTraitSet(), newFilterRel, project.getProjects(), project.getRowType()) : relBuilder.push(newFilterRel) .project(project.getProjects(), project.getRowType().getFieldNames()) .build(); call.transformTo(newProjRel); }
Example 3
Source File: PushProjectForFlattenPastProjectRule.java From dremio-oss with Apache License 2.0 | 5 votes |
@Override public void onMatch(RelOptRuleCall call) { ProjectForFlattenRel projectForFlattenRel = call.rel(0); ProjectRel project = call.rel(1); List<RexNode> newItemsExprs = RelOptUtil.pushPastProject(projectForFlattenRel.getItemExprs(), project); List<RexNode> newProjExprs = RelOptUtil.pushPastProject(projectForFlattenRel.getProjExprs(), project); ProjectForFlattenRel newProjectForFlattenRel = new ProjectForFlattenRel( projectForFlattenRel.getCluster(), projectForFlattenRel.getTraitSet(), project.getInput(), projectForFlattenRel.getRowType(), newProjExprs, newItemsExprs); call.transformTo(newProjectForFlattenRel); }
Example 4
Source File: MergeProjectForFlattenRule.java From dremio-oss with Apache License 2.0 | 5 votes |
@Override public void onMatch(RelOptRuleCall call) { ProjectForFlattenRel top = call.rel(0); ProjectForFlattenRel bottom = call.rel(1); ProjectRel temporary = ProjectRel.create(bottom.getCluster(), bottom.getTraitSet(), bottom.getInput(), bottom.getProjExprs(), bottom.getRowType()); List<RexNode> newProjExprs = RelOptUtil.pushPastProject(top.getProjExprs(), temporary); List<RexNode> newItemExprs = new ArrayList<>(top.getItemExprs().size() + bottom.getItemExprs().size()); newItemExprs.addAll(RelOptUtil.pushPastProject(top.getItemExprs(), temporary)); newItemExprs.addAll(bottom.getItemExprs()); ProjectForFlattenRel newProjectForFlatten = new ProjectForFlattenRel( top.getCluster(), top.getTraitSet(), bottom.getInput(), top.getRowType(), newProjExprs, newItemExprs); call.transformTo(newProjectForFlatten); }
Example 5
Source File: FilterProjectNLJRule.java From dremio-oss with Apache License 2.0 | 5 votes |
@Override public void onMatch(RelOptRuleCall call) { FilterPrel filter = call.rel(0); ProjectPrel project = call.rel(1); NestedLoopJoinPrel join = call.rel(2); RexNode newCondition = RelOptUtil.pushPastProject(filter.getCondition(), project); final RelBuilder relBuilder = call.builder(); RelNode newFilterRel = filter.copy(filter.getTraitSet(), NestedLoopJoinPrel.create(join.getCluster(), join.getTraitSet(), join.getLeft(), join.getRight(), join.getJoinType(), join.getCondition(), join.getProjectedFields()), RexUtil.removeNullabilityCast(relBuilder.getTypeFactory(), newCondition)); RelNode newProjRel = project.copy(project.getTraitSet(), newFilterRel, project.getProjects(), project.getRowType()); call.transformTo(newProjRel); }
Example 6
Source File: ElasticFilterRule.java From dremio-oss with Apache License 2.0 | 5 votes |
@Override public void processProject(ElasticsearchProject project) { filterExprs = pushPastProject(filterExprs, project); if (projectExprs == null) { projectExprs = project.getProjects(); projectDataType = project.getRowType(); } else { projectExprs = RelOptUtil.pushPastProject(projectExprs, project); // projectDataType should not be set here, since we want to keep the top project's row type. } }
Example 7
Source File: RelMdSelectivity.java From calcite with Apache License 2.0 | 5 votes |
public Double getSelectivity(Project rel, RelMetadataQuery mq, RexNode predicate) { final List<RexNode> notPushable = new ArrayList<>(); final List<RexNode> pushable = new ArrayList<>(); RelOptUtil.splitFilters( ImmutableBitSet.range(rel.getRowType().getFieldCount()), predicate, pushable, notPushable); final RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); RexNode childPred = RexUtil.composeConjunction(rexBuilder, pushable, true); RexNode modifiedPred; if (childPred == null) { modifiedPred = null; } else { modifiedPred = RelOptUtil.pushPastProject(childPred, rel); } Double selectivity = mq.getSelectivity(rel.getInput(), modifiedPred); if (selectivity == null) { return null; } else { RexNode pred = RexUtil.composeConjunction(rexBuilder, notPushable, true); return selectivity * RelMdUtil.guessSelectivity(pred); } }
Example 8
Source File: RelMdDistinctRowCount.java From Bats with Apache License 2.0 | 4 votes |
public Double getDistinctRowCount(Project rel, RelMetadataQuery mq, ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; } } ImmutableBitSet.Builder baseCols = ImmutableBitSet.builder(); ImmutableBitSet.Builder projCols = ImmutableBitSet.builder(); List<RexNode> projExprs = rel.getProjects(); RelMdUtil.splitCols(projExprs, groupKey, baseCols, projCols); final List<RexNode> notPushable = new ArrayList<>(); final List<RexNode> pushable = new ArrayList<>(); RelOptUtil.splitFilters( ImmutableBitSet.range(rel.getRowType().getFieldCount()), predicate, pushable, notPushable); final RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); // get the distinct row count of the child input, passing in the // columns and filters that only reference the child; convert the // filter to reference the children projection expressions RexNode childPred = RexUtil.composeConjunction(rexBuilder, pushable, true); RexNode modifiedPred; if (childPred == null) { modifiedPred = null; } else { modifiedPred = RelOptUtil.pushPastProject(childPred, rel); } Double distinctRowCount = mq.getDistinctRowCount(rel.getInput(), baseCols.build(), modifiedPred); if (distinctRowCount == null) { return null; } else if (!notPushable.isEmpty()) { RexNode preds = RexUtil.composeConjunction(rexBuilder, notPushable, true); distinctRowCount *= RelMdUtil.guessSelectivity(preds); } // No further computation required if the projection expressions // are all column references if (projCols.cardinality() == 0) { return distinctRowCount; } // multiply by the cardinality of the non-child projection expressions for (int bit : projCols.build()) { Double subRowCount = RelMdUtil.cardOfProjExpr(mq, rel, projExprs.get(bit)); if (subRowCount == null) { return null; } distinctRowCount *= subRowCount; } return RelMdUtil.numDistinctVals(distinctRowCount, mq.getRowCount(rel)); }
Example 9
Source File: ProjectMergeRule.java From Bats with Apache License 2.0 | 4 votes |
public void onMatch(RelOptRuleCall call) { final Project topProject = call.rel(0); final Project bottomProject = call.rel(1); final RelBuilder relBuilder = call.builder(); // If one or both projects are permutations, short-circuit the complex logic // of building a RexProgram. final Permutation topPermutation = topProject.getPermutation(); if (topPermutation != null) { if (topPermutation.isIdentity()) { // Let ProjectRemoveRule handle this. return; } final Permutation bottomPermutation = bottomProject.getPermutation(); if (bottomPermutation != null) { if (bottomPermutation.isIdentity()) { // Let ProjectRemoveRule handle this. return; } final Permutation product = topPermutation.product(bottomPermutation); relBuilder.push(bottomProject.getInput()); relBuilder.project(relBuilder.fields(product), topProject.getRowType().getFieldNames()); call.transformTo(relBuilder.build()); return; } } // If we're not in force mode and the two projects reference identical // inputs, then return and let ProjectRemoveRule replace the projects. if (!force) { if (RexUtil.isIdentity(topProject.getProjects(), topProject.getInput().getRowType())) { return; } } final List<RexNode> newProjects = RelOptUtil.pushPastProject(topProject.getProjects(), bottomProject); final RelNode input = bottomProject.getInput(); if (RexUtil.isIdentity(newProjects, input.getRowType())) { if (force || input.getRowType().getFieldNames() .equals(topProject.getRowType().getFieldNames())) { call.transformTo(input); return; } } // replace the two projects with a combined projection relBuilder.push(bottomProject.getInput()); relBuilder.project(newProjects, topProject.getRowType().getFieldNames()); call.transformTo(relBuilder.build()); }
Example 10
Source File: DrillPushFilterPastProjectRule.java From Bats with Apache License 2.0 | 4 votes |
public void onMatch(RelOptRuleCall call) { Filter filterRel = call.rel(0); Project projRel = call.rel(1); RelBuilder builder = call.builder(); // get a conjunctions of the filter condition. For each conjunction, if it refers to ITEM or FLATTEN expression // then we could not pushed down. Otherwise, it's qualified to be pushed down. final List<RexNode> predList = RelOptUtil.conjunctions(filterRel.getCondition()); final List<RexNode> qualifiedPredList = Lists.newArrayList(); final List<RexNode> unqualifiedPredList = Lists.newArrayList(); for (final RexNode pred : predList) { if (DrillRelOptUtil.findOperators(pred, projRel.getProjects(), BANNED_OPERATORS) == null) { qualifiedPredList.add(pred); } else { unqualifiedPredList.add(pred); } } final RexNode qualifedPred = RexUtil.composeConjunction(filterRel.getCluster().getRexBuilder(), qualifiedPredList, true); if (qualifedPred == null) { return; } // convert the filter to one that references the child of the project RexNode newCondition = RelOptUtil.pushPastProject(qualifedPred, projRel); RelNode newFilterRel = builder .push(projRel.getInput()) .filter(newCondition) .build(); RelNode newProjRel = builder .push(newFilterRel) .projectNamed(Pair.left(projRel.getNamedProjects()), Pair.right(projRel.getNamedProjects()), true) .build(); final RexNode unqualifiedPred = RexUtil.composeConjunction(filterRel.getCluster().getRexBuilder(), unqualifiedPredList, true); if (unqualifiedPred == null) { call.transformTo(newProjRel); } else { // if there are filters not qualified to be pushed down, then we have to put those filters on top of // the new Project operator. // Filter -- unqualified filters // \ // Project // \ // Filter -- qualified filters RelNode filterNotPushed = builder .push(newProjRel) .filter(unqualifiedPred) .build(); call.transformTo(filterNotPushed); } }
Example 11
Source File: DrillMergeProjectRule.java From Bats with Apache License 2.0 | 4 votes |
@Override public void onMatch(RelOptRuleCall call) { final Project topProject = call.rel(0); final Project bottomProject = call.rel(1); final RelBuilder relBuilder = call.builder(); // If one or both projects are permutations, short-circuit the complex logic // of building a RexProgram. final Permutation topPermutation = topProject.getPermutation(); if (topPermutation != null) { if (topPermutation.isIdentity()) { // Let ProjectRemoveRule handle this. return; } final Permutation bottomPermutation = bottomProject.getPermutation(); if (bottomPermutation != null) { if (bottomPermutation.isIdentity()) { // Let ProjectRemoveRule handle this. return; } final Permutation product = topPermutation.product(bottomPermutation); relBuilder.push(bottomProject.getInput()); relBuilder.project(relBuilder.fields(product), topProject.getRowType().getFieldNames()); call.transformTo(relBuilder.build()); return; } } // If we're not in force mode and the two projects reference identical // inputs, then return and let ProjectRemoveRule replace the projects. if (!force) { if (RexUtil.isIdentity(topProject.getProjects(), topProject.getInput().getRowType())) { return; } } final List<RexNode> pushedProjects = RelOptUtil.pushPastProject(topProject.getProjects(), bottomProject); final List<RexNode> newProjects = simplifyCast(pushedProjects); final RelNode input = bottomProject.getInput(); if (RexUtil.isIdentity(newProjects, input.getRowType())) { if (force || input.getRowType().getFieldNames() .equals(topProject.getRowType().getFieldNames())) { call.transformTo(input); return; } } // replace the two projects with a combined projection relBuilder.push(bottomProject.getInput()); relBuilder.project(newProjects, topProject.getRowType().getFieldNames()); call.transformTo(relBuilder.build()); }
Example 12
Source File: MergeProjectRule.java From dremio-oss with Apache License 2.0 | 4 votes |
@Override public void onMatch(RelOptRuleCall call) { final Project topProject = call.rel(0); final Project bottomProject = call.rel(1); final RelBuilder relBuilder = call.builder(); // merge projects assuming it doesn't alter the unique count of flattens. final FlattenCounter counter = new FlattenCounter(); counter.add(topProject); counter.add(bottomProject); final int uniqueFlattens = counter.getCount(); // If one or both projects are permutations, short-circuit the complex logic // of building a RexProgram. final Permutation topPermutation = topProject.getPermutation(); if (topPermutation != null) { if (topPermutation.isIdentity()) { // Let ProjectRemoveRule handle this. return; } final Permutation bottomPermutation = bottomProject.getPermutation(); if (bottomPermutation != null) { if (bottomPermutation.isIdentity()) { // Let ProjectRemoveRule handle this. return; } final Permutation product = topPermutation.product(bottomPermutation); relBuilder.push(bottomProject.getInput()); List<RexNode> exprs = relBuilder.fields(product); relBuilder.project(exprs, topProject.getRowType().getFieldNames()); if(FlattenVisitors.count(exprs) == uniqueFlattens){ call.transformTo(relBuilder.build()); } return; } } final List<RexNode> newProjects = RelOptUtil.pushPastProject(topProject.getProjects(), bottomProject); final RelNode input = bottomProject.getInput(); if (RexUtil.isIdentity(newProjects, input.getRowType()) && uniqueFlattens == 0) { call.transformTo(input); return; } // replace the two projects with a combined projection relBuilder.push(bottomProject.getInput()); relBuilder.project(newProjects, topProject.getRowType().getFieldNames()); if(FlattenVisitors.count(newProjects) == uniqueFlattens){ call.transformTo(relBuilder.build()); } }
Example 13
Source File: PushFilterPastProjectRule.java From dremio-oss with Apache License 2.0 | 4 votes |
@Override public void onMatch(RelOptRuleCall call) { Filter filterRel = call.rel(0); Project projRel = call.rel(1); // get a conjunctions of the filter condition. For each conjunction, if it refers to ITEM or FLATTEN expression // then we could not pushed down. Otherwise, it's qualified to be pushed down. final List<RexNode> predList = RelOptUtil.conjunctions(filterRel.getCondition()); final List<RexNode> qualifiedPredList = Lists.newArrayList(); final List<RexNode> unqualifiedPredList = Lists.newArrayList(); for (final RexNode pred : predList) { if (qualifies(pred, projRel.getProjects())) { qualifiedPredList.add(pred); } else { unqualifiedPredList.add(pred); } } final RexNode qualifedPred = RexUtil.composeConjunction(filterRel.getCluster().getRexBuilder(), qualifiedPredList, true); if (qualifedPred == null) { return; } // convert the filter to one that references the child of the project RexNode newCondition = RelOptUtil.pushPastProject(qualifedPred, projRel); RelBuilder relBuilder = relBuilderFactory.create(filterRel.getCluster(), null); relBuilder.push(projRel.getInput()); relBuilder.filter(newCondition); relBuilder.project(Pair.left(projRel.getNamedProjects()), Pair.right(projRel.getNamedProjects())); final RexNode unqualifiedPred = RexUtil.composeConjunction(filterRel.getCluster().getRexBuilder(), unqualifiedPredList, true); if (unqualifiedPred == null) { call.transformTo(relBuilder.build()); } else { // if there are filters not qualified to be pushed down, then we have to put those filters on top of // the new Project operator. // Filter -- unqualified filters // \ // Project // \ // Filter -- qualified filters relBuilder.filter(unqualifiedPred); call.transformTo(relBuilder.build()); } }
Example 14
Source File: ElasticProjectRule.java From dremio-oss with Apache License 2.0 | 4 votes |
@Override public void processProject(ElasticsearchProject project) { projectExprs = RelOptUtil.pushPastProject(projectExprs, project); // projectDataType should not be set here, since we want to keep the top project's row type. }
Example 15
Source File: RelMdDistinctRowCount.java From calcite with Apache License 2.0 | 4 votes |
public Double getDistinctRowCount(Project rel, RelMetadataQuery mq, ImmutableBitSet groupKey, RexNode predicate) { if (predicate == null || predicate.isAlwaysTrue()) { if (groupKey.isEmpty()) { return 1D; } } ImmutableBitSet.Builder baseCols = ImmutableBitSet.builder(); ImmutableBitSet.Builder projCols = ImmutableBitSet.builder(); List<RexNode> projExprs = rel.getProjects(); RelMdUtil.splitCols(projExprs, groupKey, baseCols, projCols); final List<RexNode> notPushable = new ArrayList<>(); final List<RexNode> pushable = new ArrayList<>(); RelOptUtil.splitFilters( ImmutableBitSet.range(rel.getRowType().getFieldCount()), predicate, pushable, notPushable); final RexBuilder rexBuilder = rel.getCluster().getRexBuilder(); // get the distinct row count of the child input, passing in the // columns and filters that only reference the child; convert the // filter to reference the children projection expressions RexNode childPred = RexUtil.composeConjunction(rexBuilder, pushable, true); RexNode modifiedPred; if (childPred == null) { modifiedPred = null; } else { modifiedPred = RelOptUtil.pushPastProject(childPred, rel); } Double distinctRowCount = mq.getDistinctRowCount(rel.getInput(), baseCols.build(), modifiedPred); if (distinctRowCount == null) { return null; } else if (!notPushable.isEmpty()) { RexNode preds = RexUtil.composeConjunction(rexBuilder, notPushable, true); distinctRowCount *= RelMdUtil.guessSelectivity(preds); } // No further computation required if the projection expressions // are all column references if (projCols.cardinality() == 0) { return distinctRowCount; } // multiply by the cardinality of the non-child projection expressions for (int bit : projCols.build()) { Double subRowCount = RelMdUtil.cardOfProjExpr(mq, rel, projExprs.get(bit)); if (subRowCount == null) { return null; } distinctRowCount *= subRowCount; } return RelMdUtil.numDistinctVals(distinctRowCount, mq.getRowCount(rel)); }
Example 16
Source File: FilterProjectTransposeRule.java From calcite with Apache License 2.0 | 4 votes |
public void onMatch(RelOptRuleCall call) { final Filter filter = call.rel(0); final Project project = call.rel(1); if (RexOver.containsOver(project.getProjects(), null)) { // In general a filter cannot be pushed below a windowing calculation. // Applying the filter before the aggregation function changes // the results of the windowing invocation. // // When the filter is on the PARTITION BY expression of the OVER clause // it can be pushed down. For now we don't support this. return; } // convert the filter to one that references the child of the project RexNode newCondition = RelOptUtil.pushPastProject(filter.getCondition(), project); final RelBuilder relBuilder = call.builder(); RelNode newFilterRel; if (copyFilter) { final RelNode input = project.getInput(); final RelTraitSet traitSet = filter.getTraitSet() .replaceIfs(RelCollationTraitDef.INSTANCE, () -> Collections.singletonList( input.getTraitSet().getTrait(RelCollationTraitDef.INSTANCE))) .replaceIfs(RelDistributionTraitDef.INSTANCE, () -> Collections.singletonList( input.getTraitSet().getTrait(RelDistributionTraitDef.INSTANCE))); newCondition = RexUtil.removeNullabilityCast(relBuilder.getTypeFactory(), newCondition); newFilterRel = filter.copy(traitSet, input, newCondition); } else { newFilterRel = relBuilder.push(project.getInput()).filter(newCondition).build(); } RelNode newProjRel = copyProject ? project.copy(project.getTraitSet(), newFilterRel, project.getProjects(), project.getRowType()) : relBuilder.push(newFilterRel) .project(project.getProjects(), project.getRowType().getFieldNames()) .build(); call.transformTo(newProjRel); }