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);
}
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);
}
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);
}
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);
}
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());
}
}
Aggregations