use of com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher in project fdb-record-layer by FoundationDB.
the class FDBInQueryTest method testMultipleInQueryIndex.
/**
* Verify that a query with multiple INs is translated into an index scan within multiple IN joins.
*/
@DualPlannerTest
void testMultipleInQueryIndex() throws Exception {
final RecordMetaDataHook recordMetaDataHook = metaData -> {
metaData.getRecordType("MyRecord").setPrimaryKey(field("str_value"));
metaData.addIndex("MyRecord", "ind", field("header").nest(field("rec_no"), field("path")));
};
setupRecordsWithHeader(recordMetaDataHook, (i, record) -> {
record.setStrValue("_" + i);
record.getHeaderBuilder().setRecNo(i % 5).setPath("String" + i % 50).setNum(i);
});
List<Long> longList = asList(1L, 4L);
List<String> stringList = asList("String6", "String25", "String1", "String34");
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("header").matches(Query.and(Query.field("rec_no").in(longList), Query.field("path").in(stringList)))).build();
// Index(ind [EQUALS $__in_rec_no__0, EQUALS $__in_path__1]) WHERE __in_path__1 IN [String6, String25, String1, String34] WHERE __in_rec_no__0 IN [1, 4]
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
final BindingMatcher<RecordQueryIndexPlan> indexPlanMatcher = indexPlan().where(indexName("ind")).and(scanComparisons(range("[EQUALS $__in_rec_no__0, EQUALS $__in_path__1]")));
assertMatchesExactly(plan, inValuesJoinPlan(inValuesJoinPlan(indexPlanMatcher).where(inValuesList(equalsObject(stringList)))).where(inValuesList(equalsObject(longList))).or(inValuesJoinPlan(inValuesJoinPlan(indexPlanMatcher).where(inValuesList(equalsObject(longList)))).where(inValuesList(equalsObject(stringList)))));
assertEquals(-1869764109, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1234840472, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(297055958, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertMatchesExactly(plan, fetchFromPartialRecordPlan(inValuesJoinPlan(inValuesJoinPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("ind")).and(scanComparisons(equalities(exactly(anyParameterComparison(), anyParameterComparison()))))))).where(inValuesList(equalsObject(longList)))).where(inValuesList(equalsObject(stringList)))));
assertEquals(-2124922292, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(2055315359, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1810804415, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
queryRecordsWithHeader(recordMetaDataHook, plan, cursor -> assertEquals(asList("_56", "_6", "_1", "_51", "_34", "_84"), cursor.map(TestRecordsWithHeaderProto.MyRecord.Builder::getStrValue).asList().get()), TestHelpers::assertDiscardedNone);
}
use of com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher in project fdb-record-layer by FoundationDB.
the class FDBCoveringIndexQueryTest method coveringWithHeader.
/**
* Verify that an index can be covering if the required fields are in the primary key.
*/
@DualPlannerTest
void coveringWithHeader() throws Exception {
RecordMetaDataHook hook = metaData -> {
metaData.getRecordType("MyRecord").setPrimaryKey(field("header").nest(concatenateFields("path", "rec_no")));
metaData.addIndex("MyRecord", "str_value");
};
try (FDBRecordContext context = openContext()) {
openRecordWithHeader(context, hook);
saveHeaderRecord(1, "a", 0, "lynx");
saveHeaderRecord(2, "a", 1, "bobcat");
saveHeaderRecord(3, "a", 2, "panther");
saveHeaderRecord(1, "b", 3, "jaguar");
saveHeaderRecord(2, "b", 4, "leopard");
saveHeaderRecord(3, "b", 5, "lion");
saveHeaderRecord(4, "b", 6, "tiger");
context.commit();
}
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("str_value").equalsValue("lion")).setRequiredResults(Collections.singletonList(field("header").nest("rec_no"))).build();
// Covering(Index(MyRecord$str_value [[lion],[lion]]) -> [str_value: KEY[0], header: [path: KEY[1], rec_no: KEY[2]]])
RecordQueryPlan plan = planner.plan(query);
BindingMatcher<? extends RecordQueryPlan> planMatcher = coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MyRecord$str_value")).and(scanComparisons(range("[[lion],[lion]]")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-629018945, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(177826375, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(344218219, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
try (FDBRecordContext context = openContext()) {
openRecordWithHeader(context, hook);
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
TestRecordsWithHeaderProto.MyRecord.Builder myrec = TestRecordsWithHeaderProto.MyRecord.newBuilder();
myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
assertEquals(3, myrec.getHeader().getRecNo());
}
}
context.commit();
assertDiscardedNone(context);
}
query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("str_value").startsWith("l")).setRequiredResults(Arrays.asList(field("header").nest(concatenateFields("path", "rec_no")), field("str_value"))).build();
// Covering(Index(MyRecord$str_value {[l],[l]}) -> [str_value: KEY[0], header: [path: KEY[1], rec_no: KEY[2]]])
plan = planner.plan(query);
planMatcher = coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MyRecord$str_value")).and(scanComparisons(range("{[l],[l]}")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-1471907004, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1581115138, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1123663700, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
try (FDBRecordContext context = openContext()) {
openRecordWithHeader(context, hook);
List<Pair<String, Long>> results = new ArrayList<>();
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
TestRecordsWithHeaderProto.MyRecord.Builder myrec = TestRecordsWithHeaderProto.MyRecord.newBuilder();
myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
assertThat(myrec.getStrValue(), startsWith("l"));
assertThat(myrec.getHeader().hasPath(), is(true));
assertThat(myrec.getHeader().hasRecNo(), is(true));
results.add(Pair.of(myrec.getHeader().getPath(), myrec.getHeader().getRecNo()));
}
}
assertEquals(Arrays.asList(Pair.of("b", 2L), Pair.of("b", 3L), Pair.of("a", 1L)), results);
context.commit();
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher in project fdb-record-layer by FoundationDB.
the class FDBCoveringIndexQueryTest method coveringMulti.
/**
* Verify that an index can be covering if more than one field is required and they are in the key.
*/
@DualPlannerTest
void coveringMulti() throws Exception {
RecordMetaDataHook hook = metaData -> {
metaData.removeIndex("MySimpleRecord$num_value_unique");
metaData.addIndex("MySimpleRecord", new Index("multi_index", "num_value_unique", "num_value_2"));
};
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_unique").greaterThan(990)).setSort(field("num_value_unique")).setRequiredResults(Arrays.asList(field("num_value_unique"), field("num_value_2"))).build();
// Covering(Index(multi_index ([990],>) -> [num_value_2: KEY[1], num_value_unique: KEY[0], rec_no: KEY[2]])
RecordQueryPlan plan = planner.plan(query);
final BindingMatcher<? extends RecordQueryPlan> planMatcher = coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("multi_index")).and(scanComparisons(range("([990],>")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(291429560, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1065678, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-80338730, 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.getNumValueUnique() > 990);
assertEquals(myrec.getNumValue2(), (999 - i) % 3);
i++;
}
}
assertEquals(10, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher in project fdb-record-layer by FoundationDB.
the class FDBCoveringIndexQueryTest method coveringWithHeaderValue.
/**
* Verify that an index can be covering for nested fields if the field is in the value of the index.
*/
@DualPlannerTest
void coveringWithHeaderValue() throws Exception {
RecordMetaDataHook hook = metaData -> {
metaData.getRecordType("MyRecord").setPrimaryKey(field("header").nest(field("rec_no")));
metaData.addIndex("MyRecord", new Index("MyRecord$str_value", field("str_value"), field("header").nest(field("path")), IndexTypes.VALUE, Collections.emptyMap()));
};
try (FDBRecordContext context = openContext()) {
openRecordWithHeader(context, hook);
}
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("str_value").equalsValue("lion")).setRequiredResults(Collections.singletonList(field("header").nest("path"))).build();
// Covering(Index(MyRecord$str_value [[lion],[lion]]) -> [str_value: KEY[0], header: [path: VALUE[0], rec_no: KEY[1]]])
RecordQueryPlan plan = planner.plan(query);
final BindingMatcher<? extends RecordQueryPlan> planMatcher = coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MyRecord$str_value")).and(scanComparisons(range("[[lion],[lion]]")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-629018945, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(177826375, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(344218219, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
use of com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher in project fdb-record-layer by FoundationDB.
the class FDBCoveringIndexQueryTest method coveringRedundant.
/**
* Verify that a covering index can have redundant duplicated fields.
*/
@DualPlannerTest
void coveringRedundant() throws Exception {
RecordMetaDataHook hook = metaData -> {
metaData.removeIndex("MySimpleRecord$num_value_unique");
metaData.addIndex("MySimpleRecord", new Index("multi_index", "num_value_2", "num_value_unique", "num_value_2"));
};
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_2").equalsValue(1)).setSort(field("num_value_unique")).setRequiredResults(Arrays.asList(field("num_value_unique"), field("num_value_2"))).build();
RecordQueryPlan plan = planner.plan(query);
final BindingMatcher<? extends RecordQueryPlan> planMatcher = coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("multi_index")).and(scanComparisons(range("[[1],[1]]")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(1372089780, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1440154798, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1095794309, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
Aggregations