use of com.apple.foundationdb.record.query.plan.RecordQueryPlanner in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQueryNoIndex.
/**
* Verify that queries with an OR of predicates with a common scan and different filters does not bother with a Union.
*/
@DualPlannerTest
void testOrQueryNoIndex() throws Exception {
RecordMetaDataHook hook = metadata -> metadata.removeIndex("MySimpleRecord$num_value_3_indexed");
complexQuerySetup(hook);
QueryComponent orComponent = Query.or(Query.field("num_value_3_indexed").equalsValue(1), Query.field("num_value_3_indexed").equalsValue(2), Query.field("num_value_3_indexed").equalsValue(4));
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").equalsValue("even"), orComponent)).build();
// Index(MySimpleRecord$str_value_indexed [[even],[even]]) | Or([num_value_3_indexed EQUALS 1, num_value_3_indexed EQUALS 2, num_value_3_indexed EQUALS 4])
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = filterPlan(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("[[even],[even]]")))).where(queryComponents(exactly(equalsObject(orComponent))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-1553701984, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1108620348, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1573180943, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("[[even],[even]]")))).where(predicates(only(orPredicate(exactly(valuePredicate(fieldValue("num_value_3_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, 1)), valuePredicate(fieldValue("num_value_3_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, 2)), valuePredicate(fieldValue("num_value_3_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, 4)))))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-1029166388, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1957223857, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1873182844, 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("even", myrec.getStrValueIndexed());
assertTrue(myrec.getNumValue3Indexed() == 1 || myrec.getNumValue3Indexed() == 2 || myrec.getNumValue3Indexed() == 4);
i++;
}
}
assertEquals(10 + 10 + 10, i);
assertDiscardedExactly(10 + 10, context);
}
}
use of com.apple.foundationdb.record.query.plan.RecordQueryPlanner in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQueryToDistinctUnionWithPartialDefer.
@DualPlannerTest
void testOrQueryToDistinctUnionWithPartialDefer() throws Exception {
complexQuerySetup(null);
setDeferFetchAfterUnionAndIntersection(true);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("str_value_indexed").equalsValue("m"), Query.field("num_value_3_indexed").equalsValue(3), Query.and(Query.field("num_value_2").equalsValue(3), Query.field("num_value_3_indexed").equalsValue(4)))).setRemoveDuplicates(true).build();
final RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = unionPlan(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")), filterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed"))).where(queryComponents(exactly(equalsObject(Query.field("num_value_2").equalsValue(3))))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-91578519, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1329489138, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1714281445, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = unionPlan(fetchFromPartialRecordPlan(unionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")))))), predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed"))).where(predicates(only(valuePredicate(fieldValue("num_value_2"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, 3))))));
assertMatchesExactly(plan, planMatcher);
assertEquals(357806958, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-325811449, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-2072211590, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
}
use of com.apple.foundationdb.record.query.plan.RecordQueryPlanner in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testComplexOrQueryToDistinctUnion.
/**
* TODO [Cascades Planner] We have a UNION DISTINCT of identical arms all containing the same filter. If the filter
* is pulled above the UNION the fetch can also be deferred until after the UNION which may be beneficial
* (according to the current cost model which is probably correct).
*/
@DualPlannerTest
void testComplexOrQueryToDistinctUnion() throws Exception {
complexQuerySetup(null);
setDeferFetchAfterUnionAndIntersection(true);
final RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").equalsValue("outer"), Query.or(Query.and(Query.field("num_value_3_indexed").greaterThan(1), Query.field("num_value_3_indexed").lessThan(2)), Query.and(Query.field("num_value_3_indexed").greaterThan(3), Query.field("num_value_3_indexed").lessThan(4)), Query.and(Query.field("num_value_3_indexed").greaterThan(5), Query.field("num_value_3_indexed").lessThan(6)), Query.and(Query.field("num_value_3_indexed").greaterThan(7), Query.field("num_value_3_indexed").lessThan(8)), Query.and(Query.field("num_value_3_indexed").greaterThan(9), Query.field("num_value_3_indexed").lessThan(10)), Query.and(Query.field("num_value_3_indexed").greaterThan(11), Query.field("num_value_3_indexed").lessThan(12)), Query.and(Query.field("num_value_3_indexed").greaterThan(13), Query.field("num_value_3_indexed").lessThan(14)), Query.and(Query.field("num_value_3_indexed").greaterThan(15), Query.field("num_value_3_indexed").lessThan(16)), Query.and(Query.field("num_value_3_indexed").greaterThan(17), Query.field("num_value_3_indexed").lessThan(18))))).setRemoveDuplicates(true).build();
final RecordQueryPlan plan = planner.plan(query);
final BindingMatcher<? extends RecordQueryPlan> planMatcher;
if (planner instanceof RecordQueryPlanner) {
planMatcher = filterPlan(fetchFromPartialRecordPlan(unionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([1],[2])"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([3],[4])"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([5],[6])"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([7],[8])"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([9],[10])"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([11],[12])"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([13],[14])"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([15],[16])"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([17],[18])")))))).where(comparisonKey(concat(field("num_value_3_indexed"), primaryKey("MySimpleRecord")))))).where(queryComponents(exactly(equalsObject(Query.field("str_value_indexed").equalsValue("outer")))));
} else {
planMatcher = unionPlan(predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([1],[2])")))).where(predicates(only(valuePredicate(fieldValue("str_value_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, "outer"))))), predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([3],[4])")))).where(predicates(only(valuePredicate(fieldValue("str_value_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, "outer"))))), predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([5],[6])")))).where(predicates(only(valuePredicate(fieldValue("str_value_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, "outer"))))), predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([7],[8])")))).where(predicates(only(valuePredicate(fieldValue("str_value_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, "outer"))))), predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([9],[10])")))).where(predicates(only(valuePredicate(fieldValue("str_value_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, "outer"))))), predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([11],[12])")))).where(predicates(only(valuePredicate(fieldValue("str_value_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, "outer"))))), predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([13],[14])")))).where(predicates(only(valuePredicate(fieldValue("str_value_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, "outer"))))), predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([15],[16])")))).where(predicates(only(valuePredicate(fieldValue("str_value_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, "outer"))))), predicatesFilterPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([17],[18])")))).where(predicates(only(valuePredicate(fieldValue("str_value_indexed"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, "outer")))))).where(comparisonKey(concat(field("num_value_3_indexed"), primaryKey("MySimpleRecord"))));
}
assertMatches(plan, planMatcher);
}
use of com.apple.foundationdb.record.query.plan.RecordQueryPlanner in project fdb-record-layer by FoundationDB.
the class FDBInQueryTest method testInQueryOrOverlap.
/**
* Verify that IN queries can be planned using index scans, then used in a UNION to implement an OR with IN whose
* elements overlap, and that the union with that comparison key deduplicates the records in the overlap.
*/
@DualPlannerTest
void testInQueryOrOverlap() throws Exception {
complexQuerySetup(NO_HOOK);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("num_value_unique").in(Arrays.asList(903, 905, 901)), Query.field("num_value_unique").in(Arrays.asList(906, 905, 904)))).build();
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
// Index(MySimpleRecord$num_value_unique [EQUALS $__in_num_value_unique__0]) WHERE __in_num_value_unique__0 IN [901, 903, 905] SORTED ∪[Field { 'num_value_unique' None}, Field { 'rec_no' None}] Index(MySimpleRecord$num_value_unique [EQUALS $__in_num_value_unique__0]) WHERE __in_num_value_unique__0 IN [904, 905, 906] SORTED
// Ordinary equality comparisons would be ordered just by the primary key so that would be the union comparison key.
// Must compare the IN field here; they are ordered, but not trivially (same value for each).
assertMatchesExactly(plan, unionPlan(inValuesJoinPlan(indexPlan().where(indexName("MySimpleRecord$num_value_unique")).and(scanComparisons(range("[EQUALS $__in_num_value_unique__0]")))).where(inValuesList(equalsObject(Arrays.asList(901, 903, 905)))), inValuesJoinPlan(indexPlan().where(indexName("MySimpleRecord$num_value_unique")).and(scanComparisons(range("[EQUALS $__in_num_value_unique__0]")))).where(inValuesList(equalsObject(Arrays.asList(904, 905, 906))))));
assertEquals(218263868, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(468995802, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(2098251608, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertMatchesExactly(plan, fetchFromPartialRecordPlan(unionPlan(inValuesJoinPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_unique")).and(scanComparisons(equalities(exactly(anyParameterComparison()))))))).where(inValuesList(equalsObject(Arrays.asList(901, 903, 905)))), inValuesJoinPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_unique")).and(scanComparisons(equalities(exactly(anyParameterComparison()))))))).where(inValuesList(equalsObject(Arrays.asList(904, 905, 906))))).where(comparisonKey(concat(field("num_value_unique"), primaryKey("MySimpleRecord"))))));
assertEquals(-1323754895, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(856768529, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1700358353, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
Set<Long> dupes = new HashSet<>();
assertEquals(5, querySimpleRecordStore(NO_HOOK, plan, EvaluationContext::empty, record -> {
assertTrue(dupes.add(record.getRecNo()), "should not have duplicated records");
assertThat(record.getNumValueUnique(), anyOf(is(901), is(903), is(904), is(905), is(906)));
}, context -> TestHelpers.assertDiscardedAtMost(1, context)));
}
use of com.apple.foundationdb.record.query.plan.RecordQueryPlanner in project fdb-record-layer by FoundationDB.
the class FDBInQueryTest method inQueryWithSortAndParameter.
/**
* Verify that an IN query over a parameter with a sort keeps filter even if OR is allowed.
*/
@ParameterizedTest
@EnumSource(InAsOrUnionMode.class)
void inQueryWithSortAndParameter(InAsOrUnionMode inAsOrMode) throws Exception {
RecordMetaDataHook hook = metaData -> metaData.addIndex("MySimpleRecord", "compoundIndex", concat(field("num_value_3_indexed"), field("str_value_indexed")));
complexQuerySetup(hook);
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 $inList
// ∪(__in_num_value_3_indexed__0 IN $inList) Index(compoundIndex [EQUALS $__in_num_value_3_indexed__0, [GREATER_THAN bar && LESS_THAN foo]])
RecordQueryPlan plan = planner.plan(query);
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(inUnionInParameter(equalsObject("inList")).and(inUnionBindingName("__in_num_value_3_indexed__0"))))));
assertEquals(-625336982, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-382102555, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1724734348, 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(1428066748, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1407869064, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(65237271, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
assertEquals(30, querySimpleRecordStore(hook, plan, () -> EvaluationContext.forBinding("inList", asList(1, 3, 4)), record -> assertThat(record.getNumValue3Indexed(), anyOf(is(1), is(3), is(4))), context -> {
}));
assertEquals(0, querySimpleRecordStore(hook, plan, () -> EvaluationContext.forBinding("inList", ImmutableList.of()), record -> fail("should not have any records"), context -> {
}));
assertEquals(10, querySimpleRecordStore(hook, plan, () -> EvaluationContext.forBinding("inList", ImmutableList.of(3)), record -> assertThat(record.getNumValue3Indexed(), is(3)), context -> {
}));
}
Aggregations