Search in sources :

Example 21 with RecordQueryIndexPlan

use of com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan in project fdb-record-layer by FoundationDB.

the class RecordQueryPlanner method planVersion.

@Nullable
private ScoredPlan planVersion(@Nonnull CandidateScan candidateScan, @Nonnull KeyExpression indexExpr, @Nonnull QueryRecordFunctionWithComparison filter, @Nullable KeyExpression sort) {
    if (indexExpr instanceof VersionKeyExpression) {
        final Comparisons.Comparison comparison = filter.getComparison();
        final ScanComparisons comparisons = ScanComparisons.from(comparison);
        if (sort == null || sort.equals(VersionKeyExpression.VERSION)) {
            IndexScanParameters scanParameters = IndexScanComparisons.byValue(comparisons);
            RecordQueryPlan plan = new RecordQueryIndexPlan(candidateScan.index.getName(), scanParameters, candidateScan.reverse);
            return new ScoredPlan(1, plan, Collections.emptyList(), false);
        }
    } else if (indexExpr instanceof ThenKeyExpression) {
        ThenKeyExpression then = (ThenKeyExpression) indexExpr;
        if (sort == null) {
            // && !then.createsDuplicates()) {
            return planVersion(candidateScan, then.getChildren().get(0), filter, null);
        } else {
            return new AndWithThenPlanner(candidateScan, then, Collections.singletonList(filter), sort).plan();
        }
    }
    return null;
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) VersionKeyExpression(com.apple.foundationdb.record.metadata.expressions.VersionKeyExpression) IndexScanParameters(com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) TimeWindowScanComparisons(com.apple.foundationdb.record.provider.foundationdb.leaderboard.TimeWindowScanComparisons) IndexScanComparisons(com.apple.foundationdb.record.provider.foundationdb.IndexScanComparisons) TimeWindowScanComparisons(com.apple.foundationdb.record.provider.foundationdb.leaderboard.TimeWindowScanComparisons) IndexScanComparisons(com.apple.foundationdb.record.provider.foundationdb.IndexScanComparisons) RankComparisons(com.apple.foundationdb.record.query.plan.planning.RankComparisons) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) Nullable(javax.annotation.Nullable)

Example 22 with RecordQueryIndexPlan

use of com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan in project fdb-record-layer by FoundationDB.

the class PlanOrderingKey method forPlan.

@Nullable
public static PlanOrderingKey forPlan(@Nonnull RecordMetaData metaData, @Nonnull RecordQueryPlan queryPlan, @Nullable KeyExpression primaryKey) {
    if (primaryKey == null) {
        return null;
    }
    while (queryPlan instanceof RecordQueryFilterPlan) {
        queryPlan = ((RecordQueryFilterPlan) queryPlan).getInnerPlan();
    }
    if (queryPlan instanceof RecordQueryPlanWithIndex) {
        final RecordQueryPlanWithIndex indexPlan = (RecordQueryPlanWithIndex) queryPlan;
        final Index index = metaData.getIndex(indexPlan.getIndexName());
        final List<KeyExpression> keys = new ArrayList<>(index.getRootExpression().normalizeKeyForPositions());
        int pkeyStart = keys.size();
        int pKeyTail = pkeyStart;
        // Primary keys come after index value keys, unless they were already part of it.
        for (KeyExpression pkey : primaryKey.normalizeKeyForPositions()) {
            int pos = keys.indexOf(pkey);
            if (pos < 0) {
                keys.add(pkey);
            } else if (pkeyStart > pos) {
                pkeyStart = pos;
            }
        }
        final int prefixSize;
        if (indexPlan instanceof RecordQueryIndexPlan) {
            prefixSize = ((RecordQueryIndexPlan) indexPlan).getComparisons().getEqualitySize();
        } else if (indexPlan instanceof RecordQueryTextIndexPlan) {
            final TextScan textScan = ((RecordQueryTextIndexPlan) indexPlan).getTextScan();
            int groupingSize = textScan.getGroupingComparisons() != null ? textScan.getGroupingComparisons().getEqualitySize() : 0;
            int suffixSize = textScan.getSuffixComparisons() != null ? textScan.getSuffixComparisons().getEqualitySize() : 0;
            if (textScan.getTextComparison().getType().isEquality()) {
                // Can use the equality comparisons in the grouping columns and any columns after the text index
                // plus the text column itself.
                prefixSize = groupingSize + suffixSize + 1;
            } else {
                // by the token that the prefix scan just so happened to hit.
                return null;
            }
        } else {
            // Some unknown index plan. Maybe this should throw an error?
            return null;
        }
        return new PlanOrderingKey(keys, prefixSize, pkeyStart, pKeyTail);
    } else if (queryPlan instanceof RecordQueryScanPlan) {
        final RecordQueryScanPlan scanPlan = (RecordQueryScanPlan) queryPlan;
        return new PlanOrderingKey(primaryKey.normalizeKeyForPositions(), scanPlan.getComparisons().getEqualitySize(), 0, 0);
    } else if (queryPlan instanceof RecordQueryIntersectionPlan) {
        return forComparisonKey(((RecordQueryIntersectionPlan) queryPlan).getComparisonKey(), primaryKey);
    } else if (queryPlan instanceof RecordQueryUnionPlan) {
        return forComparisonKey(((RecordQueryUnionPlan) queryPlan).getComparisonKey(), primaryKey);
    } else {
        return null;
    }
}
Also used : RecordQueryUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlan) RecordQueryScanPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryScanPlan) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) ArrayList(java.util.ArrayList) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) Index(com.apple.foundationdb.record.metadata.Index) RecordQueryTextIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryTextIndexPlan) RecordQueryIntersectionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIntersectionPlan) RecordQueryFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) Nullable(javax.annotation.Nullable)

Example 23 with RecordQueryIndexPlan

use of com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan in project fdb-record-layer by FoundationDB.

the class ValueIndexScanMatchCandidate method tryFetchCoveringIndexScan.

@Nonnull
private Optional<RelationalExpression> tryFetchCoveringIndexScan(@Nonnull final PartialMatch partialMatch, @Nonnull final List<ComparisonRange> comparisonRanges, final boolean isReverse) {
    if (recordTypes.size() > 1) {
        return Optional.empty();
    }
    final RecordType recordType = Iterables.getOnlyElement(recordTypes);
    final IndexKeyValueToPartialRecord.Builder builder = IndexKeyValueToPartialRecord.newBuilder(recordType);
    for (int i = 0; i < indexKeyValues.size(); i++) {
        final Value keyValue = indexKeyValues.get(i);
        if (keyValue instanceof FieldValue && keyValue.isFunctionallyDependentOn(recordValue)) {
            final AvailableFields.FieldData fieldData = AvailableFields.FieldData.of(IndexKeyValueToPartialRecord.TupleSource.KEY, i);
            addCoveringField(builder, (FieldValue) keyValue, fieldData);
        }
    }
    for (int i = 0; i < indexValueValues.size(); i++) {
        final Value valueValue = indexValueValues.get(i);
        if (valueValue instanceof FieldValue && valueValue.isFunctionallyDependentOn(recordValue)) {
            final AvailableFields.FieldData fieldData = AvailableFields.FieldData.of(IndexKeyValueToPartialRecord.TupleSource.VALUE, i);
            addCoveringField(builder, (FieldValue) valueValue, fieldData);
        }
    }
    if (!builder.isValid()) {
        return Optional.empty();
    }
    final IndexScanParameters scanParameters = IndexScanComparisons.byValue(toScanComparisons(comparisonRanges));
    final RecordQueryPlanWithIndex indexPlan = new RecordQueryIndexPlan(index.getName(), scanParameters, isReverse, false, (ValueIndexScanMatchCandidate) partialMatch.getMatchCandidate());
    final RecordQueryCoveringIndexPlan coveringIndexPlan = new RecordQueryCoveringIndexPlan(indexPlan, recordType.getName(), // not used except for old planner properties
    AvailableFields.NO_FIELDS, builder.build());
    return Optional.of(new RecordQueryFetchFromPartialRecordPlan(coveringIndexPlan, coveringIndexPlan::pushValueThroughFetch));
}
Also used : IndexScanParameters(com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters) IndexKeyValueToPartialRecord(com.apple.foundationdb.record.query.plan.IndexKeyValueToPartialRecord) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) RecordQueryCoveringIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan) AvailableFields(com.apple.foundationdb.record.query.plan.AvailableFields) RecordQueryFetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFetchFromPartialRecordPlan) RecordType(com.apple.foundationdb.record.metadata.RecordType) QuantifiedValue(com.apple.foundationdb.record.query.predicates.QuantifiedValue) FieldValue(com.apple.foundationdb.record.query.predicates.FieldValue) Value(com.apple.foundationdb.record.query.predicates.Value) QuantifiedColumnValue(com.apple.foundationdb.record.query.predicates.QuantifiedColumnValue) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) FieldValue(com.apple.foundationdb.record.query.predicates.FieldValue) Nonnull(javax.annotation.Nonnull)

Example 24 with RecordQueryIndexPlan

use of com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan in project fdb-record-layer by FoundationDB.

the class MergeFetchIntoCoveringIndexRule method onMatch.

@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
    final RecordQueryIndexPlan innerPlan = call.get(innerPlanMatcher);
    call.yield(call.ref(innerPlan));
}
Also used : RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan)

Aggregations

RecordQueryIndexPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan)24 IndexScanParameters (com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters)14 Test (org.junit.jupiter.api.Test)13 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)12 Comparisons (com.apple.foundationdb.record.query.expressions.Comparisons)7 RecordQueryScanPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryScanPlan)7 Index (com.apple.foundationdb.record.metadata.Index)5 IndexScanComparisons (com.apple.foundationdb.record.provider.foundationdb.IndexScanComparisons)5 ScanComparisons (com.apple.foundationdb.record.query.plan.ScanComparisons)5 RelationalExpression (com.apple.foundationdb.record.query.plan.temp.RelationalExpression)5 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)5 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)4 RecordQueryCoveringIndexPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan)4 RecordQueryUnionPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlan)4 RecordType (com.apple.foundationdb.record.metadata.RecordType)3 ThenKeyExpression (com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression)3 QueryComponent (com.apple.foundationdb.record.query.expressions.QueryComponent)3 Nonnull (javax.annotation.Nonnull)3 Nullable (javax.annotation.Nullable)3 IndexScanType (com.apple.foundationdb.record.IndexScanType)2