use of com.apple.foundationdb.record.RecordCursorIterator 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);
}
}
}
use of com.apple.foundationdb.record.RecordCursorIterator in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreQueryTest method enumFields.
/**
* Verify that enum field indexes are used.
*/
@DualPlannerTest
void enumFields() throws Exception {
RecordMetaDataHook hook = metaData -> {
final RecordTypeBuilder type = metaData.getRecordType("MyShapeRecord");
metaData.addIndex(type, new Index("size", field("size")));
metaData.addIndex(type, new Index("color", field("color")));
metaData.addIndex(type, new Index("shape", field("shape")));
};
setupEnumShapes(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyShapeRecord").setFilter(Query.field("color").equalsValue(TestRecordsEnumProto.MyShapeRecord.Color.RED)).build();
// Index(color [[10],[10]])
RecordQueryPlan plan = planner.plan(query);
assertMatchesExactly(plan, indexPlan().where(indexName("color")));
assertFalse(plan.hasRecordScan(), "should not use record scan");
assertEquals(1393755963, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-14917443, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-2083866282, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
try (FDBRecordContext context = openContext()) {
openEnumRecordStore(context, hook);
int i = 0;
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
TestRecordsEnumProto.MyShapeRecord.Builder shapeRec = TestRecordsEnumProto.MyShapeRecord.newBuilder();
shapeRec.mergeFrom(rec.getRecord());
assertEquals(TestRecordsEnumProto.MyShapeRecord.Color.RED, shapeRec.getColor());
i++;
}
}
assertEquals(9, i);
assertDiscardedNone(context);
}
}
Aggregations