Search in sources :

Example 21 with EvaluationContext

use of com.apple.foundationdb.record.EvaluationContext 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 22 with EvaluationContext

use of com.apple.foundationdb.record.EvaluationContext 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 23 with EvaluationContext

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

the class FDBSortQueryIndexSelectionTest method sortByPrimaryKey.

/**
 * Verify that we can sort by the primary key if possible.
 */
@DualPlannerTest
@ParameterizedTest(name = "sortByPrimaryKey() [{0}]")
@BooleanSource
void sortByPrimaryKey(boolean reverse) throws Exception {
    setupSimpleRecordStore(NO_HOOK, (i, builder) -> builder.setRecNo(i).setNumValue2(i % 2));
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setSort(field("rec_no"), reverse).build();
    RecordQueryPlan plan = planner.plan(query);
    assertThat(plan, typeFilter(contains("MySimpleRecord"), scan(unbounded())));
    AtomicLong lastId = new AtomicLong(reverse ? 99L : 0L);
    int returned = querySimpleRecordStore(NO_HOOK, plan, EvaluationContext::empty, builder -> assertThat(builder.getRecNo(), equalTo(reverse ? lastId.getAndDecrement() : lastId.getAndIncrement())), TestHelpers::assertDiscardedNone);
    assertEquals(100, returned);
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) AtomicLong(java.util.concurrent.atomic.AtomicLong) 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) BooleanSource(com.apple.test.BooleanSource)

Example 24 with EvaluationContext

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

the class FDBSortQueryIndexSelectionTest method sortWithNonScannableFilterOnIndex.

/**
 * Verify that if there is an index on the sorted field but it does not satisfy the comparison
 * of a filter (because that comparison cannot be accomplished with a scan) that the index
 * is still used solely to accomplish sorting.
 */
@ParameterizedTest
@MethodSource("hooks")
void sortWithNonScannableFilterOnIndex(RecordMetaDataHook hook, PlannableIndexTypes indexTypes) throws Exception {
    setupSimpleRecordStore(hook, (i, builder) -> builder.setRecNo(i).setNumValue2(i % 2).setNumValue3Indexed(i % 3));
    final QueryComponent filter = Query.field("num_value_3_indexed").notEquals(1);
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(filter).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)
    RecordQueryPlan plan = planner.plan(query);
    assertThat(plan, fetch(filter(filter, coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), unbounded()))))));
    assertEquals(-1303978120, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
    assertEquals(1548200279, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
    assertEquals(-856491930, 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.getNumValue3Indexed(), greaterThanOrEqualTo(lastNumValue3.get()));
        lastNumValue3.set(builder.getNumValue3Indexed());
    }, context -> assertDiscardedAtMost(33, context));
    assertEquals(67, returned);
    // reset planner
    setupPlanner(null);
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) 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 25 with EvaluationContext

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

the class LeaderboardIndexTest method basicQuery.

protected void basicQuery(Leaderboards leaderboards) {
    basicSetup(leaderboards, true);
    try (FDBRecordContext context = openContext()) {
        leaderboards.openRecordStore(context, false);
        final String recordType = leaderboards.getRecordType();
        final RecordQuery query1 = RecordQuery.newBuilder().setRecordType(recordType).setFilter(Query.and(Query.field("game_id").equalsValue("game-1"), leaderboards.queryRank().greaterThanOrEquals(1L), leaderboards.queryRank().lessThanOrEquals(2L))).build();
        final RecordQueryPlan plan1 = leaderboards.planQuery(query1);
        assertEquals("Index(LeaderboardIndex [[game-1, 1],[game-1, 2]] BY_RANK)", plan1.toString());
        assertEquals(Arrays.asList("hecuba", "achilles"), leaderboards.executeQuery(plan1).map(leaderboards::getName).asList().join());
        final RecordQuery query2 = RecordQuery.newBuilder().setRecordType(recordType).setFilter(Query.and(Query.field("game_id").equalsValue("game-1"), leaderboards.queryTimeWindowRank("l1", "l2").lessThanOrEquals(2L))).build();
        RecordQueryPlan plan2 = leaderboards.planQuery(query2);
        assertEquals("Index(LeaderboardIndex ([game-1, null],[game-1, 2]]@$l1,$l2 BY_TIME_WINDOW)", plan2.toString());
        final EvaluationContext evaluationContext1 = EvaluationContext.newBuilder().setBinding("l1", FIVE_UNITS).setBinding("l2", 10103).build();
        assertEquals(Arrays.asList("hector", "achilles"), leaderboards.executeQuery(plan2, evaluationContext1).map(leaderboards::getName).asList().join());
        final EvaluationContext evaluationContext2 = EvaluationContext.newBuilder().setBinding("l1", FIVE_UNITS).setBinding("l2", 10105).build();
        assertEquals(Arrays.asList("achilles", "hector"), leaderboards.executeQuery(plan2, evaluationContext2).map(leaderboards::getName).asList().join());
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery)

Aggregations

EvaluationContext (com.apple.foundationdb.record.EvaluationContext)43 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)33 RecordQuery (com.apple.foundationdb.record.query.RecordQuery)31 Message (com.google.protobuf.Message)28 FDBQueriedRecord (com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord)27 List (java.util.List)27 PlanHashable (com.apple.foundationdb.record.PlanHashable)25 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)25 ImmutableList (com.google.common.collect.ImmutableList)24 Objects (java.util.Objects)24 Set (java.util.Set)23 Test (org.junit.jupiter.api.Test)23 ArrayList (java.util.ArrayList)22 Collections (java.util.Collections)22 Index (com.apple.foundationdb.record.metadata.Index)21 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)20 TestHelpers (com.apple.foundationdb.record.TestHelpers)20 Comparisons (com.apple.foundationdb.record.query.expressions.Comparisons)20 Query (com.apple.foundationdb.record.query.expressions.Query)20 Tags (com.apple.test.Tags)20