use of com.apple.foundationdb.record.RecordCursorIterator 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.RecordCursorIterator in project fdb-record-layer by FoundationDB.
the class FDBFilterCoalescingQueryTest method overlappingFilters.
/**
* TODO The planner does not currently coalesce the overlapping filters (>= 3 and > 0).
* TODO: Planner does not currently coalesce overlapping filters (https://github.com/FoundationDB/fdb-record-layer/issues/1)
*/
@Test
public void overlappingFilters() throws Exception {
RecordMetaDataHook hook = metaData -> {
metaData.addIndex("MySimpleRecord", new Index("multi_index", "str_value_indexed", "num_value_3_indexed"));
};
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").equalsParameter("str"), Query.field("num_value_3_indexed").greaterThanOrEquals(3), Query.field("num_value_3_indexed").lessThanOrEquals(4), Query.field("num_value_3_indexed").greaterThan(0))).build();
// Index(multi_index [EQUALS $str, [GREATER_THAN_OR_EQUALS 3 && GREATER_THAN 0 && LESS_THAN_OR_EQUALS 4]])
RecordQueryPlan plan = planner.plan(query);
List<String> bounds = Arrays.asList("GREATER_THAN_OR_EQUALS 3", "LESS_THAN_OR_EQUALS 4", "GREATER_THAN 0");
Collection<List<String>> combinations = Collections2.permutations(bounds);
assertThat(plan, indexScan(allOf(indexName("multi_index"), bounds(anyOf(combinations.stream().map(ls -> hasTupleString("[EQUALS $str, [" + String.join(" && ", ls) + "]]")).collect(Collectors.toList()))))));
assertEquals(241654378, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-81379784, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1715241633, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
EvaluationContext boundContext = EvaluationContext.forBinding("str", "even");
int i = 0;
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = plan.execute(recordStore, boundContext).asIterator()) {
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
myrec.mergeFrom(rec.getRecord());
assertEquals("even", myrec.getStrValueIndexed());
assertThat(myrec.getNumValue3Indexed(), allOf(greaterThanOrEqualTo(3), lessThanOrEqualTo(4)));
i++;
}
}
assertEquals(20, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.RecordCursorIterator in project fdb-record-layer by FoundationDB.
the class FDBAndQueryToIntersectionTest method testComplexQuery1g.
/**
* Verify that the planner does not use aggregate indexes to implement ANDs as intersections.
*/
@Test
public void testComplexQuery1g() throws Exception {
RecordMetaDataHook hook = metaData -> {
metaData.removeIndex("MySimpleRecord$str_value_indexed");
metaData.addIndex("MySimpleRecord", new Index("grouped_index", concatenateFields("str_value_indexed", "num_value_2").group(1), IndexTypes.RANK));
};
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();
planner.setIndexScanPreference(QueryPlanner.IndexScanPreference.PREFER_SCAN);
// Index(MySimpleRecord$num_value_3_indexed [[3],[3]]) | str_value_indexed EQUALS even
RecordQueryPlan plan = planner.plan(query);
// Would get Intersection didn't have identical continuations if it did
assertThat("Should not use grouped index", plan, hasNoDescendant(indexScan("grouped_index")));
assertEquals(622816289, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1284025903, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1170038658, 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(10, context);
assertLoadRecord(20, context);
}
}
use of com.apple.foundationdb.record.RecordCursorIterator in project fdb-record-layer by FoundationDB.
the class FDBAndQueryToIntersectionTest method testComplexQueryAndWithMultipleChildren.
/**
* Verify that a complex query with an AND of more than two fields with compatibly ordered indexes generates an intersection plan.
*/
@ParameterizedTest
@BooleanSource
public void testComplexQueryAndWithMultipleChildren(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").equalsValue("odd"), Query.field("num_value_3_indexed").equalsValue(2), Query.field("num_value_2").equalsValue(1))).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
// Index(MySimpleRecord$str_value_indexed [[odd],[odd]]) ∩ Index(MySimpleRecord$num_value_3_indexed [[2],[2]]) ∩ Index(MySimpleRecord$num_value_2 [[1],[1]])
// Fetch(Covering(Index(MySimpleRecord$str_value_indexed [[odd],[odd]]) -> [rec_no: KEY[1], str_value_indexed: KEY[0]]) ∩ Covering(Index(MySimpleRecord$num_value_3_indexed [[2],[2]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]) ∩ Covering(Index(MySimpleRecord$num_value_2 [[1],[1]]) -> [num_value_2: KEY[0], rec_no: KEY[1]]))
RecordQueryPlan plan = planner.plan(query);
if (shouldDeferFetch) {
assertThat(plan, fetch(intersection(Arrays.asList(coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$str_value_indexed"), bounds(hasTupleString("[[odd],[odd]]"))))), coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), bounds(hasTupleString("[[2],[2]]"))))), coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$num_value_2"), bounds(hasTupleString("[[1],[1]]")))))), equalTo(field("rec_no")))));
assertEquals(946461036, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-625341018, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(116741660, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, intersection(Arrays.asList(indexScan(allOf(indexName("MySimpleRecord$str_value_indexed"), bounds(hasTupleString("[[odd],[odd]]")))), indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), bounds(hasTupleString("[[2],[2]]")))), indexScan(allOf(indexName("MySimpleRecord$num_value_2"), bounds(hasTupleString("[[1],[1]]"))))), equalTo(field("rec_no"))));
assertEquals(-478358039, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1448156435, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-2104728183, 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("odd", myrec.getStrValueIndexed());
assertEquals(2, myrec.getNumValue3Indexed());
assertEquals(1, myrec.getNumValue2());
i++;
}
}
assertEquals(4, i);
assertDiscardedAtMost(90, context);
if (shouldDeferFetch) {
assertLoadRecord(4, context);
}
}
}
use of com.apple.foundationdb.record.RecordCursorIterator in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreQueryTest method nullQuery.
@DualPlannerTest
void nullQuery() throws Exception {
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(1);
recBuilder.setStrValueIndexed("yes");
recBuilder.setNumValueUnique(1);
recordStore.saveRecord(recBuilder.build());
recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(2);
recBuilder.setStrValueIndexed("no");
recBuilder.setNumValueUnique(2);
recordStore.saveRecord(recBuilder.build());
recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(3);
recBuilder.setNumValueUnique(3);
recordStore.saveRecord(recBuilder.build());
commit(context);
}
{
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("str_value_indexed").notEquals("yes")).build();
RecordQueryPlan plan = planner.plan(query);
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
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());
assertTrue(myrec.getNumValueUnique() != 3);
i++;
}
}
assertEquals(1, i);
assertDiscardedAtMost(2, context);
}
}
{
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("str_value_indexed").notNull()).build();
RecordQueryPlan plan = planner.plan(query);
try (FDBRecordContext context = openContext()) {
clearStoreCounter(context);
openSimpleRecordStore(context);
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());
assertTrue(myrec.hasStrValueIndexed());
i++;
}
}
assertEquals(2, i);
assertDiscardedNone(context);
}
}
}
Aggregations