Search in sources :

Example 66 with RecordQueryPlanner

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

the class FDBSortQueryIndexSelectionTest method sortNested.

/**
 * Verify that sorts on nested fields are implemented using nested record field indexes.
 */
@SuppressWarnings("java:S5961")
@DualPlannerTest
void sortNested() {
    try (FDBRecordContext context = openContext()) {
        RecordMetaDataBuilder builder = RecordMetaData.newBuilder().setRecords(TestRecordsWithHeaderProto.getDescriptor());
        builder.getRecordType("MyRecord").setPrimaryKey(field("header").nest(concatenateFields("path", "rec_no")));
        builder.addIndex("MyRecord", "MyRecord$header_num", concat(field("header").nest("num"), field("str_value")));
        RecordMetaData metaData = builder.getRecordMetaData();
        createOrOpenRecordStore(context, metaData);
        for (int i = 0; i < 100; i++) {
            TestRecordsWithHeaderProto.MyRecord.Builder recBuilder = TestRecordsWithHeaderProto.MyRecord.newBuilder();
            TestRecordsWithHeaderProto.HeaderRecord.Builder headerBuilder = recBuilder.getHeaderBuilder();
            // Carter-Wegman hash, with large enough prime
            headerBuilder.setRecNo((1096 * i + 722) % 1289);
            headerBuilder.setPath("root");
            headerBuilder.setNum(i);
            recBuilder.setStrValue(Integer.toString(i));
            recordStore.saveRecord(recBuilder.build());
        }
        {
            RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setSort(field("header").nest("num")).build();
            // Index(MyRecord$header_num <,>)
            RecordQueryPlan plan = planner.plan(query);
            assertThat(plan, indexScan(allOf(indexName("MyRecord$header_num"), unbounded())));
            assertEquals(-1173952475, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
            assertEquals(1008825832, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
            assertEquals(1008825832, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            int i = 0;
            try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
                while (cursor.hasNext()) {
                    FDBQueriedRecord<Message> rec = cursor.next();
                    TestRecordsWithHeaderProto.MyRecord.Builder myrec = TestRecordsWithHeaderProto.MyRecord.newBuilder();
                    myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
                    assertEquals(i++, myrec.getHeader().getNum());
                }
            }
            assertEquals(100, i);
            assertDiscardedNone(context);
        }
        {
            RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("header").matches(Query.field("num").lessThan(50))).setSort(field("header").nest("num")).build();
            // Index(MyRecord$header_num ([null],[50]))
            RecordQueryPlan plan = planner.plan(query);
            assertThat(plan, indexScan(allOf(indexName("MyRecord$header_num"), bounds(hasTupleString("([null],[50])")))));
            if (planner instanceof RecordQueryPlanner) {
                assertEquals(2008179964, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
                assertEquals(2049006062, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
                assertEquals(-204519612, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            } else {
                assertEquals(2008179964, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
                // TODO strictly sorted is not set
                assertEquals(2049006068, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
                // TODO strictly sorted is not set
                assertEquals(-204519606, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            }
            int i = 0;
            try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
                while (cursor.hasNext()) {
                    FDBQueriedRecord<Message> rec = cursor.next();
                    TestRecordsWithHeaderProto.MyRecord.Builder myrec = TestRecordsWithHeaderProto.MyRecord.newBuilder();
                    myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
                    assertEquals(i++, myrec.getHeader().getNum());
                }
            }
            assertEquals(50, i);
            assertDiscardedNone(context);
        }
        {
            RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("header").matches(Query.field("num").equalsValue(1))).setSort(field("str_value")).build();
            // Index(MyRecord$header_num [[1],[1]])
            RecordQueryPlan plan = planner.plan(query);
            assertThat(plan, indexScan(allOf(indexName("MyRecord$header_num"), bounds(hasTupleString("[[1],[1]]")))));
            assertEquals(878861315, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
            assertEquals(653879397, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
            assertEquals(998239886, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            int i = 0;
            try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
                while (cursor.hasNext()) {
                    FDBQueriedRecord<Message> rec = cursor.next();
                    TestRecordsWithHeaderProto.MyRecord.Builder myrec = TestRecordsWithHeaderProto.MyRecord.newBuilder();
                    myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
                    assertEquals(1, myrec.getHeader().getNum());
                    i++;
                }
            }
            assertEquals(1, i);
            assertDiscardedNone(context);
        }
        {
            RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.and(Query.field("header").matches(Query.field("num").isNull()), Query.field("str_value").greaterThan("middle"))).setSort(field("str_value")).build();
            // Index(MyRecord$header_num ([null, middle],[null]])
            RecordQueryPlan plan = planner.plan(query);
            assertThat(plan, indexScan(allOf(indexName("MyRecord$header_num"), bounds(hasTupleString("([null, middle],[null]]")))));
            assertEquals(1553479768, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
            assertEquals(1072001836, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
            assertEquals(-1653404355, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        }
        {
            final QueryComponent filter = Query.field("header").matches(Query.field("rec_no").greaterThan(0L));
            RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(filter).setSort(field("header").nest("num")).build();
            // Fetch(Covering(Index(MyRecord$header_num <,>) -> [str_value: KEY[1], header: [num: KEY[0], path: KEY[2], rec_no: KEY[3]]]) | header/{rec_no GREATER_THAN 0})
            RecordQueryPlan plan = planner.plan(query);
            assertThat(plan, fetch(filter(filter, coveringIndexScan(indexScan(allOf(indexName("MyRecord$header_num"), unbounded()))))));
            if (planner instanceof RecordQueryPlanner) {
                assertEquals(673903077, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
                assertEquals(-582153460, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
                assertEquals(-421343502, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            } else {
                assertEquals(749683984, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
                assertEquals(87367824, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
                assertEquals(248177782, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            }
            try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
                while (cursor.hasNext()) {
                    FDBQueriedRecord<Message> rec = cursor.next();
                    TestRecordsWithHeaderProto.MyRecord.Builder myrec = TestRecordsWithHeaderProto.MyRecord.newBuilder();
                    myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
                    assertTrue(myrec.hasHeader(), "Retrieved record missing header");
                    assertTrue(myrec.getHeader().hasRecNo(), "Retrieved record missing rec_no");
                    long recNo = myrec.getHeader().getRecNo();
                    assertTrue(recNo > 0L, "Record does not match filter (rec_no " + recNo + "<= 0)");
                }
            }
            assertDiscardedExactly(0, context);
            clearStoreCounter(context);
        }
        {
            RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("header").matches(Query.and(Query.field("rec_no").greaterThan(10L), Query.field("num").lessThan(50)))).setSort(field("header").nest("num")).build();
            // Fetch(Covering(Index(MyRecord$header_num ([null],[50])) -> [str_value: KEY[1], header: [num: KEY[0], path: KEY[2], rec_no: KEY[3]]]) | header/{rec_no GREATER_THAN 10})
            RecordQueryPlan plan = planner.plan(query);
            assertThat(plan, fetch(filter(Query.field("header").matches(Query.field("rec_no").greaterThan(10L)), coveringIndexScan(indexScan(allOf(indexName("MyRecord$header_num"), bounds(hasTupleString("([null],[50])"))))))));
            if (planner instanceof RecordQueryPlanner) {
                assertEquals(1473993740, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
                assertEquals(1598662608, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
                assertEquals(619653398, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            } else {
                assertEquals(1549774647, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
                assertEquals(-2026783218, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
                assertEquals(1289174868, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            }
            try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
                while (cursor.hasNext()) {
                    FDBQueriedRecord<Message> rec = cursor.next();
                    TestRecordsWithHeaderProto.MyRecord.Builder myrec = TestRecordsWithHeaderProto.MyRecord.newBuilder();
                    myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
                    assertTrue(myrec.hasHeader(), "Retrieved record missing header");
                    assertTrue(myrec.getHeader().hasRecNo(), "Retrieved record missing rec_no");
                    assertTrue(myrec.getHeader().hasNum(), "Retrieved record missing num");
                    long recNo = myrec.getHeader().getRecNo();
                    int num = myrec.getHeader().getNum();
                    assertTrue(recNo > 10L && num < 50, "Retrieved record does not match filter (rec_no = " + recNo + " and num = " + num + ")");
                }
            }
            assertDiscardedExactly(0, context);
        }
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) TestRecordsWithHeaderProto(com.apple.foundationdb.record.TestRecordsWithHeaderProto) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) Message(com.google.protobuf.Message) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordQuery(com.apple.foundationdb.record.query.RecordQuery)

Example 67 with RecordQueryPlanner

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

the class FDBRecordStoreQueryTest method testUncommonPrimaryKey.

/**
 * Verify that complex queries on multiple types with uncommon primary keys are implemented, but only with record
 * scans, type filters, and filters.
 */
@DualPlannerTest
void testUncommonPrimaryKey() throws Exception {
    try (FDBRecordContext context = openContext()) {
        openMultiRecordStore(context);
        Message record = TestRecordsMultiProto.MultiRecordOne.newBuilder().setId(1066L).setName("William the Conqueror").addElement("Hastings").addElement("Normandy").addElement("Canterbury").addElement("England").build();
        recordStore.saveRecord(record);
        record = TestRecordsMultiProto.MultiRecordOne.newBuilder().setId(948L).setName("Æthelred the Unræd").addElement("St. Paul's").addElement("Ælfgifu of York").addElement("Ælfthryth").build();
        recordStore.saveRecord(record);
        record = TestRecordsMultiProto.MultiRecordTwo.newBuilder().setEgo(1776L).setValue("George III").addElement("Hanover").addElement("Great Britain").addElement("Proclamation of 1763").build();
        recordStore.saveRecord(record);
        record = TestRecordsMultiProto.MultiRecordThree.newBuilder().setEgo(800L).setData("Charlemagne").addElement("Saxony").addElement("Francia").addElement("Rome").build();
        recordStore.saveRecord(record);
        RecordQuery query = RecordQuery.newBuilder().setRecordTypes(Arrays.asList("MultiRecordTwo", "MultiRecordThree")).setFilter(Query.field("element").oneOfThem().greaterThan("A")).setRemoveDuplicates(true).build();
        RecordQueryPlan plan = planner.plan(query);
        if (planner instanceof RecordQueryPlanner) {
            assertMatchesExactly(plan, filterPlan(typeFilterPlan(scanPlan().where(scanComparisons(unbounded()))).where(recordTypes(containsAll(ImmutableSet.of("MultiRecordTwo", "MultiRecordThree"))))).where(queryComponents(only(equalsObject(Query.field("element").oneOfThem().greaterThan("A"))))));
            // TODO: Issue https://github.com/FoundationDB/fdb-record-layer/issues/1074
            // assertEquals(1399455990, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            assertEquals(1808059644, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        } else {
            assertMatchesExactly(plan, predicatesFilterPlan(typeFilterPlan(scanPlan().where(scanComparisons(unbounded()))).where(recordTypes(containsAll(ImmutableSet.of("MultiRecordTwo", "MultiRecordThree"))))).where(predicates(only(queryComponentPredicate(equalsObject(Query.field("element").oneOfThem().greaterThan("A")))))));
            // TODO: Issue https://github.com/FoundationDB/fdb-record-layer/issues/1074
            // assertEquals(1399455990, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            assertEquals(1808059644, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        }
        assertEquals(Arrays.asList(800L, 1776L), recordStore.executeQuery(plan).map(FDBQueriedRecord::getRecord).map(message -> message.getField(message.getDescriptorForType().findFieldByNumber(1))).asList().join());
        // TODO add a performance test here, but doing it before refactoring would be a lot of extra work
        query = RecordQuery.newBuilder().setRecordTypes(Arrays.asList("MultiRecordOne", "MultiRecordTwo")).setFilter(Query.field("element").oneOfThem().greaterThan("A")).setRemoveDuplicates(true).build();
        // Scan(<,>) | [MultiRecordOne, MultiRecordTwo] | one of element GREATER_THAN A
        // Index(onetwo$element ([A],>) | UnorderedPrimaryKeyDistinct()
        plan = planner.plan(query);
        if (planner instanceof RecordQueryPlanner) {
            // RecordQueryPlanner doesn't notice that the requested record type match the record types for onetwo$element.
            assertMatchesExactly(plan, filterPlan(typeFilterPlan(scanPlan().where(scanComparisons(unbounded()))).where(recordTypes(containsAll(ImmutableSet.of("MultiRecordOne", "MultiRecordTwo"))))).where(queryComponents(only(equalsObject(Query.field("element").oneOfThem().greaterThan("A"))))));
            assertEquals(-663593392, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
            assertEquals(898549447, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
            assertEquals(1059359340, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        } else {
            // Cascades planner correctly identifies that the requested record types match the index onetwo$element.
            assertMatchesExactly(plan, unorderedPrimaryKeyDistinctPlan(indexPlan().where(indexName("onetwo$element")).and(scanComparisons(range("([A],>")))));
        }
        assertThat(recordStore.executeQuery(plan).map(FDBQueriedRecord::getRecord).map(message -> message.getField(message.getDescriptorForType().findFieldByNumber(1))).asList().join(), containsInAnyOrder(948L, 1066L, 1776L));
    // TOOD add a performance test here, but doing it before refactoring would be a lot of extra work
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Arrays(java.util.Arrays) RecordQueryPlanMatchers.scanPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.scanPlan) Bindings(com.apple.foundationdb.record.Bindings) 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) TestHelpers.assertDiscardedNone(com.apple.foundationdb.record.TestHelpers.assertDiscardedNone) TestRecordsMultiProto(com.apple.foundationdb.record.TestRecordsMultiProto) Tuple(com.apple.foundationdb.tuple.Tuple) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) 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) Tag(org.junit.jupiter.api.Tag) Query(com.apple.foundationdb.record.query.expressions.Query) ImmutableSet(com.google.common.collect.ImmutableSet) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) RecordQueryPlanMatchers.recordTypes(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.recordTypes) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) Test(org.junit.jupiter.api.Test) Objects(java.util.Objects) List(java.util.List) ScanComparisons.range(com.apple.foundationdb.record.query.plan.ScanComparisons.range) Matchers.containsInAnyOrder(org.hamcrest.Matchers.containsInAnyOrder) 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) RecordQueryPlanComplexityException(com.apple.foundationdb.record.query.plan.RecordQueryPlanComplexityException) RecordQueryPlanMatchers.unionPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.unionPlan) RecordQueryPlanMatchers(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers) RecordQueryPlanMatchers.predicatesFilterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicatesFilterPlan) IntStream(java.util.stream.IntStream) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) Assertions.fail(org.junit.jupiter.api.Assertions.fail) ValueMatchers.anyValue(com.apple.foundationdb.record.query.plan.temp.matchers.ValueMatchers.anyValue) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) PrimitiveMatchers.equalsObject(com.apple.foundationdb.record.query.plan.temp.matchers.PrimitiveMatchers.equalsObject) QueryPredicateMatchers.queryComponentPredicate(com.apple.foundationdb.record.query.plan.temp.matchers.QueryPredicateMatchers.queryComponentPredicate) TestRecordsTupleFieldsProto(com.apple.foundationdb.record.TestRecordsTupleFieldsProto) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) PlanHashable(com.apple.foundationdb.record.PlanHashable) ArrayList(java.util.ArrayList) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) Lists(com.google.common.collect.Lists) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) 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) FDBStoredRecord(com.apple.foundationdb.record.provider.foundationdb.FDBStoredRecord) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) LongStream(java.util.stream.LongStream) ScanComparisons.unbounded(com.apple.foundationdb.record.query.plan.ScanComparisons.unbounded) RecordTypeBuilder(com.apple.foundationdb.record.metadata.RecordTypeBuilder) TupleFieldsHelper(com.apple.foundationdb.record.metadata.expressions.TupleFieldsHelper) Tags(com.apple.test.Tags) QueryPredicateMatchers.valuePredicate(com.apple.foundationdb.record.query.plan.temp.matchers.QueryPredicateMatchers.valuePredicate) PrimitiveMatchers.containsAll(com.apple.foundationdb.record.query.plan.temp.matchers.PrimitiveMatchers.containsAll) RecordQueryPlanMatchers.queryComponents(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.queryComponents) RecordQueryPlanMatchers.typeFilterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.typeFilterPlan) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) RecordQueryPlanMatchers.filterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.filterPlan) 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) RecordCursor(com.apple.foundationdb.record.RecordCursor) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) ListMatcher.exactly(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.exactly) Collections(java.util.Collections) TestRecordsBytesProto(com.apple.foundationdb.record.TestRecordsBytesProto) ValueMatchers.fieldValue(com.apple.foundationdb.record.query.plan.temp.matchers.ValueMatchers.fieldValue) 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 68 with RecordQueryPlanner

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

the class FDBRecordStoreQueryTestBase method setDeferFetchAfterUnionAndIntersection.

protected void setDeferFetchAfterUnionAndIntersection(boolean shouldDeferFetch) {
    if (planner instanceof RecordQueryPlanner) {
        RecordQueryPlanner recordQueryPlanner = (RecordQueryPlanner) planner;
        recordQueryPlanner.setConfiguration(recordQueryPlanner.getConfiguration().asBuilder().setDeferFetchAfterUnionAndIntersection(shouldDeferFetch).build());
    }
}
Also used : RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner)

Example 69 with RecordQueryPlanner

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

the class FDBRepeatedFieldQueryTest method sortRepeated2.

/**
 * Verify that sorts on repeated fields are implemented with fanout indexes.
 * Verify that they include distinctness filters and value filters where necessary.
 */
@DualPlannerTest
public void sortRepeated2() throws Exception {
    try (FDBRecordContext context = openContext()) {
        openNestedRecordStore(context);
        commit(context);
    }
    RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(Query.field("reviews").oneOfThem().matches(Query.field("rating").notNull())).setSort(field("reviews", FanType.FanOut).nest("rating"));
    RecordQuery query = builder.setRemoveDuplicates(false).build();
    // Index(review_rating ([null],>)
    RecordQueryPlan plan = planner.plan(query);
    assertThat(plan, indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("([null],>")))));
    if (planner instanceof RecordQueryPlanner) {
        assertEquals(-1499993185, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1617129902, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1617129902, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        assertEquals(-1499993185, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1617129908, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1617129908, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
    query = builder.setRemoveDuplicates(true).build();
    // Index(review_rating ([null],>) | UnorderedPrimaryKeyDistinct()
    plan = planner.plan(query);
    if (planner instanceof RecordQueryPlanner) {
        assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("([null],>"))))));
        assertEquals(-1499993184, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(821950248, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(821950248, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        assertThat(plan, fetch(primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("([null],>"))))))));
        assertEquals(-1910017683, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1317916225, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1317916225, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordQuery(com.apple.foundationdb.record.query.RecordQuery)

Example 70 with RecordQueryPlanner

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

the class QueryPlanMaxCardinalityTest method setup.

protected void setup(@Nullable RecordMetaDataHook hook) {
    RecordMetaDataBuilder builder = RecordMetaData.newBuilder().setRecords(TestRecords1Proto.getDescriptor());
    if (hook != null) {
        hook.apply(builder);
    }
    metaData = builder.getRecordMetaData();
    planner = new RecordQueryPlanner(metaData, new RecordStoreState(null, null));
}
Also used : RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordStoreState(com.apple.foundationdb.record.RecordStoreState)

Aggregations

RecordQueryPlanner (com.apple.foundationdb.record.query.plan.RecordQueryPlanner)71 RecordQuery (com.apple.foundationdb.record.query.RecordQuery)65 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)65 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)58 FDBQueriedRecord (com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord)48 Message (com.google.protobuf.Message)47 Test (org.junit.jupiter.api.Test)37 Query (com.apple.foundationdb.record.query.expressions.Query)36 Tags (com.apple.test.Tags)36 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)36 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)36 Tag (org.junit.jupiter.api.Tag)36 PlanHashable (com.apple.foundationdb.record.PlanHashable)35 Index (com.apple.foundationdb.record.metadata.Index)35 Expressions.field (com.apple.foundationdb.record.metadata.Key.Expressions.field)35 Assertions.assertTrue (org.junit.jupiter.api.Assertions.assertTrue)35 QueryComponent (com.apple.foundationdb.record.query.expressions.QueryComponent)33 Collections (java.util.Collections)33 Assertions.assertFalse (org.junit.jupiter.api.Assertions.assertFalse)33 Key (com.apple.foundationdb.record.metadata.Key)32