use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBCollateQueryTest method coveringIndex.
@Test
public void coveringIndex() throws Exception {
// Note how the name field needs to be repeated in the value because it can't be recovered from an index
// entry after transformation to a collation key.
final KeyExpression collateKey = function(collateFunctionName, concat(NAME_FIELD, value("da_DK")));
final KeyExpression indexKey = keyWithValue(concat(collateKey, NAME_FIELD), 1);
final RecordMetaDataHook hook = md -> {
md.removeIndex("MySimpleRecord$str_value_indexed");
md.addIndex("MySimpleRecord", "collated_name", indexKey);
};
loadNames(hook);
final RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.keyExpression(collateKey).lessThan("B")).setRequiredResults(Arrays.asList(NAME_FIELD)).build();
final List<String> actual = queryNames(query, hook);
final List<String> expected = Arrays.asList("Ampère");
assertEquals(expected, actual);
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, coveringIndexScan(indexScan("collated_name")));
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBCollateQueryTest method compareParameter.
@Test
public void compareParameter() throws Exception {
final KeyExpression key = function(collateFunctionName, concat(NAME_FIELD, value("de_DE")));
final RecordMetaDataHook hook = md -> {
md.removeIndex("MySimpleRecord$str_value_indexed");
md.addIndex("MySimpleRecord", "collated_name", key);
};
loadNames(hook);
final RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.keyExpression(key).equalsParameter("name")).setRequiredResults(Arrays.asList(NAME_FIELD)).build();
final List<String> actual = queryNames(query, hook, "name", "gauss");
final List<String> expected = Arrays.asList("Gauß");
assertEquals(expected, actual);
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("collated_name"), bounds(hasTupleString(String.format("[EQUALS %s($name)]", collateFunctionName))))));
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBCoveringIndexQueryTest method coveringOff.
/**
* Verify that a covering index is used when possible.
*/
@SuppressWarnings("unchecked")
@DualPlannerTest
void coveringOff() throws Exception {
complexQuerySetup(null);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_unique").greaterThan(990)).setSort(field("num_value_unique")).setRequiredResults(Collections.singletonList(field("num_value_unique"))).build();
// Covering(Index(MySimpleRecord$num_value_unique ([990],>) -> [num_value_unique: KEY[0], rec_no: KEY[1]])
planner.setConfiguration(planner.getConfiguration().asBuilder().setDisabledTransformationRuleNames(ImmutableSet.of("PushFilterThroughFetchRule", "PushDistinctThroughFetchRule", "PushSetOperationThroughFetchRule", "MergeProjectionAndFetchRule"), PlannerRuleSet.DEFAULT).build());
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_unique")).and(scanComparisons(range("([990],>")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-158312359, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1293351441, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1374755849, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = indexPlan().where(indexName("MySimpleRecord$num_value_unique")).and(scanComparisons(range("([990],>")));
assertMatchesExactly(plan, planMatcher);
assertEquals(-158312359, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(594363437, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(512959029, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
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(Objects.requireNonNull(rec).getRecord());
assertTrue(myrec.getNumValueUnique() > 990);
i++;
}
}
assertEquals(10, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBCoveringIndexQueryTest method coveringSimpleInsufficient.
/**
* Verify that a covering index is not used when it does not include enough fields; a regular index is used instead.
*/
@DualPlannerTest
void coveringSimpleInsufficient() throws Exception {
complexQuerySetup(null);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_unique").greaterThan(990)).setSort(field("num_value_unique"), true).setRequiredResults(Arrays.asList(field("num_value_unique"), field("num_value_3_indexed"))).build();
// Index(MySimpleRecord$num_value_unique ([990],> REVERSE)
RecordQueryPlan plan = planner.plan(query);
assertTrue(plan.isReverse());
if (planner instanceof RecordQueryPlanner) {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = indexPlan().where(indexName("MySimpleRecord$num_value_unique")).and(scanComparisons(range("([990],>")));
assertMatchesExactly(plan, planMatcher);
assertEquals(-158312358, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(594363257, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(512958849, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = indexPlan().where(indexName("MySimpleRecord$num_value_unique")).and(scanComparisons(range("([990],>")));
assertMatchesExactly(plan, planMatcher);
assertEquals(-158312358, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(594363251, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(512958843, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBCoveringIndexQueryTest method coveringWithAdditionalNestedFilter.
/**
* Verify that an extra covering filter can use a nested field.
*/
@DualPlannerTest
void coveringWithAdditionalNestedFilter() {
try (FDBRecordContext context = openContext()) {
RecordMetaDataBuilder builder = RecordMetaData.newBuilder().setRecords(TestRecordsWithHeaderProto.getDescriptor());
builder.getRecordType("MyRecord").setPrimaryKey(field("header").nest(field("rec_no")));
builder.addIndex("MyRecord", "multi", concat(field("str_value"), field("header").nest(concatenateFields("path", "num"))));
RecordMetaData metaData = builder.getRecordMetaData();
createOrOpenRecordStore(context, metaData);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.and(Query.field("str_value").equalsValue("abc"), Query.field("header").matches(Query.field("num").equalsValue(1)))).build();
// Fetch(Covering(Index(multi [[abc],[abc]]) -> [str_value: KEY[0], header: [num: KEY[2], path: KEY[1], rec_no: KEY[3]]]) | header/{num EQUALS 1})
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = fetchFromPartialRecordPlan(filterPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("multi")).and(scanComparisons(range("[[abc],[abc]]")))))).where(queryComponents(exactly(equalsObject(Query.field("header").matches(Query.field("num").equalsValue(1)))))));
assertMatchesExactly(plan, planMatcher);
assertEquals(-1536005152, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1350035332, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1843652335, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = fetchFromPartialRecordPlan(predicatesFilterPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("multi")).and(scanComparisons(range("[[abc],[abc]]")))))).where(predicates(only(valuePredicate(fieldValue("header.num"), new Comparisons.SimpleComparison(Comparisons.Type.EQUALS, 1))))));
assertMatchesExactly(plan, planMatcher);
assertEquals(1623341655, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(2019556616, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1174131051, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
}
}
Aggregations