Search in sources :

Example 11 with IndexScanParameters

use of com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters in project fdb-record-layer by FoundationDB.

the class ExpressionMatcherTest method matchChildrenAsReferences.

@Test
public void matchChildrenAsReferences() {
    BindingMatcher<? extends ExpressionRef<? extends RelationalExpression>> childMatcher1 = ReferenceMatchers.anyRef();
    BindingMatcher<? extends ExpressionRef<? extends RelationalExpression>> childMatcher2 = ReferenceMatchers.anyRef();
    BindingMatcher<RecordQueryUnionPlan> matcher = RecordQueryPlanMatchers.union(ListMatcher.exactly(QuantifierMatchers.physicalQuantifierOverRef(childMatcher1), QuantifierMatchers.physicalQuantifierOverRef(childMatcher2)));
    IndexScanParameters fullValueScan = IndexScanComparisons.byValue();
    RecordQueryIndexPlan child1 = new RecordQueryIndexPlan("an_index", fullValueScan, true);
    RecordQueryScanPlan child2 = new RecordQueryScanPlan(ScanComparisons.EMPTY, true);
    RelationalExpression root = // union with arbitrary comparison key
    RecordQueryUnionPlan.from(child1, child2, EmptyKeyExpression.EMPTY, false);
    Optional<PlannerBindings> possibleBindings = matcher.bindMatches(PlannerBindings.empty(), root).findFirst();
    assertTrue(possibleBindings.isPresent());
    PlannerBindings newBindings = possibleBindings.get().mergedWith(getExistingBindings());
    assertExistingBindingsSurvived(newBindings);
    // check that root matches
    assertEquals(root, newBindings.get(matcher));
    // check that children are behind references
    assertEquals(child1, newBindings.get(childMatcher1).get());
    assertEquals(child2, newBindings.get(childMatcher2).get());
}
Also used : IndexScanParameters(com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters) RelationalExpression(com.apple.foundationdb.record.query.plan.temp.RelationalExpression) RecordQueryUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlan) RecordQueryScanPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryScanPlan) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) Test(org.junit.jupiter.api.Test)

Example 12 with IndexScanParameters

use of com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters in project fdb-record-layer by FoundationDB.

the class RecordQueryPlanner method planCoveringAggregateIndex.

@Nullable
public RecordQueryCoveringIndexPlan planCoveringAggregateIndex(@Nonnull RecordQuery query, @Nonnull Index index, @Nonnull KeyExpression indexExpr) {
    final Collection<RecordType> recordTypes = metaData.recordTypesForIndex(index);
    if (recordTypes.size() != 1) {
        // Unfortunately, since we materialize partial records, we need a unique type for them.
        return null;
    }
    final RecordType recordType = recordTypes.iterator().next();
    final PlanContext planContext = getPlanContext(query);
    planContext.rankComparisons = new RankComparisons(query.getFilter(), planContext.indexes);
    // Repeated fields will be scanned one at a time by covering aggregate, so there is no issue with fan out.
    planContext.allowDuplicates = true;
    final CandidateScan candidateScan = new CandidateScan(planContext, index, query.isSortReverse());
    final ScoredPlan scoredPlan = planCandidateScan(candidateScan, indexExpr, BooleanNormalizer.forConfiguration(configuration).normalizeIfPossible(query.getFilter()), query.getSort());
    // It would be possible to handle unsatisfiedFilters if they, too, only involved group key (covering) fields.
    if (scoredPlan == null || !scoredPlan.unsatisfiedFilters.isEmpty() || !(scoredPlan.plan instanceof RecordQueryIndexPlan)) {
        return null;
    }
    final IndexKeyValueToPartialRecord.Builder builder = IndexKeyValueToPartialRecord.newBuilder(recordType);
    final List<KeyExpression> keyFields = index.getRootExpression().normalizeKeyForPositions();
    final List<KeyExpression> valueFields = Collections.emptyList();
    for (KeyExpression resultField : query.getRequiredResults()) {
        if (!addCoveringField(resultField, builder, keyFields, valueFields)) {
            return null;
        }
    }
    builder.addRequiredMessageFields();
    if (!builder.isValid(true)) {
        return null;
    }
    RecordQueryIndexPlan plan = (RecordQueryIndexPlan) scoredPlan.plan;
    IndexScanParameters scanParameters = new IndexScanComparisons(IndexScanType.BY_GROUP, plan.getComparisons());
    plan = new RecordQueryIndexPlan(plan.getIndexName(), scanParameters, plan.isReverse());
    return new RecordQueryCoveringIndexPlan(plan, recordType.getName(), AvailableFields.NO_FIELDS, builder.build());
}
Also used : IndexScanParameters(com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters) RankComparisons(com.apple.foundationdb.record.query.plan.planning.RankComparisons) IndexScanComparisons(com.apple.foundationdb.record.provider.foundationdb.IndexScanComparisons) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) 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) RecordQueryCoveringIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan) RecordType(com.apple.foundationdb.record.metadata.RecordType) Nullable(javax.annotation.Nullable)

Example 13 with IndexScanParameters

use of com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters 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 14 with IndexScanParameters

use of com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters 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)

Aggregations

IndexScanParameters (com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters)14 RecordQueryIndexPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan)14 Test (org.junit.jupiter.api.Test)8 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)6 RecordQueryScanPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryScanPlan)5 RelationalExpression (com.apple.foundationdb.record.query.plan.temp.RelationalExpression)5 IndexScanComparisons (com.apple.foundationdb.record.provider.foundationdb.IndexScanComparisons)4 RecordQueryUnionPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlan)3 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)3 RecordType (com.apple.foundationdb.record.metadata.RecordType)2 ThenKeyExpression (com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression)2 VersionKeyExpression (com.apple.foundationdb.record.metadata.expressions.VersionKeyExpression)2 Comparisons (com.apple.foundationdb.record.query.expressions.Comparisons)2 QueryComponent (com.apple.foundationdb.record.query.expressions.QueryComponent)2 RankComparisons (com.apple.foundationdb.record.query.plan.planning.RankComparisons)2 RecordQueryCoveringIndexPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan)2 Nullable (javax.annotation.Nullable)2 ExecuteProperties (com.apple.foundationdb.record.ExecuteProperties)1 EmptyKeyExpression (com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression)1 FieldKeyExpression (com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression)1