use of com.apple.foundationdb.record.TestHelpers in project fdb-record-layer by FoundationDB.
the class FDBInQueryTest method testOneOfThemInParameter.
/**
* Verify that one-of-them queries work with IN (with binding).
*/
@Test
void testOneOfThemInParameter() throws Exception {
RecordMetaDataHook recordMetaDataHook = metadata -> metadata.addIndex("MySimpleRecord", "ind", field("repeater", FanType.FanOut));
setupSimpleRecordStore(recordMetaDataHook, (i, builder) -> builder.setRecNo(i).addAllRepeater(Arrays.asList(10 + i % 4, 20 + i % 4)));
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("repeater").oneOfThem().in("values")).build();
// Index(ind [EQUALS $__in_repeater__0]) | UnorderedPrimaryKeyDistinct() WHERE __in_repeater__0 IN $values
RecordQueryPlan plan = planner.plan(query);
assertMatchesExactly(plan, inParameterJoinPlan(unorderedPrimaryKeyDistinctPlan(indexPlan().where(indexName("ind")).and(scanComparisons(range("[EQUALS $__in_repeater__0]"))))).where(RecordQueryPlanMatchers.inParameter(equalsObject("values"))));
assertEquals(-320448635, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(604626720, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(604626720, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(50, querySimpleRecordStore(recordMetaDataHook, plan, () -> EvaluationContext.forBinding("values", Arrays.asList(13L, 11L)), record -> assertThat(record.getRecNo() % 4, anyOf(is(3L), is(1L))), TestHelpers::assertDiscardedNone));
}
use of com.apple.foundationdb.record.TestHelpers in project fdb-record-layer by FoundationDB.
the class FDBNestedFieldQueryTest method nested.
/**
* Verify that nested field comparisons with fanout can scan indexes.
*/
@DualPlannerTest
public void nested() throws Exception {
try (FDBRecordContext context = openContext()) {
openNestedRecordStore(context);
TestRecords4Proto.RestaurantReviewer.Builder reviewerBuilder = TestRecords4Proto.RestaurantReviewer.newBuilder();
reviewerBuilder.setId(1);
reviewerBuilder.setName("Lemuel");
recordStore.saveRecord(reviewerBuilder.build());
reviewerBuilder.setId(2);
reviewerBuilder.setName("Gulliver");
recordStore.saveRecord(reviewerBuilder.build());
TestRecords4Proto.RestaurantRecord.Builder recBuilder = TestRecords4Proto.RestaurantRecord.newBuilder();
recBuilder.setRestNo(101);
recBuilder.setName("The Emperor's Three Tables");
TestRecords4Proto.RestaurantReview.Builder reviewBuilder = recBuilder.addReviewsBuilder();
reviewBuilder.setReviewer(1);
reviewBuilder.setRating(10);
reviewBuilder = recBuilder.addReviewsBuilder();
reviewBuilder.setReviewer(2);
reviewBuilder.setRating(3);
TestRecords4Proto.RestaurantTag.Builder tagBuilder = recBuilder.addTagsBuilder();
tagBuilder.setValue("Lilliput");
tagBuilder.setWeight(5);
recordStore.saveRecord(recBuilder.build());
recBuilder = TestRecords4Proto.RestaurantRecord.newBuilder();
recBuilder.setRestNo(102);
recBuilder.setName("Small Fry's Fried Victuals");
reviewBuilder = recBuilder.addReviewsBuilder();
reviewBuilder.setReviewer(1);
reviewBuilder.setRating(5);
reviewBuilder = recBuilder.addReviewsBuilder();
reviewBuilder.setReviewer(2);
reviewBuilder.setRating(5);
tagBuilder = recBuilder.addTagsBuilder();
tagBuilder.setValue("Lilliput");
tagBuilder.setWeight(1);
recordStore.saveRecord(recBuilder.build());
commit(context);
}
// TODO this was originally:
// QueryExpression.field("reviews").matches(QueryExpression.field("rating").greaterThan(5)),
// which should have failed validate
RecordQuery query = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(Query.field("reviews").oneOfThem().matches(Query.field("rating").greaterThan(5))).build();
// Index(review_rating ([5],>) | UnorderedPrimaryKeyDistinct()
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("([5],>"))))));
assertEquals(1378568952, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-2085209333, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(2129300140, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, fetch(primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("([5],>"))))))));
assertEquals(1060048085, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1589243362, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1669701185, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
assertEquals(Arrays.asList(101L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
query = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(Query.field("tags").oneOfThem().matches(Query.and(Query.field("value").equalsValue("Lilliput"), Query.field("weight").greaterThanOrEquals(5)))).build();
// Index(tag [[Lilliput, 5],[Lilliput]]) | UnorderedPrimaryKeyDistinct()
plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("tag"), bounds(hasTupleString("[[Lilliput, 5],[Lilliput]]"))))));
assertEquals(-1197819382, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1570485504, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1584619812, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, fetch(primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("tag"), bounds(hasTupleString("[[Lilliput, 5],[Lilliput]]"))))))));
assertEquals(205198931, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(2066451475, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(2080585783, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
assertEquals(Collections.singletonList(101L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
QueryComponent reviewFilter = Query.field("reviews").oneOfThem().matches(Query.and(Query.field("rating").equalsValue(5), Query.field("reviewer").equalsValue(1L)));
query = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(reviewFilter).build();
plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
assertThat(plan, filter(reviewFilter, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("[[5],[5]]")))))));
assertEquals(1252155441, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-2056078191, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1471222808, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Collections.singletonList(102L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
} else {
assertThat(plan, filter(reviewFilter, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), bounds(hasTupleString("[[5],[5]]")))))));
assertEquals(1252155441, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1947915247, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1762196666, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Collections.singletonList(102L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, context -> TestHelpers.assertDiscardedAtMost(3, context)));
}
}
use of com.apple.foundationdb.record.TestHelpers in project fdb-record-layer by FoundationDB.
the class FDBNestedFieldQueryTest method nestedWithAndConcat.
/**
* Verify that AND clauses in queries on nested record stores with concatenated repeats are implemented properly.
*/
@DualPlannerTest
public void nestedWithAndConcat() throws Exception {
final RecordMetaDataHook hook = metaData -> {
metaData.removeIndex("stats$school");
metaData.addIndex("RestaurantReviewer", "stats$school", field("stats").nest(concatenateFields("school_name", "start_date")));
metaData.getIndex("stats$school").setSubspaceKey("stats$school_2");
};
nestedWithAndSetup(hook);
// Same query expressed two ways.
RecordQuery query1 = RecordQuery.newBuilder().setRecordType("RestaurantReviewer").setFilter(Query.field("stats").matches(Query.and(Query.field("start_date").greaterThan(0L), Query.field("school_name").equalsValue("Human University")))).build();
// Index(stats$school ([Human University, 0],[Human University]])
RecordQueryPlan plan1 = planner.plan(query1);
assertThat(plan1, indexScan(allOf(indexName("stats$school"), bounds(hasTupleString("([Human University, 0],[Human University]]")))));
assertEquals(-1854785243, plan1.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(245473758, plan1.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1563763213, plan1.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Collections.singletonList(2L), fetchResultValues(plan1, TestRecords4Proto.RestaurantReviewer.ID_FIELD_NUMBER, ctx -> openNestedRecordStore(ctx, hook), TestHelpers::assertDiscardedNone));
RecordQuery query2 = RecordQuery.newBuilder().setRecordType("RestaurantReviewer").setFilter(Query.and(Query.field("stats").matches(Query.field("start_date").greaterThan(0L)), Query.field("stats").matches(Query.field("school_name").equalsValue("Human University")))).build();
// Index(stats$school ([Human University, 0],[Human University]])
RecordQueryPlan plan2 = planner.plan(query2);
assertThat(plan2, indexScan(allOf(indexName("stats$school"), bounds(hasTupleString("([Human University, 0],[Human University]]")))));
assertEquals(-1854785243, plan2.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(245473758, plan2.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1563763213, plan2.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Collections.singletonList(2L), fetchResultValues(plan2, TestRecords4Proto.RestaurantReviewer.ID_FIELD_NUMBER, ctx -> openNestedRecordStore(ctx, hook), TestHelpers::assertDiscardedNone));
}
use of com.apple.foundationdb.record.TestHelpers in project fdb-record-layer by FoundationDB.
the class FDBRepeatedFieldQueryTest method sortRepeated.
/**
* Verify that sorts on repeated fields are implemented with fanout indexes.
* Verify that they include distinctness filters and value filters where necessary.
*/
@ParameterizedTest
@BooleanSource
public void sortRepeated(final boolean shouldOptimizeForIndexFilters) throws Exception {
try (FDBRecordContext context = openContext()) {
openNestedRecordStore(context);
TestRecords4Proto.RestaurantReviewer reviewer = TestRecords4Proto.RestaurantReviewer.newBuilder().setId(1L).setName("Javert").setEmail("inspecteur@policier.fr").setStats(TestRecords4Proto.ReviewerStats.newBuilder().setStartDate(100L).setHometown("Toulon")).build();
recordStore.saveRecord(reviewer);
reviewer = TestRecords4Proto.RestaurantReviewer.newBuilder().setId(2L).setName("M. le Maire").setStats(TestRecords4Proto.ReviewerStats.newBuilder().setStartDate(120L).setHometown("Montreuil-sur-mer")).build();
recordStore.saveRecord(reviewer);
TestRecords4Proto.RestaurantRecord restaurant = TestRecords4Proto.RestaurantRecord.newBuilder().setRestNo(1000L).setName("Chez Thénardier").addReviews(TestRecords4Proto.RestaurantReview.newBuilder().setReviewer(1L).setRating(100)).addReviews(TestRecords4Proto.RestaurantReview.newBuilder().setReviewer(2L).setRating(0)).addTags(TestRecords4Proto.RestaurantTag.newBuilder().setValue("l'atmosphère").setWeight(10)).addTags(TestRecords4Proto.RestaurantTag.newBuilder().setValue("les aliments").setWeight(70)).addCustomer("jean").addCustomer("fantine").addCustomer("cosette").addCustomer("éponine").build();
recordStore.saveRecord(restaurant);
restaurant = TestRecords4Proto.RestaurantRecord.newBuilder().setRestNo(1001L).setName("ABC").addReviews(TestRecords4Proto.RestaurantReview.newBuilder().setReviewer(1L).setRating(34)).addReviews(TestRecords4Proto.RestaurantReview.newBuilder().setReviewer(2L).setRating(110)).addTags(TestRecords4Proto.RestaurantTag.newBuilder().setValue("l'atmosphère").setWeight(40)).addTags(TestRecords4Proto.RestaurantTag.newBuilder().setValue("les aliments").setWeight(20)).addCustomer("gavroche").addCustomer("enjolras").addCustomer("éponine").build();
recordStore.saveRecord(restaurant);
commit(context);
}
{
RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setSort(field("reviews", FanType.FanOut).nest("rating"));
RecordQuery query = builder.setRemoveDuplicates(false).build();
// Index(review_rating <,>)
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("review_rating"), unbounded())));
assertEquals(406416366, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1919610161, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1919610161, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(1000L, 1001L, 1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
query = builder.setRemoveDuplicates(true).build();
// Index(review_rating <,>) | UnorderedPrimaryKeyDistinct()
plan = planner.plan(query);
assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), unbounded()))));
assertEquals(406416367, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1124430507, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1124430507, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, context -> assertDiscardedAtMost(2, context)));
}
{
RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setSort(field("reviews", FanType.FanOut).nest("rating"), true);
RecordQuery query = builder.setRemoveDuplicates(false).build();
// Index(review_rating <,> REVERSE)
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("review_rating"), unbounded())));
assertTrue(plan.isReverse());
assertEquals(406416367, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1919609975, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1919609975, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(1001L, 1000L, 1001L, 1000L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
query = builder.setRemoveDuplicates(true).build();
// Index(review_rating <,> REVERSE) | UnorderedPrimaryKeyDistinct()
plan = planner.plan(query);
assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), unbounded()))));
assertTrue(plan.isReverse());
assertEquals(406416368, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1124430321, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1124430321, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(1001L, 1000L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, context -> assertDiscardedAtMost(2, context)));
}
{
RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setSort(field("reviews", FanType.FanOut).nest("rating")).setFilter(Query.field("name").greaterThan("A"));
RecordQuery query = builder.setRemoveDuplicates(false).build();
// Index(review_rating <,>) | name GREATER_THAN A
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, filter(query.getFilter(), indexScan(allOf(indexName("review_rating"), unbounded()))));
assertEquals(1381942688, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-2104094855, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1943284962, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(1000L, 1001L, 1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
query = builder.setRemoveDuplicates(true).build();
// Index(review_rating <,>) | UnorderedPrimaryKeyDistinct() | name GREATER_THAN A
plan = planner.plan(query);
assertThat(plan, filter(query.getFilter(), primaryKeyDistinct(indexScan(allOf(indexName("review_rating"), unbounded())))));
assertEquals(1381942689, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-984860353, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-824050460, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, context -> assertDiscardedAtMost(2, context)));
}
{
setOptimizeForIndexFilters(shouldOptimizeForIndexFilters);
RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setSort(field("customer", FanType.FanOut)).setFilter(Query.field("name").greaterThan("A"));
RecordQuery query = builder.setRemoveDuplicates(false).build();
// Index(customers <,>) | name GREATER_THAN A
// Fetch(Covering(Index(customers-name <,>) -> [name: KEY[1], rest_no: KEY[2]]) | name GREATER_THAN A)
RecordQueryPlan plan = planner.plan(query);
if (shouldOptimizeForIndexFilters) {
assertThat(plan, fetch(filter(query.getFilter(), coveringIndexScan(indexScan(allOf(indexName("customers-name"), unbounded()))))));
assertEquals(-505715770, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-378020523, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-217210630, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(1000L, 1001L, 1000L, 1001L, 1000L, 1001L, 1000L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
} else {
assertThat(plan, filter(query.getFilter(), indexScan(allOf(indexName("customers"), unbounded()))));
assertEquals(1833106833, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(201074216, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(361884109, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(1000L, 1001L, 1000L, 1001L, 1000L, 1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
}
setOptimizeForIndexFilters(shouldOptimizeForIndexFilters);
setDeferFetchAfterUnionAndIntersection(true);
query = builder.setRemoveDuplicates(true).build();
// Fetch(Covering(Index(customers <,>) -> [rest_no: KEY[1]]) | UnorderedPrimaryKeyDistinct()) | name GREATER_THAN A
// Fetch(Covering(Index(customers-name <,>) -> [name: KEY[1], rest_no: KEY[2]]) | UnorderedPrimaryKeyDistinct() | name GREATER_THAN A)
plan = planner.plan(query);
if (shouldOptimizeForIndexFilters) {
assertThat(plan, fetch(filter(query.getFilter(), primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("customers-name"), unbounded())))))));
assertEquals(-505715763, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(741213979, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(902023872, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, filter(query.getFilter(), fetch(primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("customers"), unbounded())))))));
assertEquals(-1611344673, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-484615365, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-323805472, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
assertEquals(Arrays.asList(1000L, 1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, context -> assertDiscardedAtMost(5, context)));
}
{
RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(Query.field("customer").oneOfThem().equalsValue("éponine")).setSort(field("name"));
RecordQuery query = builder.setRemoveDuplicates(false).build();
// Index(customers-name [[éponine],[éponine]])
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("customers-name"), bounds(hasTupleString("[[éponine],[éponine]]")))));
assertEquals(-574773820, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1450272556, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(173295350, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(1001L, 1000L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
query = builder.setRemoveDuplicates(true).build();
// Index(customers-name [[éponine],[éponine]]) | UnorderedPrimaryKeyDistinct()
plan = planner.plan(query);
assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("customers-name"), bounds(hasTupleString("[[éponine],[éponine]]"))))));
assertEquals(-574773819, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(2049515086, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-621884304, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(1001L, 1000L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
}
{
RecordQuery.Builder builder = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(Query.field("customer").oneOfThem().equalsValue("gavroche")).setSort(field("name"));
RecordQuery query = builder.setRemoveDuplicates(false).build();
// Index(customers-name [[gavroche],[gavroche]])
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("customers-name"), bounds(hasTupleString("[[gavroche],[gavroche]]")))));
assertEquals(-1720782767, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1507776729, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(173295350, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Collections.singletonList(1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
query = builder.setRemoveDuplicates(true).build();
// Index(customers-name [[gavroche],[gavroche]]) | UnorderedPrimaryKeyDistinct()
plan = planner.plan(query);
assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("customers-name"), bounds(hasTupleString("[[gavroche],[gavroche]]"))))));
assertEquals(-1720782766, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1992010913, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-621884304, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Collections.singletonList(1001L), fetchResultValues(plan, TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER, this::openNestedRecordStore, TestHelpers::assertDiscardedNone));
}
}
use of com.apple.foundationdb.record.TestHelpers in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method buildNewUniversalIndex.
/**
* Verify that building a universal index works.
*/
@Test
public void buildNewUniversalIndex() throws Exception {
try (FDBRecordContext context = openContext()) {
uncheckedOpenNestedRecordStore(context);
recordStore.checkVersion(null, FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_EXISTS).join();
for (int i = 0; i < 10; i++) {
recordStore.saveRecord(TestRecords4Proto.RestaurantReviewer.newBuilder().setId(i).setName("r " + i % 10).build());
recordStore.saveRecord(TestRecords4Proto.RestaurantRecord.newBuilder().setRestNo(100 + i).setName("r " + i % 10).build());
}
commit(context);
}
RecordQuery query = RecordQuery.newBuilder().setFilter(Query.field("name").equalsValue("r 8")).build();
final Function<Message, Object> getIds = r -> {
final Descriptors.Descriptor descriptor = r.getDescriptorForType();
return r.getField(Objects.equals(descriptor.getName(), "RestaurantRecord") ? descriptor.findFieldByNumber(TestRecords4Proto.RestaurantRecord.REST_NO_FIELD_NUMBER) : descriptor.findFieldByNumber(TestRecords4Proto.RestaurantReviewer.ID_FIELD_NUMBER));
};
assertEquals(Arrays.asList(8L, 108L), fetchResultValues(planner.plan(query), this::uncheckedOpenNestedRecordStore, getIds));
// Adds an index for that query.
RecordMetaDataHook hook = metaData -> metaData.addUniversalIndex(new Index("new_index", "name"));
Opener openWithNewIndex = context -> uncheckedOpenNestedRecordStore(context, hook);
try (FDBRecordContext context = openContext()) {
uncheckedOpenNestedRecordStore(context, hook);
for (int i = 10; i < 20; i++) {
recordStore.saveRecord(TestRecords4Proto.RestaurantReviewer.newBuilder().setId(i).setName("r " + i % 10).build());
recordStore.saveRecord(TestRecords4Proto.RestaurantRecord.newBuilder().setRestNo(100 + i).setName("r " + i % 10).build());
}
commit(context);
}
// Only sees new record added after index.
assertEquals(Arrays.asList(18L, 118L), fetchResultValues(planner.plan(query), openWithNewIndex, getIds));
try (FDBRecordContext context = openContext()) {
uncheckedOpenNestedRecordStore(context, hook);
recordStore.checkVersion(null, FDBRecordStoreBase.StoreExistenceCheck.NONE).join();
assertEquals(1, timer.getCount(FDBStoreTimer.Events.REBUILD_INDEX), "should build new index");
commit(context);
}
// Now see both records from indexed query.
assertEquals(Arrays.asList(8L, 18L, 108L, 118L), fetchResultValues(planner.plan(query), openWithNewIndex, getIds, TestHelpers::assertDiscardedNone));
}
Aggregations