diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/CollapseNullStrictValueOverNullValueRule.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/CollapseNullStrictValueOverNullValueRule.java
index da343a050a..22bd6eeb26 100644
--- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/CollapseNullStrictValueOverNullValueRule.java
+++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/CollapseNullStrictValueOverNullValueRule.java
@@ -23,18 +23,10 @@
import com.apple.foundationdb.annotation.API;
import com.apple.foundationdb.record.query.plan.cascades.matching.structure.BindingMatcher;
import com.apple.foundationdb.record.query.plan.cascades.values.ArithmeticValue;
-import com.apple.foundationdb.record.query.plan.cascades.values.CastValue;
-import com.apple.foundationdb.record.query.plan.cascades.values.FieldValue;
-import com.apple.foundationdb.record.query.plan.cascades.values.NotValue;
import com.apple.foundationdb.record.query.plan.cascades.values.NullValue;
-import com.apple.foundationdb.record.query.plan.cascades.values.PromoteValue;
-import com.apple.foundationdb.record.query.plan.cascades.values.SubscriptValue;
import com.apple.foundationdb.record.query.plan.cascades.values.Value;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Streams;
import javax.annotation.Nonnull;
-import java.util.Optional;
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.TypedMatcherWithPredicate.typedMatcherWithPredicate;
@@ -42,45 +34,41 @@
* A rule that collapses a {@link Value} into a {@link NullValue} if it is strictly null-propagating and has at least
* one child that is a {@link NullValue}. A {@code Value} class is strictly null-propagating if it produces a
* null result when any child evaluates to null. For example, arithmetic operators ({@link ArithmeticValue}) yield null
- * when either operand is null. For the particular classes that are considered by this rule, see {@link #VALUE_CLASSES}.
+ * when either operand is null.
+ *
+ *
The rule is parameterized over the concrete, strictly null-propagating {@link Value} subclass. This way it can use
+ * a typed matcher for the specific class and benefit from the rule index in the rule set.
+ *
+ * @param the {@link Value} subclass that this rule instance matches
*/
@API(API.Status.EXPERIMENTAL)
-public class CollapseNullStrictValueOverNullValueRule extends ValueSimplificationRule {
-
- /**
- * {@link Value} subclasses that are considered to be strictly null-propagating by this rule.
- */
- @Nonnull
- private static final ImmutableSet> VALUE_CLASSES = ImmutableSet.of(
- ArithmeticValue.class,
- CastValue.class,
- FieldValue.class,
- NotValue.class,
- PromoteValue.class,
- SubscriptValue.class);
+public final class CollapseNullStrictValueOverNullValueRule extends ValueSimplificationRule {
@Nonnull
- private static final BindingMatcher rootMatcher = typedMatcherWithPredicate(Value.class,
- v -> VALUE_CLASSES.contains(v.getClass()) && hasNullValueChild(v));
+ private final BindingMatcher rootMatcher;
- public CollapseNullStrictValueOverNullValueRule() {
- super(rootMatcher);
+ public CollapseNullStrictValueOverNullValueRule(@Nonnull final Class valueClass) {
+ this(typedMatcherWithPredicate(valueClass, CollapseNullStrictValueOverNullValueRule::hasNullValueChild));
}
- @Nonnull
- @Override
- public Optional> getRootOperator() {
- return Optional.empty();
+ private CollapseNullStrictValueOverNullValueRule(@Nonnull final BindingMatcher rootMatcher) {
+ super(rootMatcher);
+ this.rootMatcher = rootMatcher;
}
@Override
public void onMatch(@Nonnull final ValueSimplificationRuleCall call) {
- final Value value = call.getBindings().get(rootMatcher);
+ final V value = call.getBindings().get(rootMatcher);
// Note that the `NullValue` will always have a nullable result type even if the value’s result type is not.
call.yieldResult(new NullValue(value.getResultType()));
}
private static boolean hasNullValueChild(@Nonnull final Value value) {
- return Streams.stream(value.getChildren()).anyMatch(NullValue.class::isInstance);
+ for (final Value child : value.getChildren()) {
+ if (child instanceof NullValue) {
+ return true;
+ }
+ }
+ return false;
}
}
diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/DefaultValueSimplificationRuleSet.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/DefaultValueSimplificationRuleSet.java
index de8a0db738..9ee6c99cea 100644
--- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/DefaultValueSimplificationRuleSet.java
+++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/DefaultValueSimplificationRuleSet.java
@@ -21,6 +21,12 @@
package com.apple.foundationdb.record.query.plan.cascades.values.simplification;
import com.apple.foundationdb.annotation.API;
+import com.apple.foundationdb.record.query.plan.cascades.values.ArithmeticValue;
+import com.apple.foundationdb.record.query.plan.cascades.values.CastValue;
+import com.apple.foundationdb.record.query.plan.cascades.values.FieldValue;
+import com.apple.foundationdb.record.query.plan.cascades.values.NotValue;
+import com.apple.foundationdb.record.query.plan.cascades.values.PromoteValue;
+import com.apple.foundationdb.record.query.plan.cascades.values.SubscriptValue;
import com.apple.foundationdb.record.query.plan.cascades.values.Value;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
@@ -36,7 +42,17 @@
@SuppressWarnings("java:S1452")
public class DefaultValueSimplificationRuleSet extends AbstractValueRuleSet {
@Nonnull
- protected static final ValueSimplificationRule extends Value> collapseNullStrictValueOverNullValueRule = new CollapseNullStrictValueOverNullValueRule();
+ protected static final ValueSimplificationRule extends Value> collapseNullStrictArithmeticValueOverNullValueRule = new CollapseNullStrictValueOverNullValueRule<>(ArithmeticValue.class);
+ @Nonnull
+ protected static final ValueSimplificationRule extends Value> collapseNullStrictCastValueOverNullValueRule = new CollapseNullStrictValueOverNullValueRule<>(CastValue.class);
+ @Nonnull
+ protected static final ValueSimplificationRule extends Value> collapseNullStrictFieldValueOverNullValueRule = new CollapseNullStrictValueOverNullValueRule<>(FieldValue.class);
+ @Nonnull
+ protected static final ValueSimplificationRule extends Value> collapseNullStrictNotValueOverNullValueRule = new CollapseNullStrictValueOverNullValueRule<>(NotValue.class);
+ @Nonnull
+ protected static final ValueSimplificationRule extends Value> collapseNullStrictPromoteValueOverNullValueRule = new CollapseNullStrictValueOverNullValueRule<>(PromoteValue.class);
+ @Nonnull
+ protected static final ValueSimplificationRule extends Value> collapseNullStrictSubscriptValueOverNullValueRule = new CollapseNullStrictValueOverNullValueRule<>(SubscriptValue.class);
@Nonnull
protected static final ValueSimplificationRule extends Value> composeFieldValueOverRecordConstructorRule = new ComposeFieldValueOverRecordConstructorRule();
@Nonnull
@@ -48,7 +64,12 @@ public class DefaultValueSimplificationRuleSet extends AbstractValueRuleSet> SIMPLIFICATION_RULES = ImmutableSet.of(
- collapseNullStrictValueOverNullValueRule,
+ collapseNullStrictArithmeticValueOverNullValueRule,
+ collapseNullStrictCastValueOverNullValueRule,
+ collapseNullStrictFieldValueOverNullValueRule,
+ collapseNullStrictNotValueOverNullValueRule,
+ collapseNullStrictPromoteValueOverNullValueRule,
+ collapseNullStrictSubscriptValueOverNullValueRule,
composeFieldValueOverRecordConstructorRule,
composeFieldValueOverFieldValueRule,
collapseRecordConstructorOverFieldsToStarRule);