use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.
the class FDBNestedFieldQueryTest method nested2.
/**
* Verify that nested field comparisons with fanout can scan indexes.
*/
@DualPlannerTest
public void nested2() throws Exception {
RecordMetaDataHook hook = metaData -> {
metaData.addIndex("RestaurantRecord", "complex", concat(field("name"), field("rest_no"), field("reviews", KeyExpression.FanType.FanOut).nest(concat(field("reviewer"), field("rating")))));
metaData.addIndex("RestaurantRecord", "composite", concat(field("name"), field("rest_no")));
metaData.addIndex("RestaurantRecord", "duplicates", concat(field("name"), field("name")));
};
try (FDBRecordContext context = openContext()) {
openNestedRecordStore(context, hook);
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);
}
final QueryComponent nestedComponent = // Query.field("reviews").oneOfThem().matches(Query.field("rating").equalsValue(20))
Query.field("reviews").oneOfThem().matches(Query.and(Query.field("reviewer").equalsValue(10L), Query.field("rating").equalsValue(20)));
final RecordQuery query = RecordQuery.newBuilder().setRecordType("RestaurantRecord").setFilter(Query.and(Query.field("name").equalsValue("something"), Query.field("name").equalsValue("something"), Query.field("rest_no").equalsValue(1L), nestedComponent)).build();
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
// Does not understand duplicate condition
assertThat(plan, filter(nestedComponent, indexScan(allOf(indexName("duplicates"), bounds(hasTupleString("[[something, something, 1],[something, something, 1]]"))))));
} else {
assertThat(plan, fetch(primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("complex"), bounds(hasTupleString("[[something, 1, 10, 20],[something, 1, 10, 20]]"))))))));
}
}
use of com.apple.foundationdb.record.query.expressions.QueryComponent 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.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.
the class FDBFullTextQueryTest method delayFetchOnUnionOfFullTextScans.
@ParameterizedTest
@BooleanSource
public void delayFetchOnUnionOfFullTextScans(boolean shouldDeferFetch) throws Exception {
final List<TestRecordsTextProto.SimpleDocument> documents = TextIndexTestUtils.toSimpleDocuments(Arrays.asList(TextSamples.ANGSTROM, TextSamples.AETHELRED, TextSamples.ROMEO_AND_JULIET_PROLOGUE, TextSamples.FRENCH));
try (FDBRecordContext context = openContext()) {
openRecordStore(context);
documents.forEach(recordStore::saveRecord);
commit(context);
}
try (FDBRecordContext context = openContext()) {
openRecordStore(context);
final QueryComponent filter1 = Query.field("text").text().containsPhrase("civil blood makes civil hands unclean");
final Comparisons.Comparison comparison1 = new Comparisons.TextComparison(Comparisons.Type.TEXT_CONTAINS_PHRASE, "civil blood makes civil hands unclean", null, DefaultTextTokenizer.NAME);
final QueryComponent filter2 = Query.field("text").text().containsPrefix("th");
final Comparisons.Comparison comparison2 = new Comparisons.TextComparison(Comparisons.Type.TEXT_CONTAINS_PREFIX, Collections.singletonList("th"), null, DefaultTextTokenizer.NAME);
// Query for full records
RecordQuery query = RecordQuery.newBuilder().setRecordType(TextIndexTestUtils.SIMPLE_DOC).setFilter(Query.or(filter1, filter2)).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
// Unordered(TextIndex(SimpleDocument$text null, TEXT_CONTAINS_PHRASE civil blood makes civil hands unclean, null) ∪ TextIndex(SimpleDocument$text null, TEXT_CONTAINS_PREFIX [th], null) | UnorderedPrimaryKeyDistinct()) | UnorderedPrimaryKeyDistinct()
// Fetch(Unordered(Covering(TextIndex(SimpleDocument$text null, TEXT_CONTAINS_PHRASE civil blood makes civil hands unclean, null) -> [doc_id: KEY[1]]) ∪ Covering(TextIndex(SimpleDocument$text null, TEXT_CONTAINS_PREFIX [th], null) -> [doc_id: KEY[1]]) | UnorderedPrimaryKeyDistinct()) | UnorderedPrimaryKeyDistinct())
RecordQueryPlan plan = planner.plan(query);
if (shouldDeferFetch) {
assertThat(plan, fetch(primaryKeyDistinct(unorderedUnion(coveringIndexScan(textIndexScan(allOf(indexName(TextIndexTestUtils.SIMPLE_DEFAULT_NAME), textComparison(equalTo(comparison1))))), primaryKeyDistinct(coveringIndexScan(textIndexScan(allOf(indexName(TextIndexTestUtils.SIMPLE_DEFAULT_NAME), textComparison(equalTo(comparison2))))))))));
assertEquals(-683922391, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-833837033, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-464003585, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, primaryKeyDistinct(unorderedUnion(textIndexScan(allOf(indexName(TextIndexTestUtils.SIMPLE_DEFAULT_NAME), textComparison(equalTo(comparison1)))), primaryKeyDistinct(textIndexScan(allOf(indexName(TextIndexTestUtils.SIMPLE_DEFAULT_NAME), textComparison(equalTo(comparison2))))))));
assertEquals(515863556, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1307589440, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1677422888, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
List<Long> primaryKeys = recordStore.executeQuery(plan).map(FDBQueriedRecord::getPrimaryKey).map(t -> t.getLong(0)).asList().get();
assertEquals(ImmutableSet.of(0L, 1L, 2L, 3L), ImmutableSet.copyOf(primaryKeys));
if (shouldDeferFetch) {
assertLoadRecord(4, context);
} else {
assertLoadRecord(8, context);
}
}
}
use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.
the class FDBRepeatedFieldQueryTest method testPrefixRepeatedNested.
/**
* Verifies that a query of a nested, non-repeated field can use an index that starts with that field only if the
* query also includes the repeated field, because repeated introduces duplicates and index entries are ordered by
* second field and so cannot be deduplicated without additional space.
*/
@DualPlannerTest
public void testPrefixRepeatedNested() throws Exception {
final RecordMetaDataHook hook = metaData -> {
metaData.getRecordType("MyRecord").setPrimaryKey(field("header").nest(field("rec_no")));
metaData.addIndex("MyRecord", "fanout_index", concat(field("header").nest("path"), field("repeated_int", FanType.FanOut)));
};
try (FDBRecordContext context = openContext()) {
openRecordWithHeader(context, hook);
recordStore.saveRecord(TestRecordsWithHeaderProto.MyRecord.newBuilder().setHeader(TestRecordsWithHeaderProto.HeaderRecord.newBuilder().setRecNo(1L).setPath("foo").build()).clearRepeatedInt().build());
recordStore.saveRecord(TestRecordsWithHeaderProto.MyRecord.newBuilder().setHeader(TestRecordsWithHeaderProto.HeaderRecord.newBuilder().setRecNo(2L).setPath("bar").build()).clearRepeatedInt().addRepeatedInt(1000L).addRepeatedInt(2000L).build());
recordStore.saveRecord(TestRecordsWithHeaderProto.MyRecord.newBuilder().setHeader(TestRecordsWithHeaderProto.HeaderRecord.newBuilder().setRecNo(3L).setPath("baz").build()).clearRepeatedInt().addRepeatedInt(1000L).addRepeatedInt(2000L).addRepeatedInt(3000L).build());
commit(context);
}
final QueryComponent filter = Query.field("header").matches(Query.field("path").startsWith("b"));
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(filter).build();
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, filter(filter, scan(unbounded())));
try (FDBRecordContext context = openContext()) {
openRecordWithHeader(context, hook);
assertEquals(LongStream.range(2L, 4L).mapToObj(Long::valueOf).collect(Collectors.toList()), recordStore.executeQuery(plan).map(FDBQueriedRecord::getRecord).map(this::parseMyRecord).map(myRecord -> myRecord.getHeader().getRecNo()).asList().join());
}
}
use of com.apple.foundationdb.record.query.expressions.QueryComponent in project fdb-record-layer by FoundationDB.
the class FDBSortQueryIndexSelectionTest method sortNested.
/**
* Verify that sorts on nested fields are implemented using nested record field indexes.
*/
@SuppressWarnings("java:S5961")
@DualPlannerTest
void sortNested() {
try (FDBRecordContext context = openContext()) {
RecordMetaDataBuilder builder = RecordMetaData.newBuilder().setRecords(TestRecordsWithHeaderProto.getDescriptor());
builder.getRecordType("MyRecord").setPrimaryKey(field("header").nest(concatenateFields("path", "rec_no")));
builder.addIndex("MyRecord", "MyRecord$header_num", concat(field("header").nest("num"), field("str_value")));
RecordMetaData metaData = builder.getRecordMetaData();
createOrOpenRecordStore(context, metaData);
for (int i = 0; i < 100; i++) {
TestRecordsWithHeaderProto.MyRecord.Builder recBuilder = TestRecordsWithHeaderProto.MyRecord.newBuilder();
TestRecordsWithHeaderProto.HeaderRecord.Builder headerBuilder = recBuilder.getHeaderBuilder();
// Carter-Wegman hash, with large enough prime
headerBuilder.setRecNo((1096 * i + 722) % 1289);
headerBuilder.setPath("root");
headerBuilder.setNum(i);
recBuilder.setStrValue(Integer.toString(i));
recordStore.saveRecord(recBuilder.build());
}
{
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setSort(field("header").nest("num")).build();
// Index(MyRecord$header_num <,>)
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("MyRecord$header_num"), unbounded())));
assertEquals(-1173952475, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1008825832, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1008825832, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
int i = 0;
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(i++, myrec.getHeader().getNum());
}
}
assertEquals(100, i);
assertDiscardedNone(context);
}
{
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("header").matches(Query.field("num").lessThan(50))).setSort(field("header").nest("num")).build();
// Index(MyRecord$header_num ([null],[50]))
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("MyRecord$header_num"), bounds(hasTupleString("([null],[50])")))));
if (planner instanceof RecordQueryPlanner) {
assertEquals(2008179964, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(2049006062, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-204519612, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertEquals(2008179964, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
// TODO strictly sorted is not set
assertEquals(2049006068, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
// TODO strictly sorted is not set
assertEquals(-204519606, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
int i = 0;
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(i++, myrec.getHeader().getNum());
}
}
assertEquals(50, i);
assertDiscardedNone(context);
}
{
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("header").matches(Query.field("num").equalsValue(1))).setSort(field("str_value")).build();
// Index(MyRecord$header_num [[1],[1]])
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("MyRecord$header_num"), bounds(hasTupleString("[[1],[1]]")))));
assertEquals(878861315, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(653879397, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(998239886, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
int i = 0;
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(1, myrec.getHeader().getNum());
i++;
}
}
assertEquals(1, i);
assertDiscardedNone(context);
}
{
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.and(Query.field("header").matches(Query.field("num").isNull()), Query.field("str_value").greaterThan("middle"))).setSort(field("str_value")).build();
// Index(MyRecord$header_num ([null, middle],[null]])
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("MyRecord$header_num"), bounds(hasTupleString("([null, middle],[null]]")))));
assertEquals(1553479768, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1072001836, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1653404355, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
{
final QueryComponent filter = Query.field("header").matches(Query.field("rec_no").greaterThan(0L));
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(filter).setSort(field("header").nest("num")).build();
// Fetch(Covering(Index(MyRecord$header_num <,>) -> [str_value: KEY[1], header: [num: KEY[0], path: KEY[2], rec_no: KEY[3]]]) | header/{rec_no GREATER_THAN 0})
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, fetch(filter(filter, coveringIndexScan(indexScan(allOf(indexName("MyRecord$header_num"), unbounded()))))));
if (planner instanceof RecordQueryPlanner) {
assertEquals(673903077, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-582153460, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-421343502, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertEquals(749683984, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(87367824, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(248177782, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
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());
assertTrue(myrec.hasHeader(), "Retrieved record missing header");
assertTrue(myrec.getHeader().hasRecNo(), "Retrieved record missing rec_no");
long recNo = myrec.getHeader().getRecNo();
assertTrue(recNo > 0L, "Record does not match filter (rec_no " + recNo + "<= 0)");
}
}
assertDiscardedExactly(0, context);
clearStoreCounter(context);
}
{
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyRecord").setFilter(Query.field("header").matches(Query.and(Query.field("rec_no").greaterThan(10L), Query.field("num").lessThan(50)))).setSort(field("header").nest("num")).build();
// Fetch(Covering(Index(MyRecord$header_num ([null],[50])) -> [str_value: KEY[1], header: [num: KEY[0], path: KEY[2], rec_no: KEY[3]]]) | header/{rec_no GREATER_THAN 10})
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, fetch(filter(Query.field("header").matches(Query.field("rec_no").greaterThan(10L)), coveringIndexScan(indexScan(allOf(indexName("MyRecord$header_num"), bounds(hasTupleString("([null],[50])"))))))));
if (planner instanceof RecordQueryPlanner) {
assertEquals(1473993740, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1598662608, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(619653398, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertEquals(1549774647, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-2026783218, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1289174868, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
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());
assertTrue(myrec.hasHeader(), "Retrieved record missing header");
assertTrue(myrec.getHeader().hasRecNo(), "Retrieved record missing rec_no");
assertTrue(myrec.getHeader().hasNum(), "Retrieved record missing num");
long recNo = myrec.getHeader().getRecNo();
int num = myrec.getHeader().getNum();
assertTrue(recNo > 10L && num < 50, "Retrieved record does not match filter (rec_no = " + recNo + " and num = " + num + ")");
}
}
assertDiscardedExactly(0, context);
}
}
}
Aggregations