Search in sources :

Example 1 with KeyExpression

use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.

the class RecordQueryPlanner method planFilterForInJoin.

private ScoredPlan planFilterForInJoin(@Nonnull PlanContext planContext, @Nonnull QueryComponent filter, boolean needOrdering) {
    planContext.rankComparisons = new RankComparisons(filter, planContext.indexes);
    List<ScoredPlan> intersectionCandidates = new ArrayList<>();
    ScoredPlan bestPlan = null;
    Index bestIndex = null;
    if (planContext.commonPrimaryKey != null) {
        bestPlan = planIndex(planContext, filter, null, planContext.commonPrimaryKey, intersectionCandidates);
    }
    for (Index index : planContext.indexes) {
        KeyExpression indexKeyExpression = indexKeyExpressionForPlan(planContext.commonPrimaryKey, index);
        ScoredPlan p = planIndex(planContext, filter, index, indexKeyExpression, intersectionCandidates);
        if (p != null) {
            // * need for type filtering if row scan with multiple types.
            if (isBetterThanOther(planContext, p, index, bestPlan, bestIndex)) {
                bestPlan = p;
                bestIndex = index;
            }
        }
    }
    if (bestPlan != null) {
        if (bestPlan.getNumNonSargables() > 0) {
            bestPlan = handleNonSargables(bestPlan, intersectionCandidates, planContext);
        }
        if (needOrdering) {
            bestPlan.planOrderingKey = PlanOrderingKey.forPlan(metaData, bestPlan.plan, planContext.commonPrimaryKey);
        }
    }
    return bestPlan;
}
Also used : RankComparisons(com.apple.foundationdb.record.query.plan.planning.RankComparisons) ArrayList(java.util.ArrayList) RecordTypeKeyExpression(com.apple.foundationdb.record.metadata.expressions.RecordTypeKeyExpression) VersionKeyExpression(com.apple.foundationdb.record.metadata.expressions.VersionKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) Index(com.apple.foundationdb.record.metadata.Index)

Example 2 with KeyExpression

use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.

the class RecordQueryPlanner method planUnorderedUnion.

@Nullable
private ScoredPlan planUnorderedUnion(@Nonnull PlanContext planContext, @Nonnull List<ScoredPlan> subplans) {
    final KeyExpression sort = planContext.query.getSort();
    if (sort != null) {
        return null;
    }
    List<RecordQueryPlan> childPlans = new ArrayList<>(subplans.size());
    Set<RankComparisons.RankComparison> includedRankComparisons = null;
    for (ScoredPlan subplan : subplans) {
        childPlans.add(subplan.plan);
        includedRankComparisons = mergeRankComparisons(includedRankComparisons, subplan.includedRankComparisons);
    }
    final RecordQueryUnorderedUnionPlan unionPlan = RecordQueryUnorderedUnionPlan.from(childPlans);
    if (unionPlan.getComplexity() > configuration.getComplexityThreshold()) {
        throw new RecordQueryPlanComplexityException(unionPlan);
    }
    return new ScoredPlan(unionPlan, Collections.emptyList(), Collections.emptyList(), 1, true, includedRankComparisons);
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RecordTypeKeyExpression(com.apple.foundationdb.record.metadata.expressions.RecordTypeKeyExpression) VersionKeyExpression(com.apple.foundationdb.record.metadata.expressions.VersionKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) ArrayList(java.util.ArrayList) RecordQueryUnorderedUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnorderedUnionPlan) Nullable(javax.annotation.Nullable)

Example 3 with KeyExpression

use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.

the class RecordQueryPlanner method handleNonSargables.

@Nonnull
private ScoredPlan handleNonSargables(@Nonnull ScoredPlan bestPlan, @Nonnull List<ScoredPlan> intersectionCandidates, @Nonnull PlanContext planContext) {
    if (planContext.commonPrimaryKey != null && !intersectionCandidates.isEmpty()) {
        KeyExpression comparisonKey = planContext.commonPrimaryKey;
        final KeyExpression sort = planContext.query.getSort();
        comparisonKey = getKeyForMerge(sort, comparisonKey);
        ScoredPlan intersectionPlan = planIntersection(intersectionCandidates, comparisonKey);
        if (intersectionPlan != null) {
            if (intersectionPlan.unsatisfiedFilters.isEmpty()) {
                return intersectionPlan;
            } else if (bestPlan.getNumNonSargables() > intersectionPlan.getNumNonSargables()) {
                bestPlan = intersectionPlan;
            }
        }
    }
    if (bestPlan.getNumNonSargables() > 0) {
        final RecordQueryPlan filtered = new RecordQueryFilterPlan(bestPlan.plan, planContext.rankComparisons.planComparisonSubstitutes(bestPlan.combineNonSargables()));
        // TODO: further optimization requires knowing which filters are satisfied
        return new ScoredPlan(filtered, Collections.emptyList(), Collections.emptyList(), bestPlan.score, bestPlan.createsDuplicates, bestPlan.includedRankComparisons);
    } else {
        return bestPlan;
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RecordQueryFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan) RecordTypeKeyExpression(com.apple.foundationdb.record.metadata.expressions.RecordTypeKeyExpression) VersionKeyExpression(com.apple.foundationdb.record.metadata.expressions.VersionKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) Nonnull(javax.annotation.Nonnull)

Example 4 with KeyExpression

use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.

the class RecordQueryPlanner method planIndex.

@Nullable
private ScoredPlan planIndex(@Nonnull PlanContext planContext, @Nonnull QueryComponent filter, @Nullable Index index, @Nonnull KeyExpression indexExpr, @Nonnull List<ScoredPlan> intersectionCandidates) {
    final KeyExpression sort = planContext.query.getSort();
    final boolean sortReverse = planContext.query.isSortReverse();
    final CandidateScan candidateScan = new CandidateScan(planContext, index, sortReverse);
    ScoredPlan p = null;
    if (index != null) {
        if (indexTypes.getRankTypes().contains(index.getType())) {
            GroupingKeyExpression grouping = (GroupingKeyExpression) indexExpr;
            p = planRank(candidateScan, index, grouping, filter);
            // Plan as just value index.
            indexExpr = grouping.getWholeKey();
        } else if (indexTypes.getTextTypes().contains(index.getType())) {
            p = planText(candidateScan, index, filter, sort);
            if (p != null) {
                p = planRemoveDuplicates(planContext, p);
            }
            if (p != null) {
                p = computeIndexFilters(planContext, p);
            }
            return p;
        } else if (indexTypes.getLuceneTypes().contains(index.getType())) {
            p = planLucene(candidateScan, index, filter, sort);
            if (p != null) {
                p = planRemoveDuplicates(planContext, p);
            }
            if (p != null) {
                p = computeIndexFilters(planContext, p);
            }
            return p;
        } else if (!indexTypes.getValueTypes().contains(index.getType())) {
            return null;
        }
    }
    if (p == null) {
        p = planCandidateScan(candidateScan, indexExpr, filter, sort);
    }
    if (p == null) {
        // we can't match the filter, but maybe the sort
        p = planSortOnly(candidateScan, indexExpr, sort);
        if (p != null) {
            final List<QueryComponent> unsatisfiedFilters = filter instanceof AndComponent ? ((AndComponent) filter).getChildren() : Collections.singletonList(filter);
            p = new ScoredPlan(0, p.plan, unsatisfiedFilters, p.createsDuplicates);
        }
    }
    if (p != null) {
        if (getConfiguration().shouldOptimizeForIndexFilters()) {
            // partition index filters
            if (index == null) {
                // if we scan without an index all filters become index filters as we don't need a fetch
                // to evaluate these filters
                p = p.withFilters(p.combineNonSargables(), Collections.emptyList());
            } else {
                p = computeIndexFilters(planContext, p);
            }
        }
    }
    if (p != null) {
        p = planRemoveDuplicates(planContext, p);
        if (p != null && p.getNumNonSargables() > 0) {
            PlanOrderingKey planOrderingKey = PlanOrderingKey.forPlan(metaData, p.plan, planContext.commonPrimaryKey);
            if (planOrderingKey != null && (sort != null || planOrderingKey.isPrimaryKeyOrdered())) {
                // If there is a sort, all chosen plans should be ordered by it and so compatible.
                // Otherwise, by requiring pkey order, we miss out on the possible intersection of
                // X < 10 AND X < 5, which should have been handled already. We gain simplicity
                // in not trying X < 10 AND Y = 5 AND Z = 'foo', where we would need to throw
                // some out as we fail to align them all.
                p.planOrderingKey = planOrderingKey;
                intersectionCandidates.add(p);
            }
        }
    }
    return p;
}
Also used : QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) AndComponent(com.apple.foundationdb.record.query.expressions.AndComponent) RecordTypeKeyExpression(com.apple.foundationdb.record.metadata.expressions.RecordTypeKeyExpression) VersionKeyExpression(com.apple.foundationdb.record.metadata.expressions.VersionKeyExpression) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) EmptyKeyExpression(com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) Nullable(javax.annotation.Nullable)

Example 5 with KeyExpression

use of com.apple.foundationdb.record.metadata.expressions.KeyExpression in project fdb-record-layer by FoundationDB.

the class InExtractor method extractInClauses.

@SuppressWarnings("unchecked")
private QueryComponent extractInClauses() {
    final AtomicInteger bindingIndex = new AtomicInteger();
    return mapClauses(filter, (withComparison, fields) -> {
        if (withComparison.getComparison().getType() == Comparisons.Type.IN) {
            String bindingName = Bindings.Internal.IN.bindingName(withComparison.getName() + "__" + bindingIndex.getAndIncrement());
            List<FieldKeyExpression> nestedFields = null;
            if (fields != null && (withComparison instanceof FieldWithComparison || withComparison instanceof OneOfThemWithComparison)) {
                nestedFields = new ArrayList<>(fields);
                nestedFields.add(Key.Expressions.field(((BaseField) withComparison).getFieldName(), withComparison instanceof FieldWithComparison ? KeyExpression.FanType.None : KeyExpression.FanType.FanOut));
            }
            KeyExpression orderingKey = getOrderingKey(nestedFields);
            if (withComparison.getComparison() instanceof Comparisons.ComparisonWithParameter) {
                final String parameterName = ((Comparisons.ComparisonWithParameter) withComparison.getComparison()).getParameter();
                inClauses.add(new InParameterClause(bindingName, parameterName, orderingKey));
            } else {
                final List<Object> comparand = (List<Object>) withComparison.getComparison().getComparand();
                // ListComparison does not allow empty/null
                if (comparand != null && comparand.size() == 1) {
                    return withComparison.withOtherComparison(new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, comparand.get(0)));
                }
                inClauses.add(new InValuesClause(bindingName, comparand, orderingKey));
            }
            return withComparison.withOtherComparison(new Comparisons.ParameterComparison(Comparisons.Type.EQUALS, bindingName, Bindings.Internal.IN));
        } else {
            return withComparison;
        }
    }, Collections.emptyList());
}
Also used : BaseField(com.apple.foundationdb.record.query.expressions.BaseField) OneOfThemWithComparison(com.apple.foundationdb.record.query.expressions.OneOfThemWithComparison) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) NestingKeyExpression(com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FieldKeyExpression(com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List)

Aggregations

KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)152 GroupingKeyExpression (com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression)85 Test (org.junit.jupiter.api.Test)63 FieldKeyExpression (com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression)60 EmptyKeyExpression (com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression)56 NestingKeyExpression (com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression)56 ThenKeyExpression (com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression)52 Nonnull (javax.annotation.Nonnull)52 Index (com.apple.foundationdb.record.metadata.Index)37 List (java.util.List)36 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)35 Nullable (javax.annotation.Nullable)33 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)30 FunctionKeyExpression (com.apple.foundationdb.record.metadata.expressions.FunctionKeyExpression)28 Message (com.google.protobuf.Message)26 ArrayList (java.util.ArrayList)26 RecordMetaData (com.apple.foundationdb.record.RecordMetaData)25 QueryableKeyExpression (com.apple.foundationdb.record.metadata.expressions.QueryableKeyExpression)25 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)24 ListKeyExpression (com.apple.foundationdb.record.metadata.expressions.ListKeyExpression)23