Skip to content

Commit d910c99

Browse files
committed
code complete
1 parent 6ceef54 commit d910c99

21 files changed

+160
-56
lines changed

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/BooleanWithConstraint.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ public BooleanWithConstraint composeWithOther(@Nonnull final BooleanWithConstrai
124124
* the {@code constraint}
125125
*/
126126
@Nonnull
127+
@Override
127128
public BooleanWithConstraint composeWithConstraint(@Nonnull final QueryPlanConstraint constraint) {
128129
if (!this.isTrue()) {
129130
return falseValue();

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/Constrained.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ default T getUnconstrained() {
5757
* the {@code constraint}
5858
*/
5959
@Nonnull
60-
Constrained<T> composeWithConstraint(@Nonnull final QueryPlanConstraint constraint);
60+
Constrained<T> composeWithConstraint(@Nonnull QueryPlanConstraint constraint);
6161

6262
/**
6363
* Helper method to create an unconstrained wrapper.

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/simplification/AbsorptionRule.java

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222

2323
import com.apple.foundationdb.annotation.API;
2424
import com.apple.foundationdb.record.RecordCoreException;
25+
import com.apple.foundationdb.record.query.plan.cascades.LinkedIdentitySet;
2526
import com.apple.foundationdb.record.query.plan.cascades.matching.structure.BindingMatcher;
2627
import com.apple.foundationdb.record.query.plan.cascades.predicates.AndOrPredicate;
2728
import com.apple.foundationdb.record.query.plan.cascades.predicates.AndPredicate;
2829
import com.apple.foundationdb.record.query.plan.cascades.predicates.OrPredicate;
2930
import com.apple.foundationdb.record.query.plan.cascades.predicates.QueryPredicate;
3031
import com.apple.foundationdb.record.query.plan.planning.BooleanPredicateNormalizer;
3132
import com.google.common.collect.Lists;
33+
import com.google.common.collect.Sets;
3234

3335
import javax.annotation.Nonnull;
3436
import java.util.Collection;
@@ -87,15 +89,29 @@ public void onMatch(@Nonnull final QueryPredicateSimplificationRuleCall call) {
8789
})
8890
.collect(Collectors.toList());
8991

90-
final int numberOfMajors = majorTerms.size();
91-
BooleanPredicateNormalizer.applyAbsorptionLaw(majorOfMinors);
92-
if (majorOfMinors.size() < numberOfMajors) {
92+
final var absorbed = BooleanPredicateNormalizer.applyAbsorptionLaw(majorOfMinors);
93+
if (absorbed.size() < majorOfMinors.size()) {
9394
final var simplifiedPredicate =
94-
with(majorClass, majorOfMinors
95-
.stream()
96-
.map(minor -> with(minorClass, minor))
97-
.collect(Collectors.toList()));
98-
call.yieldResult(simplifiedPredicate);
95+
with(majorClass,
96+
absorbed.stream()
97+
.map(minor -> with(minorClass, minor))
98+
.collect(Collectors.toList()));
99+
100+
// Find all predicates that have not been retained
101+
final var allMajorOfMinors =
102+
majorOfMinors.stream()
103+
.flatMap(Collection::stream)
104+
.collect(LinkedIdentitySet.toLinkedIdentitySet());
105+
106+
final var retainedMajorOfMinors =
107+
absorbed.stream()
108+
.flatMap(Collection::stream)
109+
.collect(LinkedIdentitySet.toLinkedIdentitySet());
110+
111+
call.yieldResultBuilder()
112+
.addConstraintsFrom(bindings.get(getMatcher()))
113+
.addConstraintsFrom(Sets.difference(allMajorOfMinors, retainedMajorOfMinors))
114+
.yieldResult(simplifiedPredicate);
99115
}
100116
}
101117

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/simplification/AnnulmentAndRule.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,13 @@ public Optional<Class<?>> getRootOperator() {
5959
@Override
6060
public void onMatch(@Nonnull final QueryPredicateSimplificationRuleCall call) {
6161
final var bindings = call.getBindings();
62-
final var terms = bindings.getAll(andTermMatcher);
62+
final var andTerms = bindings.getAll(andTermMatcher);
6363

64-
if (terms.stream().anyMatch(QueryPredicate::isContradiction)) {
65-
call.yieldResult(new ConstantPredicate(false));
64+
if (andTerms.stream().anyMatch(QueryPredicate::isContradiction)) {
65+
call.yieldResultBuilder()
66+
.addConstraintsFrom(bindings.get(rootMatcher))
67+
.addConstraintsFrom(andTerms)
68+
.yieldResult(new ConstantPredicate(false));
6669
}
6770
}
6871
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/simplification/AnnulmentOrRule.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ public void onMatch(@Nonnull final QueryPredicateSimplificationRuleCall call) {
6363
final var orTerms = bindings.getAll(orTermMatcher);
6464

6565
if (orTerms.stream().anyMatch(QueryPredicate::isTautology)) {
66-
call.yieldResult(new ConstantPredicate(true));
66+
call.yieldResultBuilder()
67+
.addConstraintsFrom(bindings.get(rootMatcher))
68+
.addConstraintsFrom(orTerms)
69+
.yieldResult(new ConstantPredicate(true));
6770
}
6871
}
6972
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/simplification/DeMorgansTheoremRule.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,16 @@ public class DeMorgansTheoremRule<P extends AndOrPredicate> extends QueryPredica
5252
private final Class<P> majorClass;
5353
@Nonnull
5454
private final BindingMatcher<QueryPredicate> termMatcher;
55+
@Nonnull
56+
private final BindingMatcher<P> andOrPredicateMatcher;
5557

5658
public DeMorgansTheoremRule(@Nonnull final Class<P> majorClass,
5759
@Nonnull final BindingMatcher<QueryPredicate> termMatcher,
60+
@Nonnull final BindingMatcher<P> andOrPredicateMatcher,
5861
@Nonnull final BindingMatcher<NotPredicate> rootMatcher) {
5962
super(rootMatcher);
6063
this.majorClass = majorClass;
64+
this.andOrPredicateMatcher = andOrPredicateMatcher;
6165
this.termMatcher = termMatcher;
6266
}
6367

@@ -77,7 +81,9 @@ public void onMatch(@Nonnull final QueryPredicateSimplificationRuleCall call) {
7781
.map(NotPredicate::not)
7882
.collect(ImmutableList.toImmutableList());
7983

80-
call.yieldAndReExplore(minorWith(minorTerms));
84+
call.yieldResultBuilder()
85+
.addConstraintsFrom(bindings.get(getMatcher()), bindings.get(andOrPredicateMatcher))
86+
.yieldResultAndReExplore(minorWith(minorTerms));
8187
}
8288

8389
private QueryPredicate minorWith(@Nonnull final Collection<? extends QueryPredicate> terms) {
@@ -94,6 +100,7 @@ public static <P extends AndOrPredicate> DeMorgansTheoremRule<P> withMajor(@Nonn
94100
final var andOrPredicateMatcher = ofTypeWithChildren(majorClass, all(termMatcher));
95101
return new DeMorgansTheoremRule<>(majorClass,
96102
termMatcher,
103+
andOrPredicateMatcher,
97104
notPredicate(ListMatcher.exactly(andOrPredicateMatcher)));
98105
}
99106
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/simplification/IdentityAndRule.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public void onMatch(@Nonnull final QueryPredicateSimplificationRuleCall call) {
6262
final var terms = bindings.getAll(andTermMatcher);
6363

6464
final var resultTermsBuilder = ImmutableList.<QueryPredicate>builder();
65+
final var removedTermsBuilder = ImmutableList.<QueryPredicate>builder();
6566
int count = 0;
6667
for (final var term : terms) {
6768
if (!term.isTautology()) {
@@ -72,10 +73,15 @@ public void onMatch(@Nonnull final QueryPredicateSimplificationRuleCall call) {
7273

7374
// term is still needed
7475
resultTermsBuilder.add(term);
76+
} else {
77+
removedTermsBuilder.add(term);
7578
}
7679
}
7780
final var resultTerms = resultTermsBuilder.build();
7881
final var simplifiedPredicate = AndPredicate.and(resultTerms);
79-
call.yieldResult(simplifiedPredicate);
82+
call.yieldResultBuilder()
83+
.addConstraintsFrom(bindings.get(rootMatcher))
84+
.addConstraintsFrom(removedTermsBuilder.build())
85+
.yieldResult(simplifiedPredicate);
8086
}
8187
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/simplification/IdentityOrRule.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ public void onMatch(@Nonnull final QueryPredicateSimplificationRuleCall call) {
6262
final var terms = bindings.getAll(orTermMatcher);
6363

6464
final var resultTermsBuilder = ImmutableList.<QueryPredicate>builder();
65+
final var removedTermsBuilder = ImmutableList.<QueryPredicate>builder();
66+
6567
int count = 0;
6668
for (final var term : terms) {
6769
if (!term.isContradiction()) {
@@ -72,10 +74,15 @@ public void onMatch(@Nonnull final QueryPredicateSimplificationRuleCall call) {
7274

7375
// term is still needed
7476
resultTermsBuilder.add(term);
77+
} else {
78+
removedTermsBuilder.add(term);
7579
}
7680
}
7781
final var resultTerms = resultTermsBuilder.build();
7882
final var simplifiedPredicate = OrPredicate.orOrFalse(resultTerms);
79-
call.yieldResult(simplifiedPredicate);
83+
call.yieldResultBuilder()
84+
.addConstraintsFrom(bindings.get(rootMatcher))
85+
.addConstraintsFrom(removedTermsBuilder.build())
86+
.yieldResult(simplifiedPredicate);
8087
}
8188
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/simplification/NormalFormRule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public void onMatch(@Nonnull final QueryPredicateSimplificationRuleCall call) {
6464

6565
final var normalizedPredicateMaybe = normalizer.normalize(predicate, false);
6666
normalizedPredicateMaybe.ifPresent(normalizedPredicate ->
67-
call.yieldAndReExplore(normalizedPredicateMaybe.get()));
67+
// note that dues to the nature of this rule and it being run first we won't use constraints here
68+
call.yieldResultAndReExplore(normalizedPredicateMaybe.get()));
6869
}
6970
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/simplification/NotOverComparisonRule.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ public void onMatch(@Nonnull final QueryPredicateSimplificationRuleCall call) {
7373
return;
7474
}
7575

76-
call.yieldResult(new ValuePredicate(value, comparison.withType(invertedComparisonType)));
76+
call.yieldResultBuilder()
77+
.addConstraintsFrom(bindings.get(rootMatcher))
78+
.addConstraintsFrom(bindings.getAll(anyValuePredicateMatcher))
79+
.yieldResult(new ValuePredicate(value, comparison.withType(invertedComparisonType)));
7780
}
7881
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/predicates/simplification/QueryPredicateComputationRuleCall.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,4 @@ public ARGUMENT getArgument() {
7575
public Pair<QueryPredicate, RESULT> getResult(@Nonnull final QueryPredicate predicate) {
7676
return retrieveResultFunction.apply(predicate);
7777
}
78-
79-
public void yieldPredicate(@Nonnull final QueryPredicate predicate, @Nonnull final RESULT result) {
80-
super.yieldResult(NonnullPair.of(predicate, result));
81-
}
82-
83-
public void yieldPredicateAndReExplore(@Nonnull final QueryPredicate predicate, @Nonnull final RESULT result) {
84-
super.yieldAndReExplore(NonnullPair.of(predicate, result));
85-
}
8678
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/AbstractRuleCall.java

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,13 @@
3232
import com.apple.foundationdb.record.query.plan.cascades.values.Value;
3333
import com.google.common.base.Verify;
3434
import com.google.common.collect.ImmutableSet;
35+
import com.google.common.collect.Lists;
36+
import com.google.common.collect.Streams;
3537

3638
import javax.annotation.Nonnull;
3739
import java.util.Collection;
3840
import java.util.Collections;
41+
import java.util.List;
3942
import java.util.Set;
4043
import java.util.function.Function;
4144

@@ -152,7 +155,6 @@ public Set<CorrelationIdentifier> getConstantAliases() {
152155
return constantAliases;
153156
}
154157

155-
@SuppressWarnings("PMD.CompareObjectsWithEquals") // deliberate use of == equality check for short-circuit condition
156158
public void yieldResult(@Nonnull final RESULT value) {
157159
yieldResult(value, QueryPlanConstraint.noConstraint());
158160
}
@@ -169,15 +171,14 @@ public void yieldResult(@Nonnull final RESULT value,
169171
results.add(value);
170172
}
171173

172-
@SuppressWarnings("PMD.CompareObjectsWithEquals")
173-
public void yieldAndReExplore(@Nonnull final RESULT value) {
174-
yieldAndReExplore(value, QueryPlanConstraint.noConstraint());
174+
public void yieldResultAndReExplore(@Nonnull final RESULT value) {
175+
yieldResultAndReExplore(value, QueryPlanConstraint.noConstraint());
175176
}
176177

177178

178179
@SuppressWarnings("PMD.CompareObjectsWithEquals")
179-
public void yieldAndReExplore(@Nonnull RESULT value,
180-
@Nonnull final QueryPlanConstraint additionalQueryPlanConstraint) {
180+
public void yieldResultAndReExplore(@Nonnull RESULT value,
181+
@Nonnull final QueryPlanConstraint additionalQueryPlanConstraint) {
181182
Verify.verify(value != current);
182183
if (resultQueryPlanConstraint.isConstrained()) {
183184
this.resultQueryPlanConstraint = resultQueryPlanConstraint.compose(additionalQueryPlanConstraint);
@@ -199,4 +200,48 @@ public Collection<RESULT> getResults() {
199200
public boolean shouldReExplore() {
200201
return shouldReExplore;
201202
}
203+
204+
@Nonnull
205+
public YieldResultBuilder yieldResultBuilder() {
206+
return new YieldResultBuilder();
207+
}
208+
209+
public final class YieldResultBuilder {
210+
@Nonnull
211+
private final List<BASE> bases;
212+
213+
public YieldResultBuilder() {
214+
this.bases = Lists.newArrayList();
215+
}
216+
217+
@SuppressWarnings({"UseBulkOperation", "ManualArrayToCollectionCopy"}) // due to varargs warning when using bulk operations
218+
@SafeVarargs
219+
public final YieldResultBuilder addConstraintsFrom(@Nonnull final BASE... additionalBases) {
220+
for (final var additionalBase : additionalBases) {
221+
bases.add(additionalBase);
222+
}
223+
return this;
224+
}
225+
226+
public YieldResultBuilder addConstraintsFrom(@Nonnull Iterable<? extends BASE> additionalBases) {
227+
Streams.stream(additionalBases).forEach(bases::add);
228+
return this;
229+
}
230+
231+
public void yieldResult(@Nonnull final RESULT value) {
232+
AbstractRuleCall.this.yieldResult(value, computeConstraintFromBases());
233+
}
234+
235+
public void yieldResultAndReExplore(@Nonnull final RESULT value) {
236+
AbstractRuleCall.this.yieldResultAndReExplore(value, computeConstraintFromBases());
237+
}
238+
239+
@Nonnull
240+
private QueryPlanConstraint computeConstraintFromBases() {
241+
return bases.stream()
242+
.map(AbstractRuleCall.this::getQueryPlanConstraint)
243+
.reduce(QueryPlanConstraint::compose)
244+
.orElse(QueryPlanConstraint.noConstraint());
245+
}
246+
}
202247
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/CollapseRecordConstructorOverFieldsToStarRule.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ public void onMatch(@Nonnull final ValueSimplificationRuleCall call) {
100100
}
101101
}
102102

103-
call.yieldResult(Objects.requireNonNull(commonChildValue));
103+
call.yieldResultBuilder()
104+
.addConstraintsFrom(recordConstructorValue)
105+
.addConstraintsFrom(fieldValues)
106+
.yieldResult(Objects.requireNonNull(commonChildValue));
104107
}
105108
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/ComposeFieldValueOverFieldValueRule.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ public void onMatch(@Nonnull final ValueSimplificationRuleCall call) {
8989
Verify.verify(child instanceof FieldValue);
9090
Verify.verify(!outerFieldPathOrdinals.isEmpty());
9191
Verify.verify(!outerFieldPathTypes.isEmpty());
92-
call.yieldResult(FieldValue.ofFields(grandChild, ((FieldValue)(child)).getFieldPath().withSuffix(outer.getFieldPath())));
92+
call.yieldResultBuilder()
93+
.addConstraintsFrom(outer, child)
94+
.yieldResult(FieldValue.ofFields(grandChild,
95+
((FieldValue)(child)).getFieldPath().withSuffix(outer.getFieldPath())));
9396
}
9497
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/ComposeFieldValueOverRecordConstructorRule.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ public void onMatch(@Nonnull final ValueSimplificationRuleCall call) {
8484
final var column = findColumn(recordConstructor, firstFieldOrdinal, fieldFieldType);
8585

8686
final var root = bindings.get(rootMatcher);
87-
final var constraint =
88-
call.getQueryPlanConstraint(root)
89-
.compose(call.getQueryPlanConstraint(recordConstructor));
87+
final var yieldResultBuilder =
88+
call.yieldResultBuilder()
89+
.addConstraintsFrom(root, recordConstructor);
9090
if (fieldPathOrdinals.size() == 1) {
9191
// just return the child
92-
call.yieldResult(column.getValue(), constraint);
92+
yieldResultBuilder.yieldResult(column.getValue());
9393
} else {
94-
call.yieldResult(FieldValue.ofFields(column.getValue(), root.getFieldPath().subList(1)), constraint);
94+
yieldResultBuilder.yieldResult(FieldValue.ofFields(column.getValue(), root.getFieldPath().subList(1)));
9595
}
9696
}
9797

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/EliminateArithmeticValueWithConstantRule.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,15 @@ public void onMatch(@Nonnull final ValueSimplificationRuleCall call) {
9090
return;
9191
}
9292

93+
final var yieldBuilder = call.yieldResultBuilder();
9394
if (constantAliases.containsAll(children.get(0).getCorrelatedTo())) {
9495
// this first child is the constant one, the second child is not
95-
call.yieldResult(children.get(1));
96+
yieldBuilder.addConstraintsFrom(arithmeticValue, children.get(0))
97+
.yieldResult(children.get(1));
9698
} else if (constantAliases.containsAll(children.get(1).getCorrelatedTo())) {
9799
// this second child is the constant one, the first child is not
98-
call.yieldResult(children.get(0));
100+
yieldBuilder.addConstraintsFrom(arithmeticValue, children.get(1))
101+
.yieldResult(children.get(0));
99102
} // else they are both not constant
100103
}
101104
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/ExpandFusedFieldValueRule.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public void onMatch(@Nonnull final ValueSimplificationRuleCall call) {
6969
ofFields(ofFields(fieldValue.getChild(), fieldPath.getFieldPrefix()),
7070
new FieldPath(ImmutableList.of(lastAccessor)));
7171

72-
call.yieldAndReExplore(expandedFieldValue);
72+
call.yieldResultBuilder()
73+
.addConstraintsFrom(fieldValue)
74+
.yieldResultAndReExplore(expandedFieldValue);
7375
}
7476
}

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/values/simplification/ExpandRecordRule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,6 @@ public void onMatch(@Nonnull final ValueSimplificationRuleCall call) {
9696
final var resultValue =
9797
RecordConstructorValue.ofColumns(resultBuilder.build(), originalResultType.isNullable());
9898
Verify.verify(originalResultType.isNullable() == resultValue.getResultType().isNullable());
99-
call.yieldAndReExplore(resultValue);
99+
call.yieldResultBuilder().addConstraintsFrom(value).yieldResultAndReExplore(resultValue);
100100
}
101101
}

0 commit comments

Comments
 (0)