use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class FDBNestedFieldQueryTest method hierarchical.
/**
* Verify that simple queries on nested fields can use bounds on a record scan.
*/
@DualPlannerTest
public void hierarchical() throws Exception {
try (FDBRecordContext context = openContext()) {
openHierarchicalRecordStore(context);
TestRecords3Proto.MyHierarchicalRecord.Builder recBuilder = TestRecords3Proto.MyHierarchicalRecord.newBuilder();
recBuilder.setChildName("photos");
recBuilder.setNumValueIndexed(1);
recordStore.saveRecord(recBuilder.build());
recBuilder.setChildName("music");
recBuilder.setNumValueIndexed(2);
recordStore.saveRecord(recBuilder.build());
recBuilder.setParentPath("photos");
recBuilder.setChildName("vacations");
recBuilder.setNumValueIndexed(11);
recordStore.saveRecord(recBuilder.build());
recBuilder.setChildName("pets");
recBuilder.setNumValueIndexed(12);
recordStore.saveRecord(recBuilder.build());
recBuilder.setParentPath("photos/vacations");
recBuilder.setChildName("paris");
recBuilder.setNumValueIndexed(111);
recordStore.saveRecord(recBuilder.build());
recBuilder.setChildName("london");
recBuilder.setNumValueIndexed(112);
recordStore.saveRecord(recBuilder.build());
recBuilder.setParentPath("photos/vacations/paris");
recBuilder.setChildName("seine");
recBuilder.setNumValueIndexed(1111);
recordStore.saveRecord(recBuilder.build());
commit(context);
}
try (FDBRecordContext context = openContext()) {
openHierarchicalRecordStore(context);
FDBStoredRecord<Message> rec = recordStore.loadRecord(Tuple.from(null, "photos"));
assertNotNull(rec);
TestRecords3Proto.MyHierarchicalRecord.Builder myrec = TestRecords3Proto.MyHierarchicalRecord.newBuilder();
myrec.mergeFrom(rec.getRecord());
assertEquals(1, myrec.getNumValueIndexed());
}
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyHierarchicalRecord").setFilter(Query.field("parent_path").equalsValue("photos")).build();
// Scan([[photos],[photos]])
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, scan(bounds(hasTupleString("[[photos],[photos]]"))));
assertEquals(1063779424, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-623055281, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(568511736, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(12, 11), fetchResultValues(plan, TestRecords3Proto.MyHierarchicalRecord.NUM_VALUE_INDEXED_FIELD_NUMBER, this::openHierarchicalRecordStore, TestHelpers::assertDiscardedNone));
query = RecordQuery.newBuilder().setRecordType("MyHierarchicalRecord").setFilter(Query.field("parent_path").startsWith("photos")).build();
// Scan({[photos],[photos]})
plan = planner.plan(query);
assertThat(plan, scan(bounds(hasTupleString("{[photos],[photos]}"))));
assertEquals(224213141, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1663787616, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1347957217, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
assertEquals(Arrays.asList(12, 11, 112, 111, 1111), fetchResultValues(plan, TestRecords3Proto.MyHierarchicalRecord.NUM_VALUE_INDEXED_FIELD_NUMBER, this::openHierarchicalRecordStore, TestHelpers::assertDiscardedNone));
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class FDBNestedFieldQueryTest method nestedRankMap.
/**
* Verify that a rank index on a map-like repeated nested message can be scanned for rank comparisons.
*/
@Test
public void nestedRankMap() throws Exception {
final GroupingKeyExpression rankGroup = new GroupingKeyExpression(concat(field("other_id"), field("map").nest(field("entry", KeyExpression.FanType.FanOut).nest(concatenateFields("key", "value")))), 1);
final RecordMetaDataBuilder metaDataBuilder = RecordMetaData.newBuilder().setRecords(TestRecordsNestedMapProto.getDescriptor());
metaDataBuilder.addIndex("OuterRecord", new Index("rank_value_by_key", rankGroup, IndexTypes.RANK));
// TODO: This is not a very obvious way to specify this. But we don't have correlation names.
final QueryComponent keyCondition = Query.field("map").matches(Query.field("entry").oneOfThem().matches(Query.field("key").equalsValue("alpha")));
final QueryRecordFunction<Long> rank = Query.rank(rankGroup).withAdditionalCondition(keyCondition);
try (FDBRecordContext context = openContext()) {
createOrOpenRecordStore(context, metaDataBuilder.getRecordMetaData());
TestRecordsNestedMapProto.OuterRecord.Builder builder = TestRecordsNestedMapProto.OuterRecord.newBuilder().setOtherId(1);
TestRecordsNestedMapProto.MapRecord.Builder mapBuilder = builder.getMapBuilder();
builder.setRecId(1);
mapBuilder.addEntryBuilder().setKey("alpha").setValue("abc");
mapBuilder.addEntryBuilder().setKey("beta").setValue("bcd");
recordStore.saveRecord(builder.build());
builder.setRecId(2);
mapBuilder.clear();
mapBuilder.addEntryBuilder().setKey("alpha").setValue("aaa");
mapBuilder.addEntryBuilder().setKey("beta").setValue("bbb");
recordStore.saveRecord(builder.build());
commit(context);
}
RecordQuery query = RecordQuery.newBuilder().setRecordType("OuterRecord").setFilter(Query.and(Query.field("other_id").equalsValue(1L), Query.rank(rankGroup).lessThan(10L), keyCondition)).build();
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("rank_value_by_key"), indexScanType(IndexScanType.BY_RANK), bounds(hasTupleString("([1, alpha, null],[1, alpha, 10])"))))));
assertEquals(1307013946, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1725407749, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(825274646, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
try (FDBRecordContext context = openContext()) {
createOrOpenRecordStore(context, metaDataBuilder.getRecordMetaData());
try (RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan)) {
RecordCursorResult<FDBQueriedRecord<Message>> result = cursor.getNext();
assertTrue(result.hasNext());
assertEquals(Tuple.from(2), result.get().getPrimaryKey());
result = cursor.getNext();
assertTrue(result.hasNext());
assertEquals(Tuple.from(1), result.get().getPrimaryKey());
assertEquals(1, rank.eval(recordStore, EvaluationContext.EMPTY, result.get().getStoredRecord()).get());
result = cursor.getNext();
assertFalse(result.hasNext());
}
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class FDBNestedFieldQueryTest method doublyNested.
/**
* Verify that queries on doubly nested records with fanout on the inner field work properly.
*/
@DualPlannerTest
public void doublyNested() throws Exception {
try (FDBRecordContext context = openContext()) {
openDoublyNestedRecordStore(context);
TestRecords5Proto.CalendarEvent.Builder eventBuilder = TestRecords5Proto.CalendarEvent.newBuilder();
eventBuilder.setPath("ev1");
TestRecords5Proto.CalendarEventIndex.Builder indexBuilder = eventBuilder.getEventIndexBuilder();
TestRecords5Proto.Recurrence.Builder occurBuilder = indexBuilder.addRecurrenceBuilder();
occurBuilder.setStart(2);
occurBuilder.setEnd(2);
occurBuilder = indexBuilder.addRecurrenceBuilder();
occurBuilder.setStart(12);
occurBuilder.setEnd(12);
recordStore.saveRecord(eventBuilder.build());
eventBuilder = TestRecords5Proto.CalendarEvent.newBuilder();
eventBuilder.setPath("ev2");
indexBuilder = eventBuilder.getEventIndexBuilder();
occurBuilder = indexBuilder.addRecurrenceBuilder();
occurBuilder.setStart(5);
occurBuilder.setEnd(5);
recordStore.saveRecord(eventBuilder.build());
eventBuilder = TestRecords5Proto.CalendarEvent.newBuilder();
eventBuilder.setPath("ev3");
indexBuilder = eventBuilder.getEventIndexBuilder();
occurBuilder = indexBuilder.addRecurrenceBuilder();
occurBuilder.setStart(15);
occurBuilder.setEnd(15);
occurBuilder = indexBuilder.addRecurrenceBuilder();
occurBuilder.setStart(25);
occurBuilder.setEnd(25);
recordStore.saveRecord(eventBuilder.build());
commit(context);
}
// TODO this was originally:
// QueryExpression.field("eventIndex").matches(
// QueryExpression.field("recurrence").matches(
// QueryExpression.field("start").greaterThan(10L))),
// which should have failed validate
RecordQuery query = RecordQuery.newBuilder().setRecordType("CalendarEvent").setFilter(Query.field("eventIndex").matches(Query.field("recurrence").oneOfThem().matches(Query.field("start").greaterThan(10L)))).build();
// Index(event_start ([10],>) | UnorderedPrimaryKeyDistinct()
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
assertThat(plan, primaryKeyDistinct(indexScan(allOf(indexName("event_start"), bounds(hasTupleString("([10],>"))))));
assertEquals(667993366, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1217457303, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1297919931, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertThat(plan, fetch(primaryKeyDistinct(coveringIndexScan(indexScan(allOf(indexName("event_start"), bounds(hasTupleString("([10],>"))))))));
assertEquals(380986279, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-721491332, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-801953960, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
assertEquals(Arrays.asList("ev1", "ev3"), fetchResultValues(plan, TestRecords5Proto.CalendarEvent.PATH_FIELD_NUMBER, this::openDoublyNestedRecordStore, context -> TestHelpers.assertDiscardedAtMost(1, context)));
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class FDBInQueryTest method enumIn.
/**
* Verify that enum field indexes are used to implement IN clauses.
*/
@DualPlannerTest
void enumIn() throws Exception {
RecordMetaDataHook hook = metaData -> {
final RecordTypeBuilder type = metaData.getRecordType("MyShapeRecord");
metaData.addIndex(type, new Index("color", field("color")));
};
setupEnumShapes(hook);
final var redBlue = asList(TestRecordsEnumProto.MyShapeRecord.Color.RED, TestRecordsEnumProto.MyShapeRecord.Color.BLUE);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MyShapeRecord").setFilter(Query.field("color").in(redBlue)).build();
// Index(color [EQUALS $__in_color__0]) WHERE __in_color__0 IN [RED, BLUE]
RecordQueryPlan plan = planner.plan(query);
if (planner instanceof RecordQueryPlanner) {
assertMatchesExactly(plan, descendantPlans(indexPlan().where(indexName("color"))));
assertFalse(plan.hasRecordScan(), "should not use record scan");
assertEquals(-520431454, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(1447363737, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(1442809521, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertMatchesExactly(plan, fetchFromPartialRecordPlan(inValuesJoinPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("color")).and(scanComparisons(equalities(exactly(anyParameterComparison()))))))).where(inValuesList(equalsObject(redBlue)))));
assertFalse(plan.hasRecordScan(), "should not use record scan");
assertEquals(1174038242, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1089300981, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1677589406, 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(Objects.requireNonNull(rec).getRecord());
assertThat(shapeRec.getColor(), is(oneOf(TestRecordsEnumProto.MyShapeRecord.Color.RED, TestRecordsEnumProto.MyShapeRecord.Color.BLUE)));
i++;
}
}
assertEquals(18, i);
TestHelpers.assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class FDBAndQueryToIntersectionTest method testComplexQueryAndWithTwoChildren2.
/**
* Verify that a complex query with an AND of fields with compatibly ordered indexes generates an intersection plan.
*/
@DualPlannerTest
public void testComplexQueryAndWithTwoChildren2() throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("str_value_indexed").equalsValue("even"), Query.field("num_value_3_indexed").equalsValue(3))).build();
setDeferFetchAfterUnionAndIntersection(true);
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, fetch(intersection(coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$str_value_indexed"), bounds(hasTupleString("[[even],[even]]"))))), coveringIndexScan(indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), bounds(hasTupleString("[[3],[3]]"))))), equalTo(field("rec_no")))));
if (planner instanceof RecordQueryPlanner) {
assertEquals(-929788310, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1914172894, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-271606869, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertEquals(-70465554, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(2126183202, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1157469383, 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(rec.getRecord());
assertEquals("even", myrec.getStrValueIndexed());
assertTrue((myrec.getNumValue3Indexed() % 5) == 3);
i++;
}
}
assertEquals(10, i);
assertDiscardedExactly(50, context);
assertLoadRecord(10, context);
}
}
Aggregations