use of com.apple.test.BooleanSource in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQuery4.
/**
* Verify that queries with an OR of equality predicates on different fields are implemented using a union of indexes,
* if all fields are indexed.
*/
@DualPlannerTest
@ParameterizedTest
@BooleanSource
void testOrQuery4(boolean shouldDeferFetch) throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("str_value_indexed").equalsValue("even"), Query.field("num_value_3_indexed").equalsValue(1), Query.field("num_value_3_indexed").equalsValue(3))).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
// Fetch(Covering(Index(MySimpleRecord$str_value_indexed [[even],[even]]) -> [rec_no: KEY[1], str_value_indexed: KEY[0]]) ∪ Covering(Index(MySimpleRecord$num_value_3_indexed [[1],[1]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]) ∪ Covering(Index(MySimpleRecord$num_value_3_indexed [[3],[3]]) -> [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("[[even],[even]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[1],[1]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[3],[3]]")))))).where(comparisonKey(primaryKey("MySimpleRecord"))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-417814093, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1082480572, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(233155848, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = unionPlan(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("[[even],[even]]"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[1],[1]]"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[3],[3]]")))).where(comparisonKey(primaryKey("MySimpleRecord")));
assertMatchesExactly(plan, planMatcher);
assertEquals(-673254486, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(991016881, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1988313995, 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(50 + 10 + 10, i);
assertDiscardedAtMost(20, context);
if (shouldDeferFetch) {
assertLoadRecord(50 + 10 + 10, context);
}
}
}
use of com.apple.test.BooleanSource in project fdb-record-layer by FoundationDB.
the class FDBAndQueryToIntersectionTest method testComplexQueryAndWithIncompatibleFilters.
/**
* Verify that a complex query with an AND of fields that are _not_ compatibly ordered generates a plan without
* an intersection (uses filter instead).
*/
@ParameterizedTest
@BooleanSource
public void testComplexQueryAndWithIncompatibleFilters(final boolean shouldOptimizeForIndexFilters) throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").startsWith("e"), Query.field("num_value_3_indexed").equalsValue(3))).build();
setOptimizeForIndexFilters(shouldOptimizeForIndexFilters);
// Index(MySimpleRecord$str_value_indexed {[e],[e]}) | num_value_3_indexed EQUALS 3
// Fetch(Covering(Index(multi_index {[e],[e]}) -> [num_value_2: KEY[1], num_value_3_indexed: KEY[2], rec_no: KEY[3], str_value_indexed: KEY[0]]) | num_value_3_indexed EQUALS 3)
RecordQueryPlan plan = planner.plan(query);
// Not an intersection plan, since not compatibly ordered.
if (shouldOptimizeForIndexFilters) {
assertThat(plan, allOf(hasNoDescendant(intersection(anything(), anything())), descendant(filter(Query.field("num_value_3_indexed").equalsValue(3), coveringIndexScan(indexScan(anyOf(indexName("multi_index"), bounds(hasTupleString("[[e],[e]]")))))))));
assertFalse(plan.hasRecordScan(), "should not use record scan");
assertEquals(-1810430840, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1492232944, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1442514296, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, allOf(hasNoDescendant(intersection(anything(), anything())), descendant(indexScan(anyOf(indexName("MySimpleRecord$str_value_indexed"), indexName("MySimpleRecord$num_value_3_indexed"))))));
assertFalse(plan.hasRecordScan(), "should not use record scan");
assertEquals(746853985, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(312168193, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(361886841, 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(rec.getRecord());
assertEquals("even", myrec.getStrValueIndexed());
assertTrue((myrec.getNumValue3Indexed() % 5) == 3);
i++;
}
}
assertEquals(10, i);
assertDiscardedExactly(40, context);
assertLoadRecord(50, context);
}
}
use of com.apple.test.BooleanSource in project fdb-record-layer by FoundationDB.
the class FDBAndQueryToIntersectionTest method testComplexQueryAndWithTwoChildren.
/**
* Verify that a complex query with an AND of fields with compatibly ordered indexes generates an intersection plan.
*/
@ParameterizedTest
@BooleanSource
public void testComplexQueryAndWithTwoChildren(boolean shouldDeferFetch) throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").equalsValue("even"), Query.field("num_value_3_indexed").equalsValue(3))).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
// Index(MySimpleRecord$str_value_indexed [[even],[even]]) ∩ Index(MySimpleRecord$num_value_3_indexed [[3],[3]])
// Fetch(Covering(Index(MySimpleRecord$str_value_indexed [[even],[even]]) -> [rec_no: KEY[1], str_value_indexed: KEY[0]]) ∩ Covering(Index(MySimpleRecord$num_value_3_indexed [[3],[3]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]))
RecordQueryPlan plan = planner.plan(query);
if (shouldDeferFetch) {
assertThat(plan, fetch(intersection(coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$str_value_indexed"), bounds(hasTupleString("[[even],[even]]"))))), coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), bounds(hasTupleString("[[3],[3]]"))))), equalTo(field("rec_no")))));
assertEquals(-929788310, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1914172894, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-271606869, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, intersection(indexScan(allOf(indexName("MySimpleRecord$str_value_indexed"), bounds(hasTupleString("[[even],[even]]")))), indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), bounds(hasTupleString("[[3],[3]]")))), equalTo(field("rec_no"))));
assertEquals(-1973527173, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(227253579, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1869819604, 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(rec.getRecord());
assertEquals("even", myrec.getStrValueIndexed());
assertTrue((myrec.getNumValue3Indexed() % 5) == 3);
i++;
}
}
assertEquals(10, i);
assertDiscardedExactly(50, context);
if (shouldDeferFetch) {
assertLoadRecord(10, context);
}
}
}
use of com.apple.test.BooleanSource in project fdb-record-layer by FoundationDB.
the class FDBAndQueryToIntersectionTest method testComplexQueryAndWithSomeIncompatibleFilters.
/**
* Verify that a complex query with an AND of fields where some of them are compatibly ordered uses an intersection
* for only those filters.
*/
@ParameterizedTest
@BooleanSource
public void testComplexQueryAndWithSomeIncompatibleFilters(boolean shouldDeferFetch) throws Exception {
// Add an additional index to use for additional filtering
RecordMetaDataHook hook = (metaDataBuilder) -> {
complexQuerySetupHook().apply(metaDataBuilder);
metaDataBuilder.removeIndex("multi_index");
metaDataBuilder.addIndex("MySimpleRecord", "MySimpleRecord$num_value_2", field("num_value_2"));
};
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").startsWith("e"), Query.field("num_value_3_indexed").equalsValue(0), Query.field("num_value_2").equalsValue(2))).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
// Fetch(Covering(Index(MySimpleRecord$num_value_3_indexed [[0],[0]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]) ∩ Covering(Index(MySimpleRecord$num_value_2 [[2],[2]]) -> [num_value_2: KEY[0], rec_no: KEY[1]])) | str_value_indexed STARTS_WITH e
RecordQueryPlan plan = planner.plan(query);
if (shouldDeferFetch) {
assertThat(plan, filter(Query.field("str_value_indexed").startsWith("e"), fetch(intersection(coveringIndexScan(indexScan(allOf(indexName(equalTo("MySimpleRecord$num_value_3_indexed")), bounds(hasTupleString("[[0],[0]]"))))), coveringIndexScan(indexScan(allOf(indexName(equalTo("MySimpleRecord$num_value_2")), bounds(hasTupleString("[[2],[2]]"))))), equalTo(field("rec_no"))))));
assertEquals(-1979861885, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1271604119, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1737180988, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, filter(Query.field("str_value_indexed").startsWith("e"), intersection(indexScan(allOf(indexName(equalTo("MySimpleRecord$num_value_3_indexed")), bounds(hasTupleString("[[0],[0]]")))), indexScan(allOf(indexName(equalTo("MySimpleRecord$num_value_2")), bounds(hasTupleString("[[2],[2]]")))), equalTo(field("rec_no")))));
assertEquals(1095867174, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(688107104, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(222530235, 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(rec.getRecord());
assertEquals("even", myrec.getStrValueIndexed());
assertEquals(0, myrec.getNumValue3Indexed());
assertEquals(2, myrec.getNumValue2());
i++;
}
}
assertEquals(3, i);
assertDiscardedAtMost(42, context);
if (shouldDeferFetch) {
assertLoadRecord(7, context);
}
}
}
use of com.apple.test.BooleanSource in project fdb-record-layer by FoundationDB.
the class FDBFullTextQueryTest method delayFetchOnUnionOfFullTextScans.
@ParameterizedTest
@BooleanSource
public void delayFetchOnUnionOfFullTextScans(boolean shouldDeferFetch) throws Exception {
final List<TestRecordsTextProto.SimpleDocument> documents = TextIndexTestUtils.toSimpleDocuments(Arrays.asList(TextSamples.ANGSTROM, TextSamples.AETHELRED, TextSamples.ROMEO_AND_JULIET_PROLOGUE, TextSamples.FRENCH));
try (FDBRecordContext context = openContext()) {
openRecordStore(context);
documents.forEach(recordStore::saveRecord);
commit(context);
}
try (FDBRecordContext context = openContext()) {
openRecordStore(context);
final QueryComponent filter1 = Query.field("text").text().containsPhrase("civil blood makes civil hands unclean");
final Comparisons.Comparison comparison1 = new Comparisons.TextComparison(Comparisons.Type.TEXT_CONTAINS_PHRASE, "civil blood makes civil hands unclean", null, DefaultTextTokenizer.NAME);
final QueryComponent filter2 = Query.field("text").text().containsPrefix("th");
final Comparisons.Comparison comparison2 = new Comparisons.TextComparison(Comparisons.Type.TEXT_CONTAINS_PREFIX, Collections.singletonList("th"), null, DefaultTextTokenizer.NAME);
// Query for full records
RecordQuery query = RecordQuery.newBuilder().setRecordType(TextIndexTestUtils.SIMPLE_DOC).setFilter(Query.or(filter1, filter2)).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
// Unordered(TextIndex(SimpleDocument$text null, TEXT_CONTAINS_PHRASE civil blood makes civil hands unclean, null) ∪ TextIndex(SimpleDocument$text null, TEXT_CONTAINS_PREFIX [th], null) | UnorderedPrimaryKeyDistinct()) | UnorderedPrimaryKeyDistinct()
// Fetch(Unordered(Covering(TextIndex(SimpleDocument$text null, TEXT_CONTAINS_PHRASE civil blood makes civil hands unclean, null) -> [doc_id: KEY[1]]) ∪ Covering(TextIndex(SimpleDocument$text null, TEXT_CONTAINS_PREFIX [th], null) -> [doc_id: KEY[1]]) | UnorderedPrimaryKeyDistinct()) | UnorderedPrimaryKeyDistinct())
RecordQueryPlan plan = planner.plan(query);
if (shouldDeferFetch) {
assertThat(plan, fetch(primaryKeyDistinct(unorderedUnion(coveringIndexScan(textIndexScan(allOf(indexName(TextIndexTestUtils.SIMPLE_DEFAULT_NAME), textComparison(equalTo(comparison1))))), primaryKeyDistinct(coveringIndexScan(textIndexScan(allOf(indexName(TextIndexTestUtils.SIMPLE_DEFAULT_NAME), textComparison(equalTo(comparison2))))))))));
assertEquals(-683922391, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-833837033, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-464003585, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, primaryKeyDistinct(unorderedUnion(textIndexScan(allOf(indexName(TextIndexTestUtils.SIMPLE_DEFAULT_NAME), textComparison(equalTo(comparison1)))), primaryKeyDistinct(textIndexScan(allOf(indexName(TextIndexTestUtils.SIMPLE_DEFAULT_NAME), textComparison(equalTo(comparison2))))))));
assertEquals(515863556, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1307589440, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1677422888, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
List<Long> primaryKeys = recordStore.executeQuery(plan).map(FDBQueriedRecord::getPrimaryKey).map(t -> t.getLong(0)).asList().get();
assertEquals(ImmutableSet.of(0L, 1L, 2L, 3L), ImmutableSet.copyOf(primaryKeys));
if (shouldDeferFetch) {
assertLoadRecord(4, context);
} else {
assertLoadRecord(8, context);
}
}
}
Aggregations