Search in sources :

Example 21 with TestHelpers

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

the class FDBInQueryTest method testOneOfThemInParameter.

/**
 * Verify that one-of-them queries work with IN (with binding).
 */
@Test
void testOneOfThemInParameter() throws Exception {
    RecordMetaDataHook recordMetaDataHook = metadata -> metadata.addIndex("MySimpleRecord", "ind", field("repeater", FanType.FanOut));
    setupSimpleRecordStore(recordMetaDataHook, (i, builder) -> builder.setRecNo(i).addAllRepeater(Arrays.asList(10 + i % 4, 20 + i % 4)));
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("repeater").oneOfThem().in("values")).build();
    // Index(ind [EQUALS $__in_repeater__0]) | UnorderedPrimaryKeyDistinct() WHERE __in_repeater__0 IN $values
    RecordQueryPlan plan = planner.plan(query);
    assertMatchesExactly(plan, inParameterJoinPlan(unorderedPrimaryKeyDistinctPlan(indexPlan().where(indexName("ind")).and(scanComparisons(range("[EQUALS $__in_repeater__0]"))))).where(RecordQueryPlanMatchers.inParameter(equalsObject("values"))));
    assertEquals(-320448635, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
    assertEquals(604626720, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
    assertEquals(604626720, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    assertEquals(50, querySimpleRecordStore(recordMetaDataHook, plan, () -> EvaluationContext.forBinding("values", Arrays.asList(13L, 11L)), record -> assertThat(record.getRecNo() % 4, anyOf(is(3L), is(1L))), 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) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 22 with TestHelpers

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

the class FDBNestedFieldQueryTest method nested.

/**
 * Verify that nested field comparisons with fanout can scan indexes.
 */
@DualPlannerTest
public void nested() throws Exception {
    try (FDBRecordContext context = openContext()) {
        openNestedRecordStore(context);
        TestRecords4Proto.RestaurantReviewer.Builder reviewerBuilder = TestRecords4Proto.RestaurantReviewer.newBuilder();
        reviewerBuilder.setId(1);
        reviewerBuilder.setName("Lemuel");
        recordStore.saveRecord(reviewerBuilder.build());
        reviewerBuilder.setId(2);
        reviewerBuilder.setName("Gulliver");
        recordStore.saveRecord(reviewerBuilder.build());
        TestRecords4Proto.RestaurantRecord.Builder recBuilder = TestRecords4Proto.RestaurantRecord.newBuilder();
        recBuilder.setRestNo(101);
        recBuilder.setName("The Emperor's Three Tables");
        TestRecords4Proto.RestaurantReview.Builder reviewBuilder = recBuilder.addReviewsBuilder();
        reviewBuilder.setReviewer(1);
        reviewBuilder.setRating(10);
        reviewBuilder = recBuilder.addReviewsBuilder();
        reviewBuilder.setReviewer(2);
        reviewBuilder.setRating(3);
        TestRecords4Proto.RestaurantTag.Builder tagBuilder = recBuilder.addTagsBuilder();
        tagBuilder.setValue("Lilliput");
        tagBuilder.setWeight(5);
        recordStore.saveRecord(recBuilder.build());
        recBuilder = TestRecords4Proto.RestaurantRecord.newBuilder();
        recBuilder.setRestNo(102);
        recBuilder.setName("Small Fry's Fried Victuals");
        reviewBuilder = recBuilder.addReviewsBuilder();
        reviewBuilder.setReviewer(1);
        reviewBuilder.setRating(5);
        reviewBuilder = recBuilder.addReviewsBuilder();
        reviewBuilder.setReviewer(2);
        reviewBuilder.setRating(5);
        tagBuilder = recBuilder.addTagsBuilder();
        tagBuilder.setValue("Lilliput");
        tagBuilder.setWeight(1);
        recordStore.saveRecord(recBuilder.build());
        commit(context);
    }
    // TODO this was originally:
    // QueryExpression.field("reviews").matches(QueryExpression.field("rating").greaterThan(5)),
    // which should have failed validate
    RecordQuery query = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(Query.field("reviews").oneOfThem().matches(Query.field("rating").greaterThan(5))).build();
    // Index(review_rating ([5],>) | UnorderedPrimaryKeyDistinct()
    RecordQueryPlan plan = planner.plan(query);
    if (planner instanceof RecordQueryPlanner) {
        assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("([5],>"))))));
        assertEquals(1378568952, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-2085209333, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(2129300140, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        assertThat(plan, fetch(primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("([5],>"))))))));
        assertEquals(1060048085, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-1589243362, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-1669701185, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
    assertEquals(Arrays.asList(101L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
    query = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(Query.field("tags").oneOfThem().matches(Query.and(Query.field("value").equalsValue("Lilliput"), Query.field("weight").greaterThanOrEquals(5)))).build();
    // Index(tag [[Lilliput, 5],[Lilliput]]) | UnorderedPrimaryKeyDistinct()
    plan = planner.plan(query);
    if (planner instanceof RecordQueryPlanner) {
        assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("tag"), bounds(hasTupleString("[[Lilliput, 5],[Lilliput]]"))))));
        assertEquals(-1197819382, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1570485504, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1584619812, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        assertThat(plan, fetch(primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("tag"), bounds(hasTupleString("[[Lilliput, 5],[Lilliput]]"))))))));
        assertEquals(205198931, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(2066451475, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(2080585783, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
    assertEquals(Collections.singletonList(101L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
    QueryComponent reviewFilter = Query.field("reviews").oneOfThem().matches(Query.and(Query.field("rating").equalsValue(5), Query.field("reviewer").equalsValue(1L)));
    query = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(reviewFilter).build();
    plan = planner.plan(query);
    if (planner instanceof RecordQueryPlanner) {
        assertThat(plan, filter(reviewFilter, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("[[5],[5]]")))))));
        assertEquals(1252155441, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-2056078191, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-1471222808, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Collections.singletonList(102L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
    } else {
        assertThat(plan, filter(reviewFilter, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("[[5],[5]]")))))));
        assertEquals(1252155441, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1947915247, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-1762196666, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Collections.singletonList(102L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, context -> TestHelpers.assertDiscardedAtMost(3, context)));
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Arrays(java.util.Arrays) TestRecords3Proto(com.apple.foundationdb.record.TestRecords3Proto) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) PlanMatchers.bounds(com.apple.foundationdb.record.query.plan.match.PlanMatchers.bounds) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) IndexScanType(com.apple.foundationdb.record.IndexScanType) Tuple(com.apple.foundationdb.tuple.Tuple) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) TestHelpers(com.apple.foundationdb.record.TestHelpers) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) Expressions.concatenateFields(com.apple.foundationdb.record.metadata.Key.Expressions.concatenateFields) Expressions.concat(com.apple.foundationdb.record.metadata.Key.Expressions.concat) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) Tag(org.junit.jupiter.api.Tag) PlanMatchers.coveringIndexScan(com.apple.foundationdb.record.query.plan.match.PlanMatchers.coveringIndexScan) PlanMatchers.indexScanType(com.apple.foundationdb.record.query.plan.match.PlanMatchers.indexScanType) TestRecords4Proto(com.apple.foundationdb.record.TestRecords4Proto) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) Matchers.allOf(org.hamcrest.Matchers.allOf) Test(org.junit.jupiter.api.Test) PlanMatchers.hasTupleString(com.apple.foundationdb.record.query.plan.match.PlanMatchers.hasTupleString) PlanMatchers.indexName(com.apple.foundationdb.record.query.plan.match.PlanMatchers.indexName) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) TestRecordsWithHeaderProto(com.apple.foundationdb.record.TestRecordsWithHeaderProto) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) PlanMatchers.fetch(com.apple.foundationdb.record.query.plan.match.PlanMatchers.fetch) QueryRecordFunction(com.apple.foundationdb.record.query.expressions.QueryRecordFunction) PlanMatchers.primaryKeyDistinct(com.apple.foundationdb.record.query.plan.match.PlanMatchers.primaryKeyDistinct) PlanMatchers.indexScan(com.apple.foundationdb.record.query.plan.match.PlanMatchers.indexScan) PlanMatchers.queryPredicateDescendant(com.apple.foundationdb.record.query.plan.match.PlanMatchers.queryPredicateDescendant) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) TestRecordsNestedMapProto(com.apple.foundationdb.record.TestRecordsNestedMapProto) PlanHashable(com.apple.foundationdb.record.PlanHashable) PlanMatchers.filter(com.apple.foundationdb.record.query.plan.match.PlanMatchers.filter) Key(com.apple.foundationdb.record.metadata.Key) PlanMatchers.scan(com.apple.foundationdb.record.query.plan.match.PlanMatchers.scan) 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) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) Tags(com.apple.test.Tags) PredicateMatchers(com.apple.foundationdb.record.query.predicates.match.PredicateMatchers) TestRecords5Proto(com.apple.foundationdb.record.TestRecords5Proto) Index(com.apple.foundationdb.record.metadata.Index) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) Collections(java.util.Collections) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordQuery(com.apple.foundationdb.record.query.RecordQuery)

Example 23 with TestHelpers

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

the class FDBNestedFieldQueryTest method nestedWithAndConcat.

/**
 * Verify that AND clauses in queries on nested record stores with concatenated repeats are implemented properly.
 */
@DualPlannerTest
public void nestedWithAndConcat() throws Exception {
    final RecordMetaDataHook hook = metaData -> {
        metaData.removeIndex("stats$school");
        metaData.addIndex("RestaurantReviewer", "stats$school", field("stats").nest(concatenateFields("school_name", "start_date")));
        metaData.getIndex("stats$school").setSubspaceKey("stats$school_2");
    };
    nestedWithAndSetup(hook);
    // Same query expressed two ways.
    RecordQuery query1 = RecordQuery.newBuilder().setRecordType("RestaurantReviewer").setFilter(Query.field("stats").matches(Query.and(Query.field("start_date").greaterThan(0L), Query.field("school_name").equalsValue("Human University")))).build();
    // Index(stats$school ([Human University, 0],[Human University]])
    RecordQueryPlan plan1 = planner.plan(query1);
    assertThat(plan1, indexScan(allOf(indexName("stats$school"), bounds(hasTupleString("([Human University, 0],[Human University]]")))));
    assertEquals(-1854785243, plan1.planHash(PlanHashable.PlanHashKind.LEGACY));
    assertEquals(245473758, plan1.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
    assertEquals(1563763213, plan1.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    assertEquals(Collections.singletonList(2L), fetchResultValues(plan1, TestRecords4Proto.RestaurantReviewer.ID_FIELD_NUMBER, ctx -> openNestedRecordStore(ctx, hook), TestHelpers::assertDiscardedNone));
    RecordQuery query2 = RecordQuery.newBuilder().setRecordType("RestaurantReviewer").setFilter(Query.and(Query.field("stats").matches(Query.field("start_date").greaterThan(0L)), Query.field("stats").matches(Query.field("school_name").equalsValue("Human University")))).build();
    // Index(stats$school ([Human University, 0],[Human University]])
    RecordQueryPlan plan2 = planner.plan(query2);
    assertThat(plan2, indexScan(allOf(indexName("stats$school"), bounds(hasTupleString("([Human University, 0],[Human University]]")))));
    assertEquals(-1854785243, plan2.planHash(PlanHashable.PlanHashKind.LEGACY));
    assertEquals(245473758, plan2.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
    assertEquals(1563763213, plan2.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    assertEquals(Collections.singletonList(2L), fetchResultValues(plan2, TestRecords4Proto.RestaurantReviewer.ID_FIELD_NUMBER, ctx -> openNestedRecordStore(ctx, hook), TestHelpers::assertDiscardedNone));
}
Also used : Arrays(java.util.Arrays) TestRecords3Proto(com.apple.foundationdb.record.TestRecords3Proto) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) PlanMatchers.bounds(com.apple.foundationdb.record.query.plan.match.PlanMatchers.bounds) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) IndexScanType(com.apple.foundationdb.record.IndexScanType) Tuple(com.apple.foundationdb.tuple.Tuple) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) TestHelpers(com.apple.foundationdb.record.TestHelpers) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) Expressions.concatenateFields(com.apple.foundationdb.record.metadata.Key.Expressions.concatenateFields) Expressions.concat(com.apple.foundationdb.record.metadata.Key.Expressions.concat) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) Tag(org.junit.jupiter.api.Tag) PlanMatchers.coveringIndexScan(com.apple.foundationdb.record.query.plan.match.PlanMatchers.coveringIndexScan) PlanMatchers.indexScanType(com.apple.foundationdb.record.query.plan.match.PlanMatchers.indexScanType) TestRecords4Proto(com.apple.foundationdb.record.TestRecords4Proto) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) Matchers.allOf(org.hamcrest.Matchers.allOf) Test(org.junit.jupiter.api.Test) PlanMatchers.hasTupleString(com.apple.foundationdb.record.query.plan.match.PlanMatchers.hasTupleString) PlanMatchers.indexName(com.apple.foundationdb.record.query.plan.match.PlanMatchers.indexName) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) TestRecordsWithHeaderProto(com.apple.foundationdb.record.TestRecordsWithHeaderProto) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) PlanMatchers.fetch(com.apple.foundationdb.record.query.plan.match.PlanMatchers.fetch) QueryRecordFunction(com.apple.foundationdb.record.query.expressions.QueryRecordFunction) PlanMatchers.primaryKeyDistinct(com.apple.foundationdb.record.query.plan.match.PlanMatchers.primaryKeyDistinct) PlanMatchers.indexScan(com.apple.foundationdb.record.query.plan.match.PlanMatchers.indexScan) PlanMatchers.queryPredicateDescendant(com.apple.foundationdb.record.query.plan.match.PlanMatchers.queryPredicateDescendant) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) TestRecordsNestedMapProto(com.apple.foundationdb.record.TestRecordsNestedMapProto) PlanHashable(com.apple.foundationdb.record.PlanHashable) PlanMatchers.filter(com.apple.foundationdb.record.query.plan.match.PlanMatchers.filter) Key(com.apple.foundationdb.record.metadata.Key) PlanMatchers.scan(com.apple.foundationdb.record.query.plan.match.PlanMatchers.scan) 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) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) Tags(com.apple.test.Tags) PredicateMatchers(com.apple.foundationdb.record.query.predicates.match.PredicateMatchers) TestRecords5Proto(com.apple.foundationdb.record.TestRecords5Proto) Index(com.apple.foundationdb.record.metadata.Index) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) Collections(java.util.Collections) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RecordQuery(com.apple.foundationdb.record.query.RecordQuery)

Example 24 with TestHelpers

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

the class FDBRepeatedFieldQueryTest method sortRepeated.

/**
 * Verify that sorts on repeated fields are implemented with fanout indexes.
 * Verify that they include distinctness filters and value filters where necessary.
 */
@ParameterizedTest
@BooleanSource
public void sortRepeated(final boolean shouldOptimizeForIndexFilters) throws Exception {
    try (FDBRecordContext context = openContext()) {
        openNestedRecordStore(context);
        TestRecords4Proto.RestaurantReviewer reviewer = TestRecords4Proto.RestaurantReviewer.newBuilder().setId(1L).setName("Javert").setEmail("inspecteur@policier.fr").setStats(TestRecords4Proto.ReviewerStats.newBuilder().setStartDate(100L).setHometown("Toulon")).build();
        recordStore.saveRecord(reviewer);
        reviewer = TestRecords4Proto.RestaurantReviewer.newBuilder().setId(2L).setName("M. le Maire").setStats(TestRecords4Proto.ReviewerStats.newBuilder().setStartDate(120L).setHometown("Montreuil-sur-mer")).build();
        recordStore.saveRecord(reviewer);
        TestRecords4Proto.RestaurantRecord restaurant = TestRecords4Proto.RestaurantRecord.newBuilder().setRestNo(1000L).setName("Chez Thénardier").addReviews(TestRecords4Proto.RestaurantReview.newBuilder().setReviewer(1L).setRating(100)).addReviews(TestRecords4Proto.RestaurantReview.newBuilder().setReviewer(2L).setRating(0)).addTags(TestRecords4Proto.RestaurantTag.newBuilder().setValue("l'atmosphère").setWeight(10)).addTags(TestRecords4Proto.RestaurantTag.newBuilder().setValue("les aliments").setWeight(70)).addCustomer("jean").addCustomer("fantine").addCustomer("cosette").addCustomer("éponine").build();
        recordStore.saveRecord(restaurant);
        restaurant = TestRecords4Proto.RestaurantRecord.newBuilder().setRestNo(1001L).setName("ABC").addReviews(TestRecords4Proto.RestaurantReview.newBuilder().setReviewer(1L).setRating(34)).addReviews(TestRecords4Proto.RestaurantReview.newBuilder().setReviewer(2L).setRating(110)).addTags(TestRecords4Proto.RestaurantTag.newBuilder().setValue("l'atmosphère").setWeight(40)).addTags(TestRecords4Proto.RestaurantTag.newBuilder().setValue("les aliments").setWeight(20)).addCustomer("gavroche").addCustomer("enjolras").addCustomer("éponine").build();
        recordStore.saveRecord(restaurant);
        commit(context);
    }
    {
        RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setSort(field("reviews", FanType.FanOut).nest("rating"));
        RecordQuery query = builder.setRemoveDuplicates(false).build();
        // Index(review_rating <,>)
        RecordQueryPlan plan = planner.plan(query);
        assertThat(plan, indexScan(allOf(indexName("review_rating"), unbounded())));
        assertEquals(406416366, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1919610161, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1919610161, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Arrays.asList(1000L, 1001L, 1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
        query = builder.setRemoveDuplicates(true).build();
        // Index(review_rating <,>) | UnorderedPrimaryKeyDistinct()
        plan = planner.plan(query);
        assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), unbounded()))));
        assertEquals(406416367, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1124430507, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1124430507, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Arrays.asList(1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, context -> assertDiscardedAtMost(2, context)));
    }
    {
        RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setSort(field("reviews", FanType.FanOut).nest("rating"), true);
        RecordQuery query = builder.setRemoveDuplicates(false).build();
        // Index(review_rating <,> REVERSE)
        RecordQueryPlan plan = planner.plan(query);
        assertThat(plan, indexScan(allOf(indexName("review_rating"), unbounded())));
        assertTrue(plan.isReverse());
        assertEquals(406416367, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1919609975, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1919609975, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Arrays.asList(1001L, 1000L, 1001L, 1000L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
        query = builder.setRemoveDuplicates(true).build();
        // Index(review_rating <,> REVERSE) | UnorderedPrimaryKeyDistinct()
        plan = planner.plan(query);
        assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), unbounded()))));
        assertTrue(plan.isReverse());
        assertEquals(406416368, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1124430321, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(1124430321, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Arrays.asList(1001L, 1000L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, context -> assertDiscardedAtMost(2, context)));
    }
    {
        RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setSort(field("reviews", FanType.FanOut).nest("rating")).setFilter(Query.field("name").greaterThan("A"));
        RecordQuery query = builder.setRemoveDuplicates(false).build();
        // Index(review_rating <,>) | name GREATER_THAN A
        RecordQueryPlan plan = planner.plan(query);
        assertThat(plan, filter(query.getFilter(), indexScan(allOf(indexName("review_rating"), unbounded()))));
        assertEquals(1381942688, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-2104094855, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-1943284962, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Arrays.asList(1000L, 1001L, 1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
        query = builder.setRemoveDuplicates(true).build();
        // Index(review_rating <,>) | UnorderedPrimaryKeyDistinct() | name GREATER_THAN A
        plan = planner.plan(query);
        assertThat(plan, filter(query.getFilter(), primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), unbounded())))));
        assertEquals(1381942689, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-984860353, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-824050460, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Arrays.asList(1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, context -> assertDiscardedAtMost(2, context)));
    }
    {
        setOptimizeForIndexFilters(shouldOptimizeForIndexFilters);
        RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setSort(field("customer", FanType.FanOut)).setFilter(Query.field("name").greaterThan("A"));
        RecordQuery query = builder.setRemoveDuplicates(false).build();
        // Index(customers <,>) | name GREATER_THAN A
        // Fetch(Covering(Index(customers-name <,>) -> [name: KEY[1], rest_no: KEY[2]]) | name GREATER_THAN A)
        RecordQueryPlan plan = planner.plan(query);
        if (shouldOptimizeForIndexFilters) {
            assertThat(plan, fetch(filter(query.getFilter(), coveringIndexScan(indexScan(allOf(indexName("customers-name"), unbounded()))))));
            assertEquals(-505715770, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
            assertEquals(-378020523, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
            assertEquals(-217210630, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            assertEquals(Arrays.asList(1000L, 1001L, 1000L, 1001L, 1000L, 1001L, 1000L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
        } else {
            assertThat(plan, filter(query.getFilter(), indexScan(allOf(indexName("customers"), unbounded()))));
            assertEquals(1833106833, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
            assertEquals(201074216, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
            assertEquals(361884109, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
            assertEquals(Arrays.asList(1000L, 1001L, 1000L, 1001L, 1000L, 1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
        }
        setOptimizeForIndexFilters(shouldOptimizeForIndexFilters);
        setDeferFetchAfterUnionAndIntersection(true);
        query = builder.setRemoveDuplicates(true).build();
        // Fetch(Covering(Index(customers <,>) -> [rest_no: KEY[1]]) | UnorderedPrimaryKeyDistinct()) | name GREATER_THAN A
        // Fetch(Covering(Index(customers-name <,>) -> [name: KEY[1], rest_no: KEY[2]]) | UnorderedPrimaryKeyDistinct() | name GREATER_THAN A)
        plan = planner.plan(query);
        if (shouldOptimizeForIndexFilters) {
            assertThat(plan, fetch(filter(query.getFilter(), primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("customers-name"), unbounded())))))));
            assertEquals(-505715763, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
            assertEquals(741213979, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
            assertEquals(902023872, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        } else {
            assertThat(plan, filter(query.getFilter(), fetch(primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("customers"), unbounded())))))));
            assertEquals(-1611344673, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
            assertEquals(-484615365, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
            assertEquals(-323805472, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        }
        assertEquals(Arrays.asList(1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, context -> assertDiscardedAtMost(5, context)));
    }
    {
        RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(Query.field("customer").oneOfThem().equalsValue("éponine")).setSort(field("name"));
        RecordQuery query = builder.setRemoveDuplicates(false).build();
        // Index(customers-name [[éponine],[éponine]])
        RecordQueryPlan plan = planner.plan(query);
        assertThat(plan, indexScan(allOf(indexName("customers-name"), bounds(hasTupleString("[[éponine],[éponine]]")))));
        assertEquals(-574773820, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-1450272556, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(173295350, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Arrays.asList(1001L, 1000L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
        query = builder.setRemoveDuplicates(true).build();
        // Index(customers-name [[éponine],[éponine]]) | UnorderedPrimaryKeyDistinct()
        plan = planner.plan(query);
        assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("customers-name"), bounds(hasTupleString("[[éponine],[éponine]]"))))));
        assertEquals(-574773819, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(2049515086, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-621884304, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Arrays.asList(1001L, 1000L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
    }
    {
        RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(Query.field("customer").oneOfThem().equalsValue("gavroche")).setSort(field("name"));
        RecordQuery query = builder.setRemoveDuplicates(false).build();
        // Index(customers-name [[gavroche],[gavroche]])
        RecordQueryPlan plan = planner.plan(query);
        assertThat(plan, indexScan(allOf(indexName("customers-name"), bounds(hasTupleString("[[gavroche],[gavroche]]")))));
        assertEquals(-1720782767, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-1507776729, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(173295350, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Collections.singletonList(1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
        query = builder.setRemoveDuplicates(true).build();
        // Index(customers-name [[gavroche],[gavroche]]) | UnorderedPrimaryKeyDistinct()
        plan = planner.plan(query);
        assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("customers-name"), bounds(hasTupleString("[[gavroche],[gavroche]]"))))));
        assertEquals(-1720782766, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1992010913, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-621884304, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
        assertEquals(Collections.singletonList(1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) TestRecords4Proto(com.apple.foundationdb.record.TestRecords4Proto) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) TestHelpers(com.apple.foundationdb.record.TestHelpers) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) BooleanSource(com.apple.test.BooleanSource)

Example 25 with TestHelpers

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

the class FDBRecordStoreIndexTest method buildNewUniversalIndex.

/**
 * Verify that building a universal index works.
 */
@Test
public void buildNewUniversalIndex() throws Exception {
    try (FDBRecordContext context = openContext()) {
        uncheckedOpenNestedRecordStore(context);
        recordStore.checkVersion(null, FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_EXISTS).join();
        for (int i = 0; i < 10; i++) {
            recordStore.saveRecord(TestRecords4Proto.RestaurantReviewer.newBuilder().setId(i).setName("r " + i % 10).build());
            recordStore.saveRecord(TestRecords4Proto.RestaurantRecord.newBuilder().setRestNo(100 + i).setName("r " + i % 10).build());
        }
        commit(context);
    }
    RecordQuery query = RecordQuery.newBuilder().setFilter(Query.field("name").equalsValue("r 8")).build();
    final Function<Message, Object> getIds = r -> {
        final Descriptors.Descriptor descriptor = r.getDescriptorForType();
        return r.getField(Objects.equals(descriptor.getName(), "RestaurantRecord") ? descriptor.findFieldByNumber(TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER) : descriptor.findFieldByNumber(TestRecords4Proto.RestaurantReviewer.ID_FIELD_NUMBER));
    };
    assertEquals(Arrays.asList(8L, 108L), fetchResultValues(planner.plan(query), this::uncheckedOpenNestedRecordStore, getIds));
    // Adds an index for that query.
    RecordMetaDataHook hook = metaData -> metaData.addUniversalIndex(new Index("new_index", "name"));
    Opener openWithNewIndex = context -> uncheckedOpenNestedRecordStore(context, hook);
    try (FDBRecordContext context = openContext()) {
        uncheckedOpenNestedRecordStore(context, hook);
        for (int i = 10; i < 20; i++) {
            recordStore.saveRecord(TestRecords4Proto.RestaurantReviewer.newBuilder().setId(i).setName("r " + i % 10).build());
            recordStore.saveRecord(TestRecords4Proto.RestaurantRecord.newBuilder().setRestNo(100 + i).setName("r " + i % 10).build());
        }
        commit(context);
    }
    // Only sees new record added after index.
    assertEquals(Arrays.asList(18L, 118L), fetchResultValues(planner.plan(query), openWithNewIndex, getIds));
    try (FDBRecordContext context = openContext()) {
        uncheckedOpenNestedRecordStore(context, hook);
        recordStore.checkVersion(null, FDBRecordStoreBase.StoreExistenceCheck.NONE).join();
        assertEquals(1, timer.getCount(FDBStoreTimer.Events.REBUILD_INDEX), "should build new index");
        commit(context);
    }
    // Now see both records from indexed query.
    assertEquals(Arrays.asList(8L, 18L, 108L, 118L), fetchResultValues(planner.plan(query), openWithNewIndex, getIds, TestHelpers::assertDiscardedNone));
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) Arrays(java.util.Arrays) Descriptors(com.google.protobuf.Descriptors) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) Function(java.util.function.Function) Key(com.apple.foundationdb.record.metadata.Key) TestHelpers.assertDiscardedNone(com.apple.foundationdb.record.TestHelpers.assertDiscardedNone) IndexScanType(com.apple.foundationdb.record.IndexScanType) Tuple(com.apple.foundationdb.tuple.Tuple) TestHelpers(com.apple.foundationdb.record.TestHelpers) EndpointType(com.apple.foundationdb.record.EndpointType) ScanProperties(com.apple.foundationdb.record.ScanProperties) TestHelpers.assertDiscardedAtLeast(com.apple.foundationdb.record.TestHelpers.assertDiscardedAtLeast) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) Tag(org.junit.jupiter.api.Tag) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Nullable(javax.annotation.Nullable) FDBRecordStoreBase(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStoreBase) TestRecords4Proto(com.apple.foundationdb.record.TestRecords4Proto) Query(com.apple.foundationdb.record.query.expressions.Query) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) IndexOptions(com.apple.foundationdb.record.metadata.IndexOptions) FDBStoreTimer(com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer) Tags(com.apple.test.Tags) TupleRange(com.apple.foundationdb.record.TupleRange) Test(org.junit.jupiter.api.Test) Objects(java.util.Objects) Index(com.apple.foundationdb.record.metadata.Index) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) Message(com.google.protobuf.Message) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) Message(com.google.protobuf.Message) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) Index(com.apple.foundationdb.record.metadata.Index) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) Test(org.junit.jupiter.api.Test)

Aggregations

TestHelpers (com.apple.foundationdb.record.TestHelpers)26 RecordQuery (com.apple.foundationdb.record.query.RecordQuery)26 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)24 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)23 EvaluationContext (com.apple.foundationdb.record.EvaluationContext)22 IndexScanType (com.apple.foundationdb.record.IndexScanType)22 Index (com.apple.foundationdb.record.metadata.Index)22 IndexTypes (com.apple.foundationdb.record.metadata.IndexTypes)22 Key (com.apple.foundationdb.record.metadata.Key)22 Query (com.apple.foundationdb.record.query.expressions.Query)22 Tags (com.apple.test.Tags)22 Message (com.google.protobuf.Message)22 Arrays (java.util.Arrays)22 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)22 Assertions.assertTrue (org.junit.jupiter.api.Assertions.assertTrue)22 Tag (org.junit.jupiter.api.Tag)22 Test (org.junit.jupiter.api.Test)22 RecordQueryPlanner (com.apple.foundationdb.record.query.plan.RecordQueryPlanner)21 PlanHashable (com.apple.foundationdb.record.PlanHashable)20 RecordCursorResult (com.apple.foundationdb.record.RecordCursorResult)20