use of com.apple.foundationdb.record.query.plan.temp.Quantifier in project fdb-record-layer by FoundationDB.
the class PlannerRepl method printlnExpression.
void printlnExpression(@Nonnull final RelationalExpression expression, final String prefix) {
printlnKeyValue(prefix + "class", expression.getClass().getSimpleName());
getSilently("expression.toString()", expression::toString).ifPresent(expressionAsString -> printlnKeyValue(prefix + "expression", expressionAsString));
printlnKeyValue(prefix + "name", nameForObjectOrNotInCache(expression));
if (expression.getQuantifiers().isEmpty()) {
printlnKeyValue(prefix + "quantifiers", "empty");
} else {
printlnKeyValue(prefix + "quantifiers", "");
for (final Quantifier quantifier : expression.getQuantifiers()) {
printKeyValue(prefix + " name", nameForObjectOrNotInCache(quantifier) + "; ");
printKeyValue("kind", quantifier.getShorthand() + "; ");
printKeyValue("alias", quantifier.getAlias().toString() + "; ");
final ExpressionRef<? extends RelationalExpression> rangesOver = quantifier.getRangesOver();
printKeyValue("ranges over", nameForObjectOrNotInCache(rangesOver));
println();
}
}
}
use of com.apple.foundationdb.record.query.plan.temp.Quantifier in project fdb-record-layer by FoundationDB.
the class ExpressionMatcherTest method treeDescentWithMixedBindings.
@Test
public void treeDescentWithMixedBindings() {
// build a relatively complicated matcher
BindingMatcher<? extends ExpressionRef<? extends RelationalExpression>> filterLeafMatcher = ReferenceMatchers.anyRef();
BindingMatcher<QueryPredicate> predicateMatcher = QueryPredicateMatchers.anyPredicate();
final BindingMatcher<LogicalFilterExpression> filterPlanMatcher = RelationalExpressionMatchers.logicalFilterExpression(MultiMatcher.AllMatcher.all(predicateMatcher), AnyMatcher.any(QuantifierMatchers.forEachQuantifierOverRef(filterLeafMatcher)));
BindingMatcher<RecordQueryScanPlan> scanMatcher = RecordQueryPlanMatchers.scanPlan();
BindingMatcher<LogicalUnionExpression> matcher = RelationalExpressionMatchers.logicalUnionExpression(ListMatcher.exactly(QuantifierMatchers.forEachQuantifier(filterPlanMatcher), QuantifierMatchers.forEachQuantifier(scanMatcher)));
// build a relatively complicated expression
QueryComponent andBranch1 = Query.field("field1").greaterThan(6);
QueryComponent andBranch2 = Query.field("field2").equalsParameter("param");
IndexScanParameters fullValueScan = IndexScanComparisons.byValue();
final Quantifier.ForEach quantifier = Quantifier.forEach(GroupExpressionRef.of(new RecordQueryIndexPlan("an_index", fullValueScan, true)));
LogicalFilterExpression filterPlan = new LogicalFilterExpression(Query.and(andBranch1, andBranch2).expand(quantifier.getAlias()).getPredicates(), quantifier);
RecordQueryScanPlan scanPlan = new RecordQueryScanPlan(ScanComparisons.EMPTY, true);
RelationalExpression root = new LogicalUnionExpression(Quantifiers.forEachQuantifiers(ImmutableList.of(GroupExpressionRef.of(filterPlan), GroupExpressionRef.of(scanPlan))));
assertTrue(filterPlanMatcher.bindMatches(PlannerBindings.empty(), filterPlan).findFirst().isPresent());
// try to bind
Optional<PlannerBindings> possibleBindings = matcher.bindMatches(PlannerBindings.empty(), root).findFirst();
// check that all the bindings match what we expect
assertTrue(possibleBindings.isPresent());
PlannerBindings bindings = possibleBindings.get().mergedWith(getExistingBindings());
assertEquals(root, bindings.get(matcher));
assertEquals(filterPlan, bindings.get(filterPlanMatcher));
assertEquals(scanPlan, bindings.get(scanMatcher));
assertEquals(filterPlan.getPredicates(), bindings.getAll(predicateMatcher));
// dereference
assertEquals(filterPlan.getInner().getRangesOver().get(), bindings.get(filterLeafMatcher).get());
}
use of com.apple.foundationdb.record.query.plan.temp.Quantifier in project fdb-record-layer by FoundationDB.
the class RecordQueryPlan method accept.
// we know the type of the group, even though the compiler doesn't, intentional use of reference equality
@Nonnull
@SuppressWarnings({ "unchecked", "PMD.CompareObjectsWithEquals" })
default RecordQueryPlan accept(@Nonnull RecordQueryPlannerSubstitutionVisitor visitor) {
for (Quantifier childQuantifier : getQuantifiers()) {
if (!(childQuantifier instanceof Quantifier.Physical)) {
throw new RecordCoreException("quantifiers of RecordQueryPlans must be physical");
}
// Group expression is the only type of reference at this point.
GroupExpressionRef<RecordQueryPlan> childGroup = ((GroupExpressionRef) ((Quantifier.Physical) childQuantifier).getRangesOver());
// Group is generated by the RecordQueryPlanner so must have a single member
RecordQueryPlan child = childGroup.get();
RecordQueryPlan modifiedChild = child.accept(visitor);
if (child != modifiedChild) {
// intentional use of reference equality, since equals() might not be conservative enough for plans
childGroup.replace(modifiedChild);
}
}
return visitor.postVisit(this);
}
use of com.apple.foundationdb.record.query.plan.temp.Quantifier in project fdb-record-layer by FoundationDB.
the class OneOfThemWithComparison method expand.
@Override
public GraphExpansion expand(@Nonnull final CorrelationIdentifier baseAlias, @Nonnull final List<String> fieldNamePrefix) {
List<String> fieldNames = ImmutableList.<String>builder().addAll(fieldNamePrefix).add(getFieldName()).build();
final Quantifier childBase = Quantifier.forEach(GroupExpressionRef.of(ExplodeExpression.explodeField(baseAlias, 0, fieldNames)));
final SelectExpression selectExpression = GraphExpansion.ofPredicate(QuantifiedObjectValue.of(childBase.getAlias()).withComparison(comparison)).buildSelectWithBase(childBase);
final Quantifier.Existential childQuantifier = Quantifier.existential(GroupExpressionRef.of(selectExpression));
// create a query component that creates a path to this prefix and then applies this to it
// this is needed for reapplication of the component if the sub query cannot be matched or only matched with
// compensation
QueryComponent withPrefix = this;
for (int i = fieldNamePrefix.size() - 1; i >= 0; i--) {
final String fieldName = fieldNames.get(i);
withPrefix = Query.field(fieldName).matches(withPrefix);
}
return GraphExpansion.ofPredicateAndQuantifier(new ExistsPredicate(childQuantifier.getAlias(), withPrefix), childQuantifier);
}
use of com.apple.foundationdb.record.query.plan.temp.Quantifier in project fdb-record-layer by FoundationDB.
the class PlannerGraph method fromNodeAndChildGraphs.
public static PlannerGraph fromNodeAndChildGraphs(@Nonnull final Node node, @Nonnull final List<? extends PlannerGraph> childGraphs) {
final InternalPlannerGraphBuilder plannerGraphBuilder = builder(node);
// Traverse results from children and create graph edges. Hand in the directly preceding edge
// in the dependsOn set. That in turn causes the dot exporter to render the graph left to right which
// is important for join order, among other things.
final List<? extends Quantifier> quantifiers = tryGetQuantifiers(node);
Edge previousEdge = null;
int i = 0;
for (final PlannerGraph childGraph : childGraphs) {
final GroupExpressionRefEdge edge;
final Set<? extends AbstractEdge> dependsOn = previousEdge == null ? ImmutableSet.of() : ImmutableSet.of(previousEdge);
if (i < quantifiers.size()) {
@Nullable final String label;
final Quantifier quantifier = quantifiers.get(i);
label = Debugger.mapDebugger(debugger -> quantifier.getAlias().getId()).orElse(null);
if (quantifier instanceof Quantifier.Existential) {
edge = new ExistentialQuantifierEdge(label, dependsOn);
} else if (quantifier instanceof Quantifier.ForEach) {
edge = new ForEachQuantifierEdge(label, dependsOn);
} else if (quantifier instanceof Quantifier.Physical) {
edge = new PhysicalQuantifierEdge(label, dependsOn);
} else {
edge = new GroupExpressionRefEdge(label, dependsOn);
}
} else {
edge = new GroupExpressionRefEdge(null, dependsOn);
}
plannerGraphBuilder.addGraph(childGraph).addEdge(childGraph.getRoot(), plannerGraphBuilder.getRoot(), edge);
previousEdge = edge;
i += 1;
}
return plannerGraphBuilder.build();
}
Aggregations