use of com.apple.foundationdb.record.RecordCursorIterator in project fdb-record-layer by FoundationDB.
the class ChainedCursorTest method limitBy.
private void limitBy(int returnedRowLimit, int recordScanLimit, RecordCursor.NoNextReason noNextReason) {
// Note that this test only requires a database and a context because the ChainedCursor API requires
// a context to be passed in when you are applying scan limits.
FDBDatabase database = FDBDatabaseFactory.instance().getDatabase();
try (FDBRecordContext context = database.openContext()) {
ScanProperties props = new ScanProperties(ExecuteProperties.newBuilder().setReturnedRowLimit(returnedRowLimit).setScannedRecordsLimit(recordScanLimit).setFailOnScanLimitReached(false).build());
RecordCursorIterator<Long> cursor = new ChainedCursor<>(context, ChainedCursorTest::nextKey, (key) -> Tuple.from(key).pack(), (prevContinuation) -> Tuple.fromBytes(prevContinuation).getLong(0), null, props).asIterator();
int count = 0;
while (cursor.hasNext()) {
assertEquals(Long.valueOf(count), cursor.next());
++count;
}
assertEquals(Math.min(returnedRowLimit, recordScanLimit), count);
assertEquals(cursor.getNoNextReason(), noNextReason);
}
}
use of com.apple.foundationdb.record.RecordCursorIterator in project fdb-record-layer by FoundationDB.
the class FDBFilterCoalescingQueryTest method duplicateFilters.
/**
* Verify that the planner removes duplicate filters.
* TODO We currently don't. Update this test when it gets implemented.
* TODO: Some query plans include redundant filtering operations even when the index is a complete specification (https://github.com/FoundationDB/fdb-record-layer/issues/2)
*/
@Test
public void duplicateFilters() throws Exception {
RecordMetaDataHook hook = metaData -> {
metaData.addIndex("MySimpleRecord", new Index("multi_index", "str_value_indexed", "num_value_3_indexed"));
};
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), Query.field("num_value_3_indexed").equalsValue(3))).build();
// Fetch(Covering(Index(multi_index [[even, 3],[even, 3]]) -> [num_value_3_indexed: KEY[1], rec_no: KEY[2], str_value_indexed: KEY[0]]) | num_value_3_indexed EQUALS 3)
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, descendant(coveringIndexScan(indexScan(allOf(indexName("multi_index"), bounds(hasTupleString("[[even, 3],[even, 3]]")))))));
assertEquals(-766201402, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1632715349, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1418679945, 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());
assertEquals(3, myrec.getNumValue3Indexed());
assertEquals(3, myrec.getRecNo() % 5);
i++;
}
}
assertEquals(10, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.RecordCursorIterator in project fdb-record-layer by FoundationDB.
the class FDBFilterCoalescingQueryTest method versionRangeCoalesce.
/**
* Validate that a query for all values within a given range of versions will be coalesced into a single scan.
* This is similar to the {@link #simpleRangeCoalesce()} test above, but it is for version key expressions in
* particular.
*/
@Test
public void versionRangeCoalesce() throws Exception {
Index versionIndex = new Index("MySimpleRecord$version", VersionKeyExpression.VERSION, IndexTypes.VERSION);
RecordMetaDataHook hook = metaData -> {
metaData.setStoreRecordVersions(true);
metaData.addIndex("MySimpleRecord", versionIndex);
};
complexQuerySetup(hook);
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
long readVersion = context.getReadVersion();
FDBRecordVersion lowBoundary = FDBRecordVersion.firstInDBVersion(0);
FDBRecordVersion highBoundary = FDBRecordVersion.lastInDBVersion(readVersion);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.version().greaterThan(lowBoundary), Query.version().lessThan(highBoundary))).build();
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName(versionIndex.getName()), bounds(hasTupleString("([" + lowBoundary.toVersionstamp() + "],[" + highBoundary.toVersionstamp() + "])")))));
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan).asIterator()) {
int i = 0;
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
FDBRecordVersion version = rec.getVersion();
assertNotNull(version);
assertThat(version, allOf(lessThan(highBoundary), greaterThan(lowBoundary)));
i++;
}
assertEquals(100, i);
assertDiscardedNone(context);
}
}
}
use of com.apple.foundationdb.record.RecordCursorIterator in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method scanIndexWithValue.
/**
* Verify that explicit (i.e. bypassing the planner) index scans work .
*/
@Test
public void scanIndexWithValue() throws Exception {
RecordMetaDataHook hook = metaData -> {
metaData.removeIndex("MySimpleRecord$num_value_unique");
metaData.addIndex("MySimpleRecord", new Index("multi_index_value", Key.Expressions.field("num_value_unique"), Key.Expressions.field("num_value_2"), IndexTypes.VALUE, IndexOptions.UNIQUE_OPTIONS));
};
complexQuerySetup(hook);
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
int i = 0;
try (RecordCursorIterator<IndexEntry> cursor = recordStore.scanIndex(recordStore.getRecordMetaData().getIndex("multi_index_value"), IndexScanType.BY_VALUE, new TupleRange(Tuple.from(900L), Tuple.from(950L), EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_INCLUSIVE), null, ScanProperties.FORWARD_SCAN).asIterator()) {
while (cursor.hasNext()) {
IndexEntry tuples = cursor.next();
Tuple key = tuples.getKey();
Tuple value = tuples.getValue();
assertEquals(2, key.size());
assertEquals(1, value.size());
assertTrue(key.getLong(0) >= 900);
assertTrue(key.getLong(0) <= 950);
assertTrue(value.getLong(0) == (999 - i) % 3);
i++;
}
}
assertEquals(50, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.RecordCursorIterator 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);
}
}
Aggregations