This is an automated email from the ASF dual-hosted git repository.
zabetak pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new f32289870b [CALCITE-5705] Generalize RemoveEmptySingleRule to work
with arbitrary relations and pruning configurations
f32289870b is described below
commit f32289870be80e69dabc5b7e24bd6c777d4eb688
Author: Stamatis Zampetakis <[email protected]>
AuthorDate: Tue May 16 15:19:12 2023 +0200
[CALCITE-5705] Generalize RemoveEmptySingleRule to work with arbitrary
relations and pruning configurations
1. Remove cast to `SingleRel` inside `RemoveEmptySingleRule#onMatch` to
allow the rule to transform arbitrary relations (such as `Correlate`)
to empty.
2. Change `RemoveEmptySingleRule` constructor to accept
`PruneEmptyRule.Config` instead of `RemoveEmptySingleRuleConfig` to
be able to instatiate the rule from any kind of pruning configuration
that aims to tranform a relation to empty.
3. Refactor `CorrelateLeftEmptyRuleConfig`, `ZeroMaxRowsRuleConfig` and
`SortFetchZeroRuleConfig` to use `RemoveEmptySingleRule` and remove
duplicate code.
Close apache/calcite#3205
---
.../apache/calcite/rel/rules/PruneEmptyRules.java | 57 ++++++++--------------
1 file changed, 20 insertions(+), 37 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/rel/rules/PruneEmptyRules.java
b/core/src/main/java/org/apache/calcite/rel/rules/PruneEmptyRules.java
index 1b2c10f4aa..bd5a9e8c27 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/PruneEmptyRules.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/PruneEmptyRules.java
@@ -280,11 +280,21 @@ public abstract class PruneEmptyRules {
public static final RelOptRule CORRELATE_LEFT_INSTANCE =
CorrelateLeftEmptyRuleConfig.DEFAULT.toRule();
- /** Planner rule that converts a single-rel (e.g. project, sort, aggregate or
- * filter) on top of the empty relational expression into empty. */
+ /**
+ * Rule that converts a relation into empty.
+ * <p>
+ * The users can control the application of the rule by:</p>
+ * <ul>
+ * <li>calling the appropriate constructor and passing the necessary
configuration;</li>
+ * <li>extending the class through inheritance and overriding
+ * {@link RemoveEmptySingleRule#matches(RelOptRuleCall)}).</li>
+ * </ul>
+ *
+ * <p>When using the deprecated constructors it is only possible to convert
relations
+ * which strictly have a single input ({@link SingleRel}).</p>*/
public static class RemoveEmptySingleRule extends PruneEmptyRule {
/** Creates a RemoveEmptySingleRule. */
- RemoveEmptySingleRule(RemoveEmptySingleRuleConfig config) {
+ RemoveEmptySingleRule(PruneEmptyRule.Config config) {
super(config);
}
@@ -318,7 +328,7 @@ public abstract class PruneEmptyRules {
}
@Override public void onMatch(RelOptRuleCall call) {
- SingleRel singleRel = call.rel(0);
+ RelNode singleRel = call.rel(0);
RelNode emptyValues = call.builder().push(singleRel).empty().build();
RelTraitSet traits = singleRel.getTraitSet();
// propagate all traits (except convention) from the original singleRel
into the empty values
@@ -473,21 +483,12 @@ public abstract class PruneEmptyRules {
.withDescription("PruneSortLimit0");
@Override default PruneEmptyRule toRule() {
- return new PruneEmptyRule(this) {
- @Override public void onMatch(RelOptRuleCall call) {
+ return new RemoveEmptySingleRule(this) {
+ @Override public boolean matches(final RelOptRuleCall call) {
Sort sort = call.rel(0);
- if (sort.fetch != null
+ return sort.fetch != null
&& !(sort.fetch instanceof RexDynamicParam)
- && RexLiteral.intValue(sort.fetch) == 0) {
- RelNode emptyValues = call.builder().push(sort).empty().build();
- RelTraitSet traits = sort.getTraitSet();
- // propagate all traits (except convention) from the original sort
into the empty values
- if (emptyValues.getConvention() != null) {
- traits = traits.replace(emptyValues.getConvention());
- }
- emptyValues = emptyValues.copy(traits, Collections.emptyList());
- call.transformTo(emptyValues);
- }
+ && RexLiteral.intValue(sort.fetch) == 0;
}
};
@@ -582,12 +583,7 @@ public abstract class PruneEmptyRules {
b2 -> b2.operand(RelNode.class).anyInputs()))
.withDescription("PruneEmptyCorrelate(left)");
@Override default PruneEmptyRule toRule() {
- return new PruneEmptyRule(this) {
- @Override public void onMatch(RelOptRuleCall call) {
- final Correlate corr = call.rel(0);
- call.transformTo(call.builder().push(corr).empty().build());
- }
- };
+ return new RemoveEmptySingleRule(this);
}
}
@@ -639,25 +635,12 @@ public abstract class PruneEmptyRules {
.withDescription("PruneZeroRowsTable");
@Override default PruneEmptyRule toRule() {
- return new PruneEmptyRule(this) {
+ return new RemoveEmptySingleRule(this) {
@Override public boolean matches(RelOptRuleCall call) {
RelNode node = call.rel(0);
Double maxRowCount = call.getMetadataQuery().getMaxRowCount(node);
return maxRowCount != null && maxRowCount == 0.0;
}
-
- @Override public void onMatch(RelOptRuleCall call) {
- RelNode node = call.rel(0);
- RelNode emptyValues = call.builder().push(node).empty().build();
- RelTraitSet traits = node.getTraitSet();
- // propagate all traits (except convention) from the original
tableScan
- // into the empty values
- if (emptyValues.getConvention() != null) {
- traits = traits.replace(emptyValues.getConvention());
- }
- emptyValues = emptyValues.copy(traits, Collections.emptyList());
- call.transformTo(emptyValues);
- }
};
}
}