use of com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.comparisonKey in project fdb-record-layer by FoundationDB.
the class FDBInQueryTest method inQueryWithSortAndRangePredicateOnSecondFieldOfCompoundIndex.
/**
* Verify that an IN query with a sort and range predicate can be implemented as an ordered union of compound indexes
* that can satisfy the sort once the equality predicates from the IN have been pushed onto the indexes.
* @see com.apple.foundationdb.record.query.plan.planning.InExtractor#asOr()
*/
@ParameterizedTest
@EnumSource(InAsOrUnionMode.class)
void inQueryWithSortAndRangePredicateOnSecondFieldOfCompoundIndex(InAsOrUnionMode inAsOrMode) throws Exception {
RecordMetaDataHook hook = metaData -> metaData.addIndex("MySimpleRecord", "compoundIndex", concat(field("num_value_3_indexed"), field("str_value_indexed")));
complexQuerySetup(hook);
final List<Integer> inList = asList(1, 4, 2);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("num_value_3_indexed").in(inList), Query.field("str_value_indexed").greaterThan("bar"), Query.field("str_value_indexed").lessThan("foo"))).setSort(field("str_value_indexed")).build();
// The configuration is planner-specific.
assertTrue(planner instanceof RecordQueryPlanner);
RecordQueryPlanner recordQueryPlanner = (RecordQueryPlanner) planner;
recordQueryPlanner.setConfiguration(inAsOrMode.configure(recordQueryPlanner.getConfiguration().asBuilder()).build());
// Index(MySimpleRecord$str_value_indexed ([bar],[foo])) | num_value_3_indexed IN [1, 4, 2]
// Index(compoundIndex ([1, bar],[1, foo])) ∪[Field { 'str_value_indexed' None}, Field { 'rec_no' None}] Index(compoundIndex ([4, bar],[4, foo])) ∪[Field { 'str_value_indexed' None}, Field { 'rec_no' None}] Index(compoundIndex ([2, bar],[2, foo]))
// ∪(__in_num_value_3_indexed__0 IN [1, 4, 2]) Index(compoundIndex [EQUALS $__in_num_value_3_indexed__0, [GREATER_THAN bar && LESS_THAN foo]])
RecordQueryPlan plan = planner.plan(query);
if (inAsOrMode == InAsOrUnionMode.AS_OR) {
// IN join is impossible because of incompatible sorting, but we can still plan as an OR on the compound index.
assertMatchesExactly(plan, unionPlan(inList.stream().map(number -> indexPlan().where(indexName("compoundIndex")).and(scanComparisons(range(String.format("([%d, bar],[%d, foo])", number, number))))).collect(ImmutableList.toImmutableList())).where(RecordQueryPlanMatchers.comparisonKey(equalsObject(concat(field("str_value_indexed"), primaryKey("MySimpleRecord"))))));
assertEquals(651476052, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-2091774924, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1421992908, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else if (inAsOrMode == InAsOrUnionMode.AS_UNION) {
assertMatchesExactly(plan, inUnionPlan(indexPlan().where(indexName("compoundIndex")).and(scanComparisons(range("[EQUALS $__in_num_value_3_indexed__0, [GREATER_THAN bar && LESS_THAN foo]]")))).where(inUnionComparisonKey(concat(field("str_value_indexed"), primaryKey("MySimpleRecord")))).and(inUnionValuesSources(exactly(inUnionInValues(equalsObject(inList)).and(inUnionBindingName("__in_num_value_3_indexed__0"))))));
assertEquals(591462908, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(834697335, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1630766853, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertMatchesExactly(plan, filterPlan(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("([bar],[foo])")))).where(queryComponents(only(equalsObject(Query.field("num_value_3_indexed").in(inList))))));
assertEquals(-1681846586, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(340962909, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-790068626, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
assertEquals(30, querySimpleRecordStore(hook, plan, EvaluationContext::empty, record -> assertThat(record.getNumValue3Indexed(), anyOf(is(1), is(2), is(4))), context -> {
}));
}
Aggregations