Search in sources :

Example 96 with FDBQueriedRecord

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

the class FDBOrQueryToUnionTest method testOrderedOrQueryWithAnd.

/**
 * Verify that a query with an OR of an AND can be implemented as a union of an index scan with an intersection of index scans.
 */
@DualPlannerTest
void testOrderedOrQueryWithAnd() throws Exception {
    RecordMetaDataHook hook = metaData -> {
        metaData.addIndex("MySimpleRecord", "str_2", concat(field("str_value_indexed"), field("num_value_2")));
        metaData.addIndex("MySimpleRecord", "nu_2", concat(field("num_value_unique"), field("num_value_2")));
        metaData.addIndex("MySimpleRecord", "n3_2", concat(field("num_value_3_indexed"), field("num_value_2")));
    };
    complexQuerySetup(hook);
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("str_value_indexed").equalsValue("even"), Query.and(Query.field("num_value_3_indexed").equalsValue(1), Query.field("num_value_unique").equalsValue(909)))).setSort(field("num_value_2")).build();
    // Index(str_2 [[even],[even]]) ∪[Field { 'num_value_2' None}, Field { 'rec_no' None}] Index(nu_2 [[909],[909]]) ∩ Index(n3_2 [[1],[1]])
    RecordQueryPlan plan = planner.plan(query);
    if (planner instanceof RecordQueryPlanner) {
        final BindingMatcher<? extends RecordQueryPlan> planMatcher = unionPlan(indexPlan().where(indexName("str_2")).and(scanComparisons(range("[[even],[even]]"))), intersectionPlan(indexPlan().where(indexName("nu_2")).and(scanComparisons(range("[[909],[909]]"))), indexPlan().where(indexName("n3_2")).and(scanComparisons(range("[[1],[1]]"))))).where(comparisonKey(concat(field("num_value_2"), primaryKey("MySimpleRecord"))));
        assertMatchesExactly(plan, planMatcher);
        assertEquals(-1659601413, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-1344221020, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-1474039530, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        final BindingMatcher<? extends RecordQueryPlan> planMatcher = fetchFromPartialRecordPlan(unionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("str_2")).and(scanComparisons(range("[[even],[even]]"))))), intersectionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("nu_2")).and(scanComparisons(range("[[909],[909]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("n3_2")).and(scanComparisons(range("[[1],[1]]"))))))).where(comparisonKey(concat(field("num_value_2"), primaryKey("MySimpleRecord")))));
        assertMatchesExactly(plan, planMatcher);
        assertEquals(1254181870, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(156652779, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1906836981, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, hook);
        int i = 0;
        try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
            while (cursor.hasNext()) {
                FDBQueriedRecord<Message> rec = cursor.next();
                TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
                myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
                assertTrue(myrec.getStrValueIndexed().equals("even") || (myrec.getNumValue3Indexed() == 1 && myrec.getNumValueUnique() == 909));
                i++;
            }
        }
        assertEquals(51, i);
    }
}
Also used : RecordQueryPlanMatchers.coveringIndexPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.coveringIndexPlan) CascadesPlanner(com.apple.foundationdb.record.query.plan.temp.CascadesPlanner) Matchers.not(org.hamcrest.Matchers.not) Assertions.assertNotEquals(org.junit.jupiter.api.Assertions.assertNotEquals) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQueryPlanMatchers.predicates(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicates) QueryPredicateMatchers.orPredicate(com.apple.foundationdb.record.query.plan.temp.matchers.QueryPredicateMatchers.orPredicate) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) TestHelpers.assertDiscardedNone(com.apple.foundationdb.record.TestHelpers.assertDiscardedNone) RecordQueryPlanMatchers.fetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.fetchFromPartialRecordPlan) Tuple(com.apple.foundationdb.tuple.Tuple) QueryPlan(com.apple.foundationdb.record.query.plan.plans.QueryPlan) ListMatcher.only(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.only) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) 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) RecordQueryUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlan) RecordQueryUnorderedUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnorderedUnionPlan) MethodSource(org.junit.jupiter.params.provider.MethodSource) Query(com.apple.foundationdb.record.query.expressions.Query) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) Matchers.allOf(org.hamcrest.Matchers.allOf) Matchers.lessThanOrEqualTo(org.hamcrest.Matchers.lessThanOrEqualTo) Set(java.util.Set) Arguments(org.junit.jupiter.params.provider.Arguments) RecordQueryPlanMatchers.intersectionPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.intersectionPlan) Test(org.junit.jupiter.api.Test) Objects(java.util.Objects) ScanComparisons.range(com.apple.foundationdb.record.query.plan.ScanComparisons.range) Stream(java.util.stream.Stream) RecordQueryPlanMatchers.comparisonKey(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.comparisonKey) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) Matchers.equalTo(org.hamcrest.Matchers.equalTo) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) 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.predicatesFilterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicatesFilterPlan) RecordQueryPlannerSubstitutionVisitor(com.apple.foundationdb.record.query.plan.visitor.RecordQueryPlannerSubstitutionVisitor) IndexScanParameters(com.apple.foundationdb.record.provider.foundationdb.IndexScanParameters) RecordQueryPlanMatchers.indexPlanOf(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexPlanOf) KeyWithValueExpression(com.apple.foundationdb.record.metadata.expressions.KeyWithValueExpression) 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) Key(com.apple.foundationdb.record.metadata.Key) HashSet(java.util.HashSet) TestHelpers.assertDiscardedExactly(com.apple.foundationdb.record.TestHelpers.assertDiscardedExactly) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) Lists(com.google.common.collect.Lists) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) IndexScanComparisons(com.apple.foundationdb.record.provider.foundationdb.IndexScanComparisons) Matchers.lessThan(org.hamcrest.Matchers.lessThan) BooleanSource(com.apple.test.BooleanSource) 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) Nonnull(javax.annotation.Nonnull) Expressions.field(com.apple.foundationdb.record.metadata.Key.Expressions.field) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) Matchers.greaterThanOrEqualTo(org.hamcrest.Matchers.greaterThanOrEqualTo) Tags(com.apple.test.Tags) TestHelpers.assertLoadRecord(com.apple.foundationdb.record.TestHelpers.assertLoadRecord) QueryPredicateMatchers.valuePredicate(com.apple.foundationdb.record.query.plan.temp.matchers.QueryPredicateMatchers.valuePredicate) PlannableIndexTypes(com.apple.foundationdb.record.query.plan.PlannableIndexTypes) RecordQueryPlanMatchers.queryComponents(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.queryComponents) OrComponent(com.apple.foundationdb.record.query.expressions.OrComponent) 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) ValueMatchers.fieldValue(com.apple.foundationdb.record.query.plan.temp.matchers.ValueMatchers.fieldValue) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Message(com.google.protobuf.Message) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordQuery(com.apple.foundationdb.record.query.RecordQuery)

Example 97 with FDBQueriedRecord

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

the class FDBOrQueryToUnionTest method testOrQuery5WithLimits.

@DualPlannerTest
@MethodSource("query5WithLimitsArgs")
@ParameterizedTest(name = "testOrQuery5WithLimits [limit = {0}, removesDuplicates = {1}]")
void testOrQuery5WithLimits(int limit, boolean removesDuplicates) throws Exception {
    RecordMetaDataHook hook = complexQuerySetupHook();
    complexQuerySetup(hook);
    setDeferFetchAfterUnionAndIntersection(true);
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("str_value_indexed").lessThan("m"), Query.field("num_value_3_indexed").greaterThan(3))).setRemoveDuplicates(removesDuplicates).build();
    // Unordered(Index(MySimpleRecord$str_value_indexed ([null],[m])) ∪ Index(MySimpleRecord$num_value_3_indexed ([3],>))
    RecordQueryPlan plan = planner.plan(query);
    final BindingMatcher<RecordQueryUnorderedUnionPlan> unionPlanBindingMatcher = unorderedUnionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")))));
    final BindingMatcher<? extends RecordQueryPlan> planMatcher;
    if (removesDuplicates) {
        planMatcher = fetchFromPartialRecordPlan(unorderedPrimaryKeyDistinctPlan(unionPlanBindingMatcher));
    } else {
        planMatcher = fetchFromPartialRecordPlan(unionPlanBindingMatcher);
    }
    assertMatchesExactly(plan, planMatcher);
    if (planner instanceof RecordQueryPlanner) {
        assertEquals(removesDuplicates ? 1898767693 : 1898767686, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(removesDuplicates ? -583062018 : 212117636, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(removesDuplicates ? 1864525478 : -1635262164, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        assertEquals(removesDuplicates ? 1898767693 : 1898767686, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(removesDuplicates ? -583062018 : 212117636, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(removesDuplicates ? 1864525478 : -1635262164, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, hook);
        boolean done = false;
        byte[] continuation = null;
        Set<Tuple> uniqueKeys = new HashSet<>();
        int itr = 0;
        while (!done) {
            ExecuteProperties executeProperties = ExecuteProperties.newBuilder().setReturnedRowLimit(limit).build();
            try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan, continuation, executeProperties).asIterator()) {
                int i = 0;
                Set<Tuple> keysThisIteration = new HashSet<>();
                while (cursor.hasNext()) {
                    FDBQueriedRecord<Message> rec = cursor.next();
                    TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
                    myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
                    assertTrue(myrec.getStrValueIndexed().compareTo("m") < 0 || myrec.getNumValue3Indexed() > 3);
                    uniqueKeys.add(rec.getPrimaryKey());
                    if (removesDuplicates) {
                        assertThat(keysThisIteration.add(rec.getPrimaryKey()), is(true));
                    }
                    i++;
                }
                continuation = cursor.getContinuation();
                done = cursor.getNoNextReason().isSourceExhausted();
                if (!done) {
                    assertEquals(limit, i);
                }
            }
            itr++;
            assertThat("exceeded maximum iterations", itr, lessThan(500));
        }
        assertEquals(50 + 10, uniqueKeys.size());
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Message(com.google.protobuf.Message) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) RecordQueryUnorderedUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnorderedUnionPlan) Tuple(com.apple.foundationdb.tuple.Tuple) HashSet(java.util.HashSet) MethodSource(org.junit.jupiter.params.provider.MethodSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 98 with FDBQueriedRecord

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

the class FDBOrQueryToUnionTest method testOrQuery4.

/**
 * Verify that queries with an OR of equality predicates on different fields are implemented using a union of indexes,
 * if all fields are indexed.
 */
@DualPlannerTest
@ParameterizedTest
@BooleanSource
void testOrQuery4(boolean shouldDeferFetch) throws Exception {
    RecordMetaDataHook hook = complexQuerySetupHook();
    complexQuerySetup(hook);
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("str_value_indexed").equalsValue("even"), Query.field("num_value_3_indexed").equalsValue(1), Query.field("num_value_3_indexed").equalsValue(3))).build();
    setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
    // Fetch(Covering(Index(MySimpleRecord$str_value_indexed [[even],[even]]) -> [rec_no: KEY[1], str_value_indexed: KEY[0]]) ∪ Covering(Index(MySimpleRecord$num_value_3_indexed [[1],[1]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]) ∪ Covering(Index(MySimpleRecord$num_value_3_indexed [[3],[3]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]))
    RecordQueryPlan plan = planner.plan(query);
    if (shouldDeferFetch || planner instanceof CascadesPlanner) {
        final BindingMatcher<? extends RecordQueryPlan> planMatcher = fetchFromPartialRecordPlan(unionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("[[even],[even]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[1],[1]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[3],[3]]")))))).where(comparisonKey(primaryKey("MySimpleRecord"))));
        assertMatchesExactly(plan, planMatcher);
        assertEquals(-417814093, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-1082480572, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(233155848, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        final BindingMatcher<? extends RecordQueryPlan> planMatcher = unionPlan(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("[[even],[even]]"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[1],[1]]"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[3],[3]]")))).where(comparisonKey(primaryKey("MySimpleRecord")));
        assertMatchesExactly(plan, planMatcher);
        assertEquals(-673254486, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(991016881, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-1988313995, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, hook);
        int i = 0;
        try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
            while (cursor.hasNext()) {
                FDBQueriedRecord<Message> rec = cursor.next();
                TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
                myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
                assertTrue(myrec.getStrValueIndexed().equals("even") || myrec.getNumValue3Indexed() == 1 || myrec.getNumValue3Indexed() == 3);
                i++;
            }
        }
        assertEquals(50 + 10 + 10, i);
        assertDiscardedAtMost(20, context);
        if (shouldDeferFetch) {
            assertLoadRecord(50 + 10 + 10, context);
        }
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Message(com.google.protobuf.Message) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) CascadesPlanner(com.apple.foundationdb.record.query.plan.temp.CascadesPlanner) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) BooleanSource(com.apple.test.BooleanSource)

Example 99 with FDBQueriedRecord

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

the class FDBAndQueryToIntersectionTest method testComplexQueryAndWithIncompatibleFilters.

/**
 * Verify that a complex query with an AND of fields that are _not_ compatibly ordered generates a plan without
 * an intersection (uses filter instead).
 */
@ParameterizedTest
@BooleanSource
public void testComplexQueryAndWithIncompatibleFilters(final boolean shouldOptimizeForIndexFilters) throws Exception {
    RecordMetaDataHook hook = complexQuerySetupHook();
    complexQuerySetup(hook);
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").startsWith("e"), Query.field("num_value_3_indexed").equalsValue(3))).build();
    setOptimizeForIndexFilters(shouldOptimizeForIndexFilters);
    // Index(MySimpleRecord$str_value_indexed {[e],[e]}) | num_value_3_indexed EQUALS 3
    // Fetch(Covering(Index(multi_index {[e],[e]}) -> [num_value_2: KEY[1], num_value_3_indexed: KEY[2], rec_no: KEY[3], str_value_indexed: KEY[0]]) | num_value_3_indexed EQUALS 3)
    RecordQueryPlan plan = planner.plan(query);
    // Not an intersection plan, since not compatibly ordered.
    if (shouldOptimizeForIndexFilters) {
        assertThat(plan, allOf(hasNoDescendant(intersection(anything(), anything())), descendant(filter(Query.field("num_value_3_indexed").equalsValue(3), coveringIndexScan(indexScan(anyOf(indexName("multi_index"), bounds(hasTupleString("[[e],[e]]")))))))));
        assertFalse(plan.hasRecordScan(), "should not use record scan");
        assertEquals(-1810430840, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-1492232944, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-1442514296, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        assertThat(plan, allOf(hasNoDescendant(intersection(anything(), anything())), descendant(indexScan(anyOf(indexName("MySimpleRecord$str_value_indexed"), indexName("MySimpleRecord$num_value_3_indexed"))))));
        assertFalse(plan.hasRecordScan(), "should not use record scan");
        assertEquals(746853985, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(312168193, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(361886841, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, hook);
        int i = 0;
        try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
            while (cursor.hasNext()) {
                FDBQueriedRecord<Message> rec = cursor.next();
                TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
                myrec.mergeFrom(rec.getRecord());
                assertEquals("even", myrec.getStrValueIndexed());
                assertTrue((myrec.getNumValue3Indexed() % 5) == 3);
                i++;
            }
        }
        assertEquals(10, i);
        assertDiscardedExactly(40, context);
        assertLoadRecord(50, context);
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) Message(com.google.protobuf.Message) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) BooleanSource(com.apple.test.BooleanSource)

Example 100 with FDBQueriedRecord

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

the class FDBAndQueryToIntersectionTest method testComplexQueryAndWithTwoChildren.

/**
 * Verify that a complex query with an AND of fields with compatibly ordered indexes generates an intersection plan.
 */
@ParameterizedTest
@BooleanSource
public void testComplexQueryAndWithTwoChildren(boolean shouldDeferFetch) throws Exception {
    RecordMetaDataHook hook = complexQuerySetupHook();
    complexQuerySetup(hook);
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").equalsValue("even"), Query.field("num_value_3_indexed").equalsValue(3))).build();
    setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
    // Index(MySimpleRecord$str_value_indexed [[even],[even]]) ∩ Index(MySimpleRecord$num_value_3_indexed [[3],[3]])
    // Fetch(Covering(Index(MySimpleRecord$str_value_indexed [[even],[even]]) -> [rec_no: KEY[1], str_value_indexed: KEY[0]]) ∩ Covering(Index(MySimpleRecord$num_value_3_indexed [[3],[3]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]))
    RecordQueryPlan plan = planner.plan(query);
    if (shouldDeferFetch) {
        assertThat(plan, fetch(intersection(coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$str_value_indexed"), bounds(hasTupleString("[[even],[even]]"))))), coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), bounds(hasTupleString("[[3],[3]]"))))), equalTo(field("rec_no")))));
        assertEquals(-929788310, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-1914172894, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-271606869, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        assertThat(plan, intersection(indexScan(allOf(indexName("MySimpleRecord$str_value_indexed"), bounds(hasTupleString("[[even],[even]]")))), indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), bounds(hasTupleString("[[3],[3]]")))), equalTo(field("rec_no"))));
        assertEquals(-1973527173, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(227253579, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1869819604, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, hook);
        int i = 0;
        try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
            while (cursor.hasNext()) {
                FDBQueriedRecord<Message> rec = cursor.next();
                TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
                myrec.mergeFrom(rec.getRecord());
                assertEquals("even", myrec.getStrValueIndexed());
                assertTrue((myrec.getNumValue3Indexed() % 5) == 3);
                i++;
            }
        }
        assertEquals(10, i);
        assertDiscardedExactly(50, context);
        if (shouldDeferFetch) {
            assertLoadRecord(10, context);
        }
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) Message(com.google.protobuf.Message) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) BooleanSource(com.apple.test.BooleanSource)

Aggregations

FDBQueriedRecord (com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord)137 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)125 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)117 RecordQuery (com.apple.foundationdb.record.query.RecordQuery)116 Message (com.google.protobuf.Message)108 Test (org.junit.jupiter.api.Test)65 Tags (com.apple.test.Tags)52 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)52 Tag (org.junit.jupiter.api.Tag)52 RecordQueryPlanner (com.apple.foundationdb.record.query.plan.RecordQueryPlanner)50 Query (com.apple.foundationdb.record.query.expressions.Query)47 List (java.util.List)47 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)46 ExecuteProperties (com.apple.foundationdb.record.ExecuteProperties)45 Index (com.apple.foundationdb.record.metadata.Index)45 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)45 ArrayList (java.util.ArrayList)43 Collections (java.util.Collections)42 PlanHashable (com.apple.foundationdb.record.PlanHashable)41 Tuple (com.apple.foundationdb.tuple.Tuple)41