use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBInQueryTest method testInQueryIndex.
/**
* Verify that an IN with an index is implemented as an index scan, with an IN join.
*/
@DualPlannerTest
void testInQueryIndex() throws Exception {
complexQuerySetup(NO_HOOK);
List<Integer> ls = asList(1, 2, 4);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_3_indexed").in(ls)).setSort(field("num_value_3_indexed")).build();
planner.setConfiguration(InAsOrUnionMode.AS_UNION.configure(planner.getConfiguration().asBuilder()).build());
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
// Index(MySimpleRecord$num_value_3_indexed [EQUALS $__in_num_value_3_indexed__0]) WHERE __in_num_value_3_indexed__0 IN [1, 2, 4]
assertMatchesExactly(plan, inValuesJoinPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[EQUALS $__in_num_value_3_indexed__0]")))).where(inValuesList(equalsObject(ls))));
assertEquals(-2004060309, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(571226247, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(571195399, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertMatchesExactly(plan, fetchFromPartialRecordPlan(inValuesJoinPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(equalities(only(anyParameterComparison()))))))).where(inValuesList(equalsObject(ls)))));
assertEquals(-2068499040, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-992959779, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1998042418, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
assertEquals(60, querySimpleRecordStore(NO_HOOK, plan, EvaluationContext::empty, record -> assertThat(record.getNumValue3Indexed(), anyOf(is(1), is(2), is(4))), TestHelpers::assertDiscardedNone));
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan 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.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBInQueryTest method testInQueryParameter.
/**
* Verify that an IN (with parameter) with an index is implemented as an index scan, with an IN join.
*/
@DualPlannerTest
void testInQueryParameter() throws Exception {
complexQuerySetup(NO_HOOK);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_3_indexed").in("valueThrees")).build();
planner.setConfiguration(InAsOrUnionMode.AS_UNION.configure(planner.getConfiguration().asBuilder()).build());
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
// Index(MySimpleRecord$num_value_3_indexed [EQUALS $__in_num_value_3_indexed__0]) WHERE __in_num_value_3_indexed__0 IN $valueThrees
assertMatchesExactly(plan, inParameterJoinPlan(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(range("[EQUALS $__in_num_value_3_indexed__0]")))).where(RecordQueryPlanMatchers.inParameter(equalsObject("valueThrees"))));
assertEquals(883815022, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(514739864, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(514739864, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertMatchesExactly(plan, fetchFromPartialRecordPlan(inParameterJoinPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("MySimpleRecord$num_value_3_indexed")).and(scanComparisons(equalities(only(anyParameterComparison()))))))).where(RecordQueryPlanMatchers.inParameter(equalsObject("valueThrees")))));
assertEquals(1152354842, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1759971309, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1759971309, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
int count = querySimpleRecordStore(NO_HOOK, plan, () -> EvaluationContext.forBinding("valueThrees", asList(1, 3, 4)), myrec -> assertThat(myrec.getNumValue3Indexed(), anyOf(is(1), is(3), is(4))), TestHelpers::assertDiscardedNone);
assertEquals(60, count);
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBInQueryTest method testInQueryNoIndex.
/**
* Verify that an IN without an index is implemented as a filter on a scan, as opposed to a loop of a filter on a scan.
*/
@DualPlannerTest
void testInQueryNoIndex() throws Exception {
complexQuerySetup(NO_HOOK);
final QueryComponent filter = Query.field("num_value_2").in(asList(0, 2));
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(filter).build();
// Scan(<,>) | [MySimpleRecord] | num_value_2 IN [0, 2]
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
assertMatchesExactly(plan, filterPlan(descendantPlans(scanPlan().where(scanComparisons(unbounded())))).where(queryComponents(exactly(equalsObject(filter)))));
assertEquals(-1139367278, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1907300063, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1694772440, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertMatchesExactly(plan, predicatesFilterPlan(descendantPlans(scanPlan().where(scanComparisons(unbounded())))).where(predicates(valuePredicate(fieldValue("num_value_2"), new Comparisons.ListComparison(Comparisons.Type.IN, ImmutableList.of(0, 2))))));
assertEquals(997592219, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1107686929, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-895159306, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
assertEquals(67, querySimpleRecordStore(NO_HOOK, plan, EvaluationContext::empty, record -> assertThat(record.getNumValue2(), anyOf(is(0), is(2))), context -> assertDiscardedAtMost(33, context)));
}
use of com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreNullQueryTest method testTupleFields.
@Test
public void testTupleFields() throws Exception {
final UUID nullId = UUID.randomUUID();
final UUID emptyId = UUID.randomUUID();
final UUID defaultId = UUID.randomUUID();
final UUID otherId = UUID.randomUUID();
final TestRecordsTupleFieldsProto.MyFieldsRecord nullRecord = TestRecordsTupleFieldsProto.MyFieldsRecord.newBuilder().setUuid(TupleFieldsHelper.toProto(nullId)).build();
final TestRecordsTupleFieldsProto.MyFieldsRecord emptyRecord = TestRecordsTupleFieldsProto.MyFieldsRecord.newBuilder().setUuid(TupleFieldsHelper.toProto(emptyId)).setFdouble(TupleFieldsProto.NullableDouble.getDefaultInstance()).setFfloat(TupleFieldsProto.NullableFloat.getDefaultInstance()).setFint32(TupleFieldsProto.NullableInt32.getDefaultInstance()).setFint64(TupleFieldsProto.NullableInt64.getDefaultInstance()).setFbool(TupleFieldsProto.NullableBool.getDefaultInstance()).setFstring(TupleFieldsProto.NullableString.getDefaultInstance()).setFbytes(TupleFieldsProto.NullableBytes.getDefaultInstance()).build();
final TestRecordsTupleFieldsProto.MyFieldsRecord defaultRecord = TestRecordsTupleFieldsProto.MyFieldsRecord.newBuilder().setUuid(TupleFieldsHelper.toProto(defaultId)).setFdouble(TupleFieldsHelper.toProto(0.0)).setFfloat(TupleFieldsHelper.toProto(0.0f)).setFint32(TupleFieldsHelper.toProto(0)).setFint64(TupleFieldsHelper.toProto(0L)).setFbool(TupleFieldsHelper.toProto(false)).setFstring(TupleFieldsHelper.toProto("")).setFbytes(TupleFieldsHelper.toProto(ByteString.EMPTY)).build();
final TestRecordsTupleFieldsProto.MyFieldsRecord otherRecord = TestRecordsTupleFieldsProto.MyFieldsRecord.newBuilder().setUuid(TupleFieldsHelper.toProto(otherId)).setFdouble(TupleFieldsHelper.toProto(1.0)).setFfloat(TupleFieldsHelper.toProto(1.0f)).setFint32(TupleFieldsHelper.toProto(1)).setFint64(TupleFieldsHelper.toProto(1L)).setFbool(TupleFieldsHelper.toProto(true)).setFstring(TupleFieldsHelper.toProto(" ")).setFbytes(TupleFieldsHelper.toProto(ByteString.copyFrom(" ", "UTF-8"))).build();
try (FDBRecordContext context = openContext()) {
createOrOpenRecordStore(context, tupleFieldsMetaData());
recordStore.saveRecord(nullRecord);
recordStore.saveRecord(emptyRecord);
recordStore.saveRecord(defaultRecord);
recordStore.saveRecord(otherRecord);
context.commit();
}
try (FDBRecordContext context = openContext()) {
createOrOpenRecordStore(context, tupleFieldsMetaData());
assertEquals(nullId, fieldsRecordId(recordStore.loadRecord(Tuple.from(nullId))));
assertEquals(otherId, fieldsRecordId(recordStore.loadRecord(Tuple.from(otherId))));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fdouble").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("ffloat").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fint32").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fint64").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fbool").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fstring").isNull()));
assertEquals(Collections.singleton(nullId), fieldsRecordQuery(context, Query.field("fbytes").isNull()));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fdouble").equalsValue(0.0)));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("ffloat").equalsValue(0.0f)));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fint32").equalsValue(0)));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fint64").equalsValue(0L)));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fbool").equalsValue(false)));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fstring").equalsValue("")));
assertEquals(ImmutableSet.of(emptyId, defaultId), fieldsRecordQuery(context, Query.field("fbytes").equalsValue(ByteString.EMPTY)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fdouble").equalsValue(1.0)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("ffloat").equalsValue(1.0f)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fint32").equalsValue(1)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fint64").equalsValue(1L)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fbool").equalsValue(true)));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fstring").equalsValue(" ")));
assertEquals(Collections.singleton(otherId), fieldsRecordQuery(context, Query.field("fbytes").equalsValue(ByteString.copyFrom(" ", "UTF-8"))));
{
final RecordQueryPlan coveringPlan = planner.plan(RecordQuery.newBuilder().setRecordType("MyFieldsRecord").setFilter(Query.field("fint64").greaterThan(0L)).setRequiredResults(Stream.of("uuid", "fint64").map(Key.Expressions::field).collect(Collectors.toList())).build());
assertThat(coveringPlan, PlanMatchers.coveringIndexScan(PlanMatchers.indexScan(PlanMatchers.indexName("MyFieldsRecord$fint64"))));
final List<Pair<UUID, Long>> results = recordStore.executeQuery(coveringPlan).map(rec -> {
final TestRecordsTupleFieldsProto.MyFieldsRecord myrec = TestRecordsTupleFieldsProto.MyFieldsRecord.newBuilder().mergeFrom(rec.getRecord()).build();
return Pair.of(TupleFieldsHelper.fromProto(myrec.getUuid()), TupleFieldsHelper.fromProto(myrec.getFint64()));
}).asList().join();
assertEquals(Collections.singletonList(Pair.of(otherId, 1L)), results);
}
context.commit();
}
}
Aggregations