Search in sources :

Example 11 with Quantifier

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();
        }
    }
}
Also used : Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier)

Example 12 with Quantifier

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());
}
Also used : QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) IndexScanParameters(com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) QueryPredicate(com.apple.foundationdb.record.query.predicates.QueryPredicate) RecordQueryScanPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryScanPlan) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) LogicalUnionExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalUnionExpression) LogicalFilterExpression(com.apple.foundationdb.record.query.plan.temp.expressions.LogicalFilterExpression) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) Test(org.junit.jupiter.api.Test)

Example 13 with Quantifier

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);
}
Also used : RecordCoreException(com.apple.foundationdb.record.RecordCoreException) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) Nonnull(javax.annotation.Nonnull)

Example 14 with Quantifier

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);
}
Also used : ExistsPredicate(com.apple.foundationdb.record.query.predicates.ExistsPredicate) Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) SelectExpression(com.apple.foundationdb.record.query.plan.temp.expressions.SelectExpression)

Example 15 with Quantifier

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();
}
Also used : Quantifier(com.apple.foundationdb.record.query.plan.temp.Quantifier) Nullable(javax.annotation.Nullable)

Aggregations

Quantifier (com.apple.foundationdb.record.query.plan.temp.Quantifier)23 Nonnull (javax.annotation.Nonnull)13 API (com.apple.foundationdb.annotation.API)10 ImmutableList (com.google.common.collect.ImmutableList)10 List (java.util.List)9 RelationalExpression (com.apple.foundationdb.record.query.plan.temp.RelationalExpression)8 CorrelationIdentifier (com.apple.foundationdb.record.query.plan.temp.CorrelationIdentifier)7 AliasMap (com.apple.foundationdb.record.query.plan.temp.AliasMap)6 BindingMatcher (com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher)6 QueryPredicate (com.apple.foundationdb.record.query.predicates.QueryPredicate)6 Value (com.apple.foundationdb.record.query.predicates.Value)6 GroupExpressionRef (com.apple.foundationdb.record.query.plan.temp.GroupExpressionRef)5 PlannerRule (com.apple.foundationdb.record.query.plan.temp.PlannerRule)5 PlannerRuleCall (com.apple.foundationdb.record.query.plan.temp.PlannerRuleCall)5 ImmutableSet (com.google.common.collect.ImmutableSet)5 Collection (java.util.Collection)5 Set (java.util.Set)5 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)4 MatchInfo (com.apple.foundationdb.record.query.plan.temp.MatchInfo)4 PartialMatch (com.apple.foundationdb.record.query.plan.temp.PartialMatch)4