use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQuery2.
/**
* Verify that queries with an OR of a mix of equality and inequality predicates on the same field are implemented
* using a union of indexes.
*/
@DualPlannerTest
@ParameterizedTest
@BooleanSource
void testOrQuery2(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").greaterThan(3))).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
// Fetch(Covering(Index(MySimpleRecord$num_value_3_indexed [[1],[1]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]) ∪[Field { 'num_value_3_indexed' None}, Field { 'rec_no' None}] Covering(Index(MySimpleRecord$num_value_3_indexed [[2],[2]]) -> [num_value_3_indexed: KEY[0], rec_no: KEY[1]]) ∪[Field { 'num_value_3_indexed' None}, Field { 'rec_no' None}] Covering(Index(MySimpleRecord$num_value_3_indexed ([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$num_value_3_indexed")).and(scanComparisons(range("[[1],[1]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[2],[2]]"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([3],>")))))).where(comparisonKey(concat(field("num_value_3_indexed"), primaryKey("MySimpleRecord")))));
assertMatchesExactly(plan, planMatcher);
assertEquals(504228282, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1520996708, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(2080970598, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
final BindingMatcher<? extends RecordQueryPlan> planMatcher = unionPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[1],[1]]"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[[2],[2]]"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([3],>")))).where(comparisonKey(concat(field("num_value_3_indexed"), primaryKey("MySimpleRecord"))));
assertMatchesExactly(plan, planMatcher);
assertEquals(1299166123, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-700473135, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-140499245, 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.getNumValue3Indexed() == 1 || myrec.getNumValue3Indexed() == 2 || myrec.getNumValue3Indexed() > 3);
i++;
}
}
assertEquals(20 + 20 + 20, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBOrQueryToUnionTest method testOrQuery5.
/**
* Verify that an OR of inequalities on different fields uses an unordered union, since there is no compatible ordering.
*/
@DualPlannerTest
@ParameterizedTest(name = "testOrQuery5 [removesDuplicates = {0}]")
@BooleanSource
void testOrQuery5(boolean removesDuplicates) throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.or(Query.field("str_value_indexed").lessThan("m"), Query.field("num_value_3_indexed").greaterThan(3))).setRemoveDuplicates(removesDuplicates).build();
// Unordered(Index(MySimpleRecord$str_value_indexed ([null],[m])) ∪ Index(MySimpleRecord$num_value_3_indexed ([3],>))
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof CascadesPlanner) {
BindingMatcher<? extends RecordQueryPlan> planMatcher = unorderedUnionPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("([null],[m])"))))), coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([3],>"))))));
if (removesDuplicates) {
planMatcher = fetchFromPartialRecordPlan(unorderedPrimaryKeyDistinctPlan(planMatcher));
} else {
planMatcher = fetchFromPartialRecordPlan(planMatcher);
}
assertMatchesExactly(plan, planMatcher);
assertEquals(removesDuplicates ? 1898767693 : 1898767686, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(removesDuplicates ? -583062018 : 212117636, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(removesDuplicates ? 1864525478 : -1635262164, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
BindingMatcher<? extends RecordQueryPlan> planMatcher = unorderedUnionPlan(indexPlan().where(indexName("MySimpleRecord$str_value_indexed")).and(scanComparisons(range("([null],[m])"))), indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("([3],>"))));
if (removesDuplicates) {
planMatcher = unorderedPrimaryKeyDistinctPlan(planMatcher);
}
assertMatchesExactly(plan, planMatcher);
assertEquals(removesDuplicates ? -1569447744 : -1569447745, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(removesDuplicates ? 1558364455 : -1941423187, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(removesDuplicates ? -289015345 : 506164309, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
try (FDBRecordContext context = openContext()) {
Objects.requireNonNull(context.getTimer()).reset();
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().compareTo("m") < 0 || myrec.getNumValue3Indexed() > 3);
i++;
}
}
if (removesDuplicates) {
assertEquals(50 + 10, i);
assertDiscardedAtMost(10, context);
} else {
assertEquals(70, i);
assertDiscardedNone(context);
}
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBQueryCompatibilityTest method testParameterBindings.
@DualPlannerTest
public void testParameterBindings() throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
BoundRecordQuery boundQuery = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").equalsParameter("p1"), Query.field("str_value_indexed").equalsParameter("p2"), Query.field("num_value_3_indexed").equalsParameter("p3"), Query.field("num_value_2").equalsValue(0))).buildAndBind(recordStore, Bindings.newBuilder().set("p1", "whatever").set("p2", "whatever").set("p3", "-10").build());
final RecordQueryPlan plan = planner.plan(boundQuery.getRecordQuery());
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
final Bindings compatibleBindings = Bindings.newBuilder().set("p1", "even").set("p2", "even").set("p3", 3).build();
assertTrue(boundQuery.isCompatible(recordStore, compatibleBindings));
final Bindings incompatibleBindings = Bindings.newBuilder().set("p1", "even").set("p2", "odd").set("p3", 3).build();
assertFalse(boundQuery.isCompatible(recordStore, incompatibleBindings));
int i = 0;
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = plan.execute(recordStore, EvaluationContext.forBindings(compatibleBindings)).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());
assertEquals(0, (myrec.getNumValue2() % 3));
assertEquals(3, (myrec.getNumValue3Indexed() % 5));
i++;
}
}
assertEquals(3, i);
TestHelpers.assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexScanPreferenceTest method noIndexes.
@Test
public void noIndexes() throws Exception {
try (FDBRecordContext context = openContext()) {
openAnyRecordStore(TestNoIndexesProto.getDescriptor(), context);
}
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").build();
for (QueryPlanner.IndexScanPreference indexScanPreference : QueryPlanner.IndexScanPreference.values()) {
planner.setIndexScanPreference(indexScanPreference);
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, scan(unbounded()));
}
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class TextIndexTest method queryMapDocumentsWithIndex.
@Nonnull
private List<Long> queryMapDocumentsWithIndex(@Nonnull String key, @Nonnull QueryComponent textFilter, int planHash, boolean isCoveringIndexExpected) throws InterruptedException, ExecutionException {
if (!(textFilter instanceof ComponentWithComparison)) {
throw new RecordCoreArgumentException("filter without comparison provided as text filter");
}
final QueryComponent filter = Query.field("entry").oneOfThem().matches(Query.and(Query.field("key").equalsValue(key), textFilter));
Matcher<RecordQueryPlan> indexMatcher = textIndexScan(allOf(indexName(MAP_ON_VALUE_INDEX.getName()), groupingBounds(allOf(notNullValue(), hasTupleString("[[" + key + "],[" + key + "]]"))), textComparison(equalTo(((ComponentWithComparison) textFilter).getComparison()))));
if (isCoveringIndexExpected) {
indexMatcher = coveringIndexScan(indexMatcher);
}
final Matcher<RecordQueryPlan> planMatcher = descendant(indexMatcher);
return queryDocuments(Collections.singletonList(MAP_DOC), Collections.singletonList(field("doc_id")), filter, planHash, planMatcher).map(t -> t.getLong(0)).asList().get();
}
Aggregations