Search in sources :

Example 1 with RecordQueryIndexPlan

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

the class ImplementIndexScanRule method onMatch.

@Override
public void onMatch(@Nonnull PlannerRuleCall call) {
    final IndexScanExpression logical = call.get(root);
    final IndexScanParameters scan = new IndexScanComparisons(logical.getScanType(), logical.scanComparisons());
    call.yield(call.ref(new RecordQueryIndexPlan(Objects.requireNonNull(logical.getIndexName()), scan, logical.isReverse())));
}
Also used : IndexScanParameters(com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters) IndexScanComparisons(com.apple.foundationdb.record.provider.foundationdb.IndexScanComparisons) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) IndexScanExpression(com.apple.foundationdb.record.query.plan.temp.expressions.IndexScanExpression)

Example 2 with RecordQueryIndexPlan

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

the class OrderingProperty method fromIndexScanOrCoveringIndexScan.

@Nonnull
private static Optional<Ordering> fromIndexScanOrCoveringIndexScan(@Nonnull final PlanContext context, @Nonnull final RecordQueryPlan plan) {
    final RecordQueryIndexPlan recordQueryIndexPlan;
    if (plan instanceof RecordQueryIndexPlan) {
        recordQueryIndexPlan = (RecordQueryIndexPlan) plan;
    } else if (plan instanceof RecordQueryCoveringIndexPlan) {
        final RecordQueryPlanWithIndex planWithIndex = ((RecordQueryCoveringIndexPlan) plan).getIndexPlan();
        if (planWithIndex instanceof RecordQueryIndexPlan) {
            recordQueryIndexPlan = (RecordQueryIndexPlan) planWithIndex;
        } else {
            return Optional.empty();
        }
    } else {
        return Optional.empty();
    }
    final String indexName = recordQueryIndexPlan.getIndexName();
    final RecordMetaData metaData = context.getMetaData();
    final Index index = metaData.getIndex(indexName);
    final Collection<RecordType> recordTypesForIndex = metaData.recordTypesForIndex(index);
    final KeyExpression commonPrimaryKeyForIndex = RecordMetaData.commonPrimaryKey(recordTypesForIndex);
    final KeyExpression keyExpression = ValueIndexExpansionVisitor.fullKey(index, commonPrimaryKeyForIndex);
    final ScanComparisons scanComparisons = recordQueryIndexPlan.getComparisons();
    return fromKeyAndScanComparisons(keyExpression, scanComparisons, plan.isReverse(), index.isUnique());
}
Also used : RecordMetaData(com.apple.foundationdb.record.RecordMetaData) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) RecordType(com.apple.foundationdb.record.metadata.RecordType) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) RecordQueryCoveringIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) RecordQueryPlanWithIndex(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlanWithIndex) Index(com.apple.foundationdb.record.metadata.Index) Nonnull(javax.annotation.Nonnull)

Example 3 with RecordQueryIndexPlan

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

the class FDBInQueryTest method testMultipleInQueryIndex.

/**
 * Verify that a query with multiple INs is translated into an index scan within multiple IN joins.
 */
@DualPlannerTest
void testMultipleInQueryIndex() throws Exception {
    final RecordMetaDataHook recordMetaDataHook = metaData -> {
        metaData.getRecordType("MyRecord").setPrimaryKey(field("str_value"));
        metaData.addIndex("MyRecord", "ind", field("header").nest(field("rec_no"), field("path")));
    };
    setupRecordsWithHeader(recordMetaDataHook, (i, record) -> {
        record.setStrValue("_" + i);
        record.getHeaderBuilder().setRecNo(i % 5).setPath("String" + i % 50).setNum(i);
    });
    List<Long> longList = asList(1L, 4L);
    List<String> stringList = asList("String6", "String25", "String1", "String34");
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("header").matches(Query.and(Query.field("rec_no").in(longList), Query.field("path").in(stringList)))).build();
    // Index(ind [EQUALS $__in_rec_no__0, EQUALS $__in_path__1]) WHERE __in_path__1 IN [String6, String25, String1, String34] WHERE __in_rec_no__0 IN [1, 4]
    RecordQueryPlan plan = planner.plan(query);
    if (planner instanceof RecordQueryPlanner) {
        final BindingMatcher<RecordQueryIndexPlan> indexPlanMatcher = indexPlan().where(indexName("ind")).and(scanComparisons(range("[EQUALS $__in_rec_no__0, EQUALS $__in_path__1]")));
        assertMatchesExactly(plan, inValuesJoinPlan(inValuesJoinPlan(indexPlanMatcher).where(inValuesList(equalsObject(stringList)))).where(inValuesList(equalsObject(longList))).or(inValuesJoinPlan(inValuesJoinPlan(indexPlanMatcher).where(inValuesList(equalsObject(longList)))).where(inValuesList(equalsObject(stringList)))));
        assertEquals(-1869764109, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1234840472, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(297055958, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        assertMatchesExactly(plan, fetchFromPartialRecordPlan(inValuesJoinPlan(inValuesJoinPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("ind")).and(scanComparisons(equalities(exactly(anyParameterComparison(), anyParameterComparison()))))))).where(inValuesList(equalsObject(longList)))).where(inValuesList(equalsObject(stringList)))));
        assertEquals(-2124922292, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(2055315359, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1810804415, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
    queryRecordsWithHeader(recordMetaDataHook, plan, cursor -> assertEquals(asList("_56", "_6", "_1", "_51", "_34", "_84"), cursor.map(TestRecordsWithHeaderProto.MyRecord.Builder::getStrValue).asList().get()), TestHelpers::assertDiscardedNone);
}
Also used : RecordQueryPlanMatchers.coveringIndexPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.coveringIndexPlan) Arrays(java.util.Arrays) RecordQueryPlanMatchers.inUnionPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.inUnionPlan) RecordQueryPlanMatchers.scanPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.scanPlan) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQueryPlanMatchers.predicates(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicates) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordQueryPlanMatchers.fetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.fetchFromPartialRecordPlan) IndexScanType(com.apple.foundationdb.record.IndexScanType) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) TestHelpers(com.apple.foundationdb.record.TestHelpers) ListMatcher.only(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.only) RecordQueryPlanMatchers.inValuesList(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.inValuesList) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) Arrays.asList(java.util.Arrays.asList) RecordQueryPlanMatchers.indexName(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexName) Expressions.concat(com.apple.foundationdb.record.metadata.Key.Expressions.concat) Tag(org.junit.jupiter.api.Tag) RecordQueryPlanMatchers.selfOrDescendantPlans(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.selfOrDescendantPlans) Query(com.apple.foundationdb.record.query.expressions.Query) PrimitiveMatchers(com.apple.foundationdb.record.query.plan.temp.matchers.PrimitiveMatchers) RecordQueryPlannerConfiguration(com.apple.foundationdb.record.query.plan.RecordQueryPlannerConfiguration) RecordQueryPlanMatchers.inUnionValuesSources(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.inUnionValuesSources) Set(java.util.Set) FanType(com.apple.foundationdb.record.metadata.expressions.KeyExpression.FanType) RecordQueryPlanMatchers.inValuesJoinPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.inValuesJoinPlan) Test(org.junit.jupiter.api.Test) Objects(java.util.Objects) List(java.util.List) ScanComparisons.range(com.apple.foundationdb.record.query.plan.ScanComparisons.range) RecordQueryPlanMatchers.inParameterJoinPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.inParameterJoinPlan) RecordQueryPlanMatchers.comparisonKey(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.comparisonKey) RecordQueryPlanMatchers.inUnionInValues(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.inUnionInValues) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) TestRecordsEnumProto(com.apple.foundationdb.record.TestRecordsEnumProto) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) TestRecordsWithHeaderProto(com.apple.foundationdb.record.TestRecordsWithHeaderProto) Matchers.greaterThan(org.hamcrest.Matchers.greaterThan) Matchers.is(org.hamcrest.Matchers.is) RecordQueryPlanMatchers.unionPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.unionPlan) Matchers.anyOf(org.hamcrest.Matchers.anyOf) RecordQueryPlanMatchers(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers) ScanComparisons.equalities(com.apple.foundationdb.record.query.plan.ScanComparisons.equalities) RecordQueryPlanMatchers.predicatesFilterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicatesFilterPlan) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) Assertions.fail(org.junit.jupiter.api.Assertions.fail) RecordQueryPlanMatchers.indexPlanOf(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexPlanOf) EnumSource(org.junit.jupiter.params.provider.EnumSource) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) PrimitiveMatchers.equalsObject(com.apple.foundationdb.record.query.plan.temp.matchers.PrimitiveMatchers.equalsObject) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) PlanHashable(com.apple.foundationdb.record.PlanHashable) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) HashSet(java.util.HashSet) RecordQueryPlanMatchers.descendantPlans(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.descendantPlans) ImmutableList(com.google.common.collect.ImmutableList) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) Matchers.lessThan(org.hamcrest.Matchers.lessThan) RecordQueryPlanMatchers.inUnionComparisonKey(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.inUnionComparisonKey) RecordQueryPlanMatchers.scanComparisons(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.scanComparisons) RecordQueryPlanMatchers.unorderedPrimaryKeyDistinctPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.unorderedPrimaryKeyDistinctPlan) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Expressions.field(com.apple.foundationdb.record.metadata.Key.Expressions.field) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) Matchers.oneOf(org.hamcrest.Matchers.oneOf) RecordQueryPlanMatchers.inUnionBindingName(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.inUnionBindingName) Matchers.greaterThanOrEqualTo(org.hamcrest.Matchers.greaterThanOrEqualTo) ScanComparisons.unbounded(com.apple.foundationdb.record.query.plan.ScanComparisons.unbounded) RecordTypeBuilder(com.apple.foundationdb.record.metadata.RecordTypeBuilder) Tags(com.apple.test.Tags) QueryPredicateMatchers.valuePredicate(com.apple.foundationdb.record.query.plan.temp.matchers.QueryPredicateMatchers.valuePredicate) RecordQueryPlanMatchers.queryComponents(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.queryComponents) RecordQueryPlanMatchers.inUnionInParameter(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.inUnionInParameter) ScanComparisons.anyParameterComparison(com.apple.foundationdb.record.query.plan.ScanComparisons.anyParameterComparison) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) RecordQueryPlanMatchers.filterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.filterPlan) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) Index(com.apple.foundationdb.record.metadata.Index) RecordQueryPlanMatchers.indexPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexPlan) TestHelpers.assertDiscardedAtMost(com.apple.foundationdb.record.TestHelpers.assertDiscardedAtMost) Message(com.google.protobuf.Message) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) RecordQueryPlanMatchers.unorderedUnionPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.unorderedUnionPlan) ListMatcher.exactly(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.exactly) Collections(java.util.Collections) ValueMatchers.fieldValue(com.apple.foundationdb.record.query.plan.temp.matchers.ValueMatchers.fieldValue) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) TestRecordsWithHeaderProto(com.apple.foundationdb.record.TestRecordsWithHeaderProto) RecordTypeBuilder(com.apple.foundationdb.record.metadata.RecordTypeBuilder) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) TestHelpers(com.apple.foundationdb.record.TestHelpers) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordQuery(com.apple.foundationdb.record.query.RecordQuery)

Example 4 with RecordQueryIndexPlan

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

the class QueryPlanCursorTest method indexRange.

@Test
public void indexRange() throws Exception {
    final IndexScanParameters scan = IndexScanComparisons.byValue(new ScanComparisons(Collections.emptyList(), ImmutableSet.of(new Comparisons.SimpleComparison(Comparisons.Type.GREATER_THAN, 2), new Comparisons.SimpleComparison(Comparisons.Type.LESS_THAN, 4))));
    final RecordQueryPlan plan = new RecordQueryIndexPlan("MySimpleRecord$num_value_3_indexed", scan, false);
    compareSkipsAndCursors(plan);
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) Test(org.junit.jupiter.api.Test)

Example 5 with RecordQueryIndexPlan

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

the class RemoveSortRule method strictlyOrderedIfUnique.

// TODO: This suggests that ordering and distinct should be tracked together.
public static boolean strictlyOrderedIfUnique(@Nonnull RecordQueryPlan orderedPlan, @Nonnull final Function<String, Index> getIndex, final int nkeys) {
    if (orderedPlan instanceof RecordQueryCoveringIndexPlan) {
        orderedPlan = ((RecordQueryCoveringIndexPlan) orderedPlan).getIndexPlan();
    }
    if (orderedPlan instanceof RecordQueryIndexPlan) {
        RecordQueryIndexPlan indexPlan = (RecordQueryIndexPlan) orderedPlan;
        Index index = getIndex.apply(indexPlan.getIndexName());
        return index.isUnique() && nkeys >= index.getColumnSize();
    }
    return false;
}
Also used : RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) RecordQueryCoveringIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryCoveringIndexPlan) Index(com.apple.foundationdb.record.metadata.Index)

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