Search in sources :

Example 96 with RecordQuery

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

the class FDBSimpleJoinQueryTest method joinParentToChild.

/**
 * Verify that simple binding joins in parent/child relationships work.
 */
@Test
public void joinParentToChild() throws Exception {
    createJoinRecords(true);
    RecordQuery parentQuery = RecordQuery.newBuilder().setRecordType("MyParentRecord").setFilter(Query.field("str_value_indexed").equalsValue("even")).build();
    RecordQueryPlan parentPlan = planner.plan(parentQuery);
    RecordQueryPlan childPlan = new RecordQueryLoadByKeysPlan("children");
    try (FDBRecordContext context = openContext()) {
        openJoinRecordStore(context);
        RecordCursor<FDBQueriedRecord<Message>> parentCursor = recordStore.executeQuery(parentPlan);
        RecordCursor<FDBQueriedRecord<Message>> childCursor = RecordCursor.flatMapPipelined(ignore -> recordStore.executeQuery(parentPlan), (rec, ignore) -> {
            TestRecordsParentChildRelationshipProto.MyParentRecord.Builder parentRec = TestRecordsParentChildRelationshipProto.MyParentRecord.newBuilder();
            parentRec.mergeFrom(rec.getRecord());
            EvaluationContext childContext = EvaluationContext.forBinding("children", parentRec.getChildRecNosList().stream().map(Tuple::from).collect(Collectors.toList()));
            return childPlan.execute(recordStore, childContext);
        }, null, 10);
        RecordCursor<String> resultsCursor = childCursor.map(rec -> {
            TestRecordsParentChildRelationshipProto.MyChildRecord.Builder childRec = TestRecordsParentChildRelationshipProto.MyChildRecord.newBuilder();
            childRec.mergeFrom(rec.getRecord());
            return childRec.getStrValue();
        });
        assertEquals(Arrays.asList("2.1", "2.2", "2.3", "4.1", "4.2", "4.3"), resultsCursor.asList().join());
        assertDiscardedNone(context);
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) RecordQueryLoadByKeysPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryLoadByKeysPlan) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) Tuple(com.apple.foundationdb.tuple.Tuple) Test(org.junit.jupiter.api.Test)

Example 97 with RecordQuery

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

the class FDBSortQueryIndexSelectionTest method sortWithScannableFilterOnIndex.

/**
 * Verify that if the sort matches an index that can satisfy a filter that the index is used.
 */
@ParameterizedTest
@MethodSource("hooks")
void sortWithScannableFilterOnIndex(RecordMetaDataHook hook, PlannableIndexTypes indexTypes) throws Exception {
    setupSimpleRecordStore(hook, (i, builder) -> builder.setRecNo(i).setNumValue2(i % 2).setNumValue3Indexed(i % 3));
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_3_indexed").greaterThanOrEquals(2)).setSort(field("num_value_3_indexed")).build();
    setupPlanner(indexTypes);
    // Index(MySimpleRecord$num_value_3_indexed [[2],>)
    RecordQueryPlan plan = planner.plan(query);
    assertThat(plan, indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), bounds(hasTupleString("[[2],>")))));
    assertEquals(1008857205, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
    assertEquals(-2059045225, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
    assertEquals(-1347749581, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    AtomicInteger lastNumValue3 = new AtomicInteger(Integer.MIN_VALUE);
    int returned = querySimpleRecordStore(hook, plan, EvaluationContext::empty, builder -> {
        assertThat(builder.getNumValue3Indexed(), greaterThanOrEqualTo(2));
        assertThat(builder.getNumValue3Indexed(), greaterThanOrEqualTo(lastNumValue3.get()));
        lastNumValue3.set(builder.getNumValue3Indexed());
    }, TestHelpers::assertDiscardedNone);
    assertEquals(33, returned);
    // reset planner
    setupPlanner(null);
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TestHelpers(com.apple.foundationdb.record.TestHelpers) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 98 with RecordQuery

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

the class FDBSortQueryIndexSelectionTest method sortByPrimaryKeyWithFilter.

private void sortByPrimaryKeyWithFilter(@Nonnull QueryComponent filter, boolean reverse, int planHash, int expectedReturn, int maxDiscarded, @Nonnull Matcher<RecordQueryPlan> planMatcher, @Nonnull TestHelpers.DangerousConsumer<TestRecords1Proto.MySimpleRecord.Builder> checkRecord) throws Exception {
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(filter).setSort(field("rec_no"), reverse).build();
    RecordQueryPlan plan = planner.plan(query);
    assertThat("unexpected plan for filter: " + filter, plan, planMatcher);
    assertEquals(planHash, plan.planHash(PlanHashable.PlanHashKind.LEGACY), "unexpected plan hash for filter: " + filter);
    AtomicLong lastId = new AtomicLong(reverse ? Long.MAX_VALUE : Long.MIN_VALUE);
    int returned = querySimpleRecordStore(NO_HOOK, plan, EvaluationContext::empty, builder -> {
        checkRecord.accept(builder);
        if (reverse) {
            assertThat(builder.getRecNo(), lessThan(lastId.get()));
        } else {
            assertThat(builder.getRecNo(), greaterThan(lastId.get()));
        }
        lastId.set(builder.getRecNo());
    }, context -> assertDiscardedAtMost(maxDiscarded, context));
    assertEquals(expectedReturn, returned, "unexpected return count for filter: " + filter);
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) AtomicLong(java.util.concurrent.atomic.AtomicLong) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery)

Example 99 with RecordQuery

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

the class FDBSortQueryIndexSelectionTest method sortWithNonScannableFilterWithAnd.

/**
 * Verify that if we have an "and" query where one of the filters matches the sort but we can't use a scan
 * that the index is used only for sorting and not to satisfy the predicate.
 */
@ParameterizedTest
@MethodSource("hooks")
void sortWithNonScannableFilterWithAnd(RecordMetaDataHook hook, PlannableIndexTypes indexTypes) throws Exception {
    setupSimpleRecordStore(hook, (i, builder) -> builder.setRecNo(i).setNumValue2(i % 2).setNumValue3Indexed(i % 3));
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("num_value_3_indexed").notEquals(1), Query.field("num_value_2").equalsValue(0))).setSort(field("num_value_3_indexed")).build();
    setupPlanner(indexTypes);
    // Fetch(Covering(Index(MySimpleRecord$num_value_3_indexed <,>) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]) | num_value_3_indexed NOT_EQUALS 1) | num_value_2 EQUALS 0
    RecordQueryPlan plan = planner.plan(query);
    assertThat(plan, filter(Query.field("num_value_2").equalsValue(0), fetch(filter(Objects.requireNonNull(Query.field("num_value_3_indexed").notEquals(1)), coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), unbounded())))))));
    assertEquals(-2013739934, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
    assertEquals(-1437222023, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
    assertEquals(-867524414, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    AtomicInteger lastNumValue3 = new AtomicInteger(Integer.MIN_VALUE);
    int returned = querySimpleRecordStore(hook, plan, EvaluationContext::empty, builder -> {
        assertThat(builder.getNumValue3Indexed(), not(equalTo(1)));
        assertThat(builder.getNumValue2(), equalTo(0));
        assertThat(builder.getNumValue3Indexed(), greaterThanOrEqualTo(lastNumValue3.get()));
        lastNumValue3.set(builder.getNumValue3Indexed());
    }, context -> assertDiscardedAtMost(66, context));
    assertEquals(34, returned);
    // reset the planner
    setupPlanner(null);
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 100 with RecordQuery

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

the class FDBSortQueryIndexSelectionTest method sortOnlyUnique.

private void sortOnlyUnique(RecordMetaDataHook hook) {
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, hook);
        for (int i = 0; i < 100; i++) {
            TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
            // Carter-Wegman hash, with large enough prime
            recBuilder.setRecNo((1096 * i + 722) % 1289);
            recBuilder.setNumValueUnique(i);
            recordStore.saveRecord(recBuilder.build());
        }
        commit(context);
    }
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setSort(field("num_value_unique")).build();
    // Index(MySimpleRecord$num_value_unique <,>)
    RecordQueryPlan plan = planner.plan(query);
    assertThat(plan, indexScan(allOf(indexName("MySimpleRecord$num_value_unique"), unbounded())));
    assertEquals(-1130465929, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
    assertEquals(-491910604, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
    assertEquals(-491910604, 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());
                assertEquals(i++, myrec.getNumValueUnique());
            }
        }
        assertEquals(100, i);
        assertDiscardedNone(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)

Aggregations

RecordQuery (com.apple.foundationdb.record.query.RecordQuery)334 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)250 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)222 Test (org.junit.jupiter.api.Test)205 Message (com.google.protobuf.Message)166 FDBQueriedRecord (com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord)163 Index (com.apple.foundationdb.record.metadata.Index)114 Query (com.apple.foundationdb.record.query.expressions.Query)114 Tags (com.apple.test.Tags)112 Tag (org.junit.jupiter.api.Tag)112 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)108 RecordQueryPlanner (com.apple.foundationdb.record.query.plan.RecordQueryPlanner)107 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)106 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)102 Arrays (java.util.Arrays)99 Expressions.field (com.apple.foundationdb.record.metadata.Key.Expressions.field)98 Collections (java.util.Collections)97 List (java.util.List)96 QueryComponent (com.apple.foundationdb.record.query.expressions.QueryComponent)95 Assertions.assertTrue (org.junit.jupiter.api.Assertions.assertTrue)93