use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQuery7.
/**
* Verify that an OR with complex limits is implemented as a union, where the comparison key is constructed
* without repetition out of the index key and primary key (see note).
*/
@DualPlannerTest
void testOrQuery7() throws Exception {
RecordMetaDataHook hook = complexPrimaryKeyHook(true);
complexQuerySetup(hook);
setDeferFetchAfterUnionAndIntersection(true);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").equalsValue("even"), Query.or(Query.field("num_value_3_indexed").equalsValue(1), Query.field("num_value_3_indexed").greaterThan(3)))).build();
// Index(str_value_3_index [[even, 1],[even, 1]]) ∪[Field { 'str_value_indexed' None}, Field { 'num_value_3_indexed' None}, Field { 'num_value_unique' None}] Index(str_value_3_index ([even, 3],[even]])
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = fetchFromPartialRecordPlan(unionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("str_value_3_index")).and(scanComparisons(range("[[even, 1],[even, 1]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("str_value_3_index")).and(scanComparisons(range("([even, 3],[even]]")))))).where(comparisonKey(concat(Key.Expressions.field("str_value_indexed"), field("num_value_3_indexed"), field("num_value_unique")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-664830657, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1572009327, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1251823795, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = fetchFromPartialRecordPlan(unionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("str_value_3_index")).and(scanComparisons(range("[[even, 1],[even, 1]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("str_value_3_index")).and(scanComparisons(range("([even, 3],[even]]")))))).where(comparisonKey(concat(field("num_value_3_indexed"), field("num_value_unique")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-60058062, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1391842890, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(79291284, 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());
assertTrue(myrec.getStrValueIndexed().equals("even") && (myrec.getNumValue3Indexed() == 1) || myrec.getNumValue3Indexed() > 3);
i++;
}
}
assertEquals(10 + 10, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQueryPlanEquals.
/**
* Verify that queries with an OR of equality predicates on the same field are implemented using a union of indexes.
*/
@DualPlannerTest
@ParameterizedTest
@BooleanSource
void testOrQueryPlanEquals(boolean shouldDeferFetch) throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(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))).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
RecordQueryPlan plan = planner.plan(query);
RecordQuery query2 = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("num_value_3_indexed").equalsValue(4), Query.field("num_value_3_indexed").equalsValue(2), Query.field("num_value_3_indexed").equalsValue(1))).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
RecordQueryPlan plan2 = planner.plan(query2);
// plan is physically different but returns the same result
assertThat(plan.hashCode(), not(equalTo(plan2.hashCode())));
assertThat(plan, not(equalTo(plan2)));
assertTrue(plan.semanticEquals(plan2));
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQuery6.
/**
* Verify that a complex query with an OR of an AND produces a union plan if appropriate indexes are defined.
* In particular, verify that it can use the last field of an index and does not require primary key ordering
* compatibility.
*/
@DualPlannerTest
void testOrQuery6() throws Exception {
RecordMetaDataHook hook = metaData -> metaData.addIndex("MySimpleRecord", new Index("str_value_3_index", "str_value_indexed", "num_value_3_indexed"));
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.and(Query.field("str_value_indexed").equalsValue("even"), Query.field("num_value_3_indexed").greaterThan(3)), Query.field("num_value_3_indexed").lessThan(1))).build();
// Index(str_value_3_index ([even, 3],[even]]) ∪[Field { 'num_value_3_indexed' None}, Field { 'rec_no' None}] Index(MySimpleRecord$num_value_3_indexed ([null],[1]))
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof CascadesPlanner) {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = fetchFromPartialRecordPlan(unionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("str_value_3_index")).and(scanComparisons(range("([even, 3],[even]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([null],[1])")))))).where(comparisonKey(concat(Key.Expressions.field("num_value_3_indexed"), primaryKey("MySimpleRecord")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-835124758, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(778876973, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1061354639, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = unionPlan(indexPlan().where(indexName("str_value_3_index")).and(scanComparisons(range("([even, 3],[even]]"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([null],[1])")))).where(comparisonKey(concat(Key.Expressions.field("num_value_3_indexed"), primaryKey("MySimpleRecord"))));
assertMatchesExactly(plan, planMatcher);
assertEquals(1721396731, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1374663850, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1092186184, 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());
assertTrue((myrec.getStrValueIndexed().equals("even") && myrec.getNumValue3Indexed() > 3) || myrec.getNumValue3Indexed() < 1);
i++;
}
}
assertEquals(20 + 10, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQueryChildReordering.
@DualPlannerTest
@ParameterizedTest
@BooleanSource
void testOrQueryChildReordering(boolean shouldPushFetchAboveUnionToIntersection) throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query1 = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("str_value_indexed").equalsValue("odd"), Query.field("num_value_3_indexed").equalsValue(0))).setSort(null, true).setRemoveDuplicates(true).build();
setDeferFetchAfterUnionAndIntersection(shouldPushFetchAboveUnionToIntersection);
// Index(MySimpleRecord$str_value_indexed [[odd],[odd]] REVERSE) ∪ Index(MySimpleRecord$num_value_3_indexed [[0],[0]] REVERSE)
// Fetch(Covering(Index(MySimpleRecord$str_value_indexed [[odd],[odd]] REVERSE) -> [rec_no: KEY[1], str_value_indexed: KEY[0]]) ∪ Covering(Index(MySimpleRecord$num_value_3_indexed [[0],[0]] REVERSE) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]))
RecordQueryPlan plan1 = planner.plan(query1);
RecordQuery query2 = query1.toBuilder().setFilter(Query.or(Query.field("num_value_3_indexed").equalsValue(0), Query.field("str_value_indexed").equalsValue("odd"))).build();
// Index(MySimpleRecord$num_value_3_indexed [[0],[0]] REVERSE) ∪ Index(MySimpleRecord$str_value_indexed [[odd],[odd]] REVERSE)
// Fetch(Covering(Index(MySimpleRecord$num_value_3_indexed [[0],[0]] REVERSE) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]) ∪ Covering(Index(MySimpleRecord$str_value_indexed [[odd],[odd]] REVERSE) -> [rec_no: KEY[1], str_value_indexed: KEY[0]]))
RecordQueryPlan plan2 = planner.plan(query2);
assertNotEquals(plan1.hashCode(), plan2.hashCode());
assertNotEquals(plan1, plan2);
assertEquals(plan1.semanticHashCode(), plan2.semanticHashCode());
assertTrue(plan1.semanticEquals(plan2));
if (shouldPushFetchAboveUnionToIntersection || planner instanceof CascadesPlanner) {
assertEquals(-1584186103, plan1.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-357068519, plan1.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(964023338, plan1.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(-91575587, plan2.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1919956247, plan2.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(78160824, plan2.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertEquals(-2067012572, plan1.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1784357954, plan1.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1189517485, plan1.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(600484528, plan2.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(221470226, plan2.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-2075379999, plan2.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
Set<Long> seen = new HashSet<>();
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
int i = 0;
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor1 = recordStore.executeQuery(plan1).asIterator();
RecordCursorIterator<FDBQueriedRecord<Message>> cursor2 = recordStore.executeQuery(plan2).asIterator()) {
while (cursor1.hasNext()) {
assertThat(cursor2.hasNext(), is(true));
FDBQueriedRecord<Message> rec1 = cursor1.next();
FDBQueriedRecord<Message> rec2 = cursor2.next();
assertEquals(Objects.requireNonNull(rec1).getRecord(), Objects.requireNonNull(rec2).getRecord());
TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
myrec.mergeFrom(rec1.getRecord());
assertTrue(myrec.getStrValueIndexed().equals("odd") || myrec.getNumValue3Indexed() == 0, "condition on record not met");
assertFalse(seen.contains(myrec.getRecNo()), "Already saw a record!");
seen.add(myrec.getRecNo());
i++;
}
assertThat(cursor2.hasNext(), is(false));
}
assertEquals(60, i);
assertDiscardedAtMost(20, context);
if (shouldPushFetchAboveUnionToIntersection) {
assertLoadRecord(120, context);
}
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testComplexQuery6.
/**
* Verify that an OR of compatibly-ordered (up to reversal) indexed fields can be implemented as a union.
*/
@DualPlannerTest
@ParameterizedTest
@BooleanSource
void testComplexQuery6(boolean shouldDeferFetch) throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("str_value_indexed").equalsValue("odd"), Query.field("num_value_3_indexed").equalsValue(0))).setSort(null, true).setRemoveDuplicates(true).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
// Index(MySimpleRecord$str_value_indexed [[odd],[odd]] REVERSE) ∪ Index(MySimpleRecord$num_value_3_indexed [[0],[0]] REVERSE)
// Fetch(Covering(Index(MySimpleRecord$str_value_indexed [[odd],[odd]] REVERSE) -> [rec_no: KEY[1], str_value_indexed: KEY[0]]) ∪ Covering(Index(MySimpleRecord$num_value_3_indexed [[0],[0]] REVERSE) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]))
RecordQueryPlan plan = planner.plan(query);
if (shouldDeferFetch || planner instanceof CascadesPlanner) {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = fetchFromPartialRecordPlan(unionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("[[odd],[odd]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[0],[0]]")))))));
assertMatchesExactly(plan, planMatcher);
assertTrue(plan.getQueryPlanChildren().stream().allMatch(QueryPlan::isReverse));
assertEquals(-1584186103, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-357068519, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(964023338, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = unionPlan(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("[[odd],[odd]]"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[0],[0]]"))));
assertMatchesExactly(plan, planMatcher);
assertTrue(plan.getQueryPlanChildren().stream().allMatch(QueryPlan::isReverse));
assertEquals(-2067012572, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1784357954, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1189517485, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
Set<Long> seen = new HashSet<>();
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());
assertTrue(myrec.getStrValueIndexed().equals("odd") || myrec.getNumValue3Indexed() == 0, "condition on record not met");
assertFalse(seen.contains(myrec.getRecNo()), "Already saw a record!");
seen.add(myrec.getRecNo());
i++;
}
}
assertEquals(60, i);
assertDiscardedAtMost(10, context);
if (shouldDeferFetch) {
assertLoadRecord(60, context);
}
}
}
Aggregations