use of com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord in project fdb-record-layer by FoundationDB.
the class FDBSortQueryIndexSelectionTest method testComplexLimits1.
/**
* Verify that reverse sorts can be implemented by a reverse index scan.
*/
@DualPlannerTest
public void testComplexLimits1() throws Exception {
RecordMetaDataHook hook = complexQuerySetupHook();
complexQuerySetup(hook);
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setSort(field("str_value_indexed"), true).build();
// Index(MySimpleRecord$str_value_indexed <,> REVERSE)
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("MySimpleRecord$str_value_indexed"), unbounded())));
assertTrue(plan.isReverse(), "plan is reversed");
assertEquals(324762955, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(19722195, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(19722195, 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, null, ExecuteProperties.newBuilder().setReturnedRowLimit(10).build()).asIterator()) {
while (cursor.hasNext()) {
FDBQueriedRecord<Message> rec = cursor.next();
TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
assertEquals("odd", myrec.getStrValueIndexed());
i += 1;
}
}
assertEquals(10, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord in project fdb-record-layer by FoundationDB.
the class FDBSortQueryIndexSelectionTest method sortUniqueNull.
/**
* Verify that sort with filter works with different null interpretation on unique index.
*/
@DualPlannerTest
void sortUniqueNull() {
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, NULL_UNIQUE_HOOK);
for (int i = 0; i < 100; i++) {
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo((1096 * i + 722) % 1289);
recBuilder.setNumValueUnique(i);
recordStore.saveRecord(recBuilder.build());
}
commit(context);
}
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_unique").greaterThanOrEquals(20)).setSort(field("num_value_unique")).build();
// Index(MySimpleRecord$num_value_unique [[20],>)
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, indexScan(allOf(indexName("MySimpleRecord$num_value_unique"), bounds(hasTupleString("[[20],>")))));
if (planner instanceof RecordQueryPlanner) {
assertEquals(-535398101, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1799532339, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1088253993, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
} else {
assertEquals(-535398101, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
assertEquals(-1799532345, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
assertEquals(-1088253999, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, NULL_UNIQUE_HOOK);
int i = 20;
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(Objects.requireNonNull(rec).getRecord());
assertEquals(i++, myrec.getNumValueUnique());
}
}
assertEquals(100, i);
assertDiscardedNone(context);
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreScanLimitTest method unorderedIntersectionWithScanLimit.
@ParameterizedTest(name = "unorderedIntersectionWithScanLimit [fail = {0}]")
@BooleanSource
public void unorderedIntersectionWithScanLimit(boolean fail) throws Exception {
// TODO: When there is an UnorderedIntersectionPlan (or whatever) add that to the unordered plans stream
RecordQueryPlanner planner = new RecordQueryPlanner(simpleMetaData(NO_HOOK), new RecordStoreState(null, null));
RecordQueryPlan leftPlan = planner.plan(RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("str_value_indexed").startsWith("ev")).build());
RecordQueryPlan rightPlan = planner.plan(RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_3_indexed").lessThanOrEquals(1)).build());
int maximumToScan;
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
maximumToScan = recordStore.executeQuery(leftPlan).getCount().get() + recordStore.executeQuery(rightPlan).getCount().get();
}
for (int limit = 0; limit < 3 * maximumToScan; limit = 2 * limit + 1) {
final int finalLimit = limit;
Function<byte[], RecordCursor<FDBQueriedRecord<Message>>> cursorFunction = (continuation) -> {
ExecuteProperties executeProperties = ExecuteProperties.newBuilder().setScannedRecordsLimit(finalLimit).setFailOnScanLimitReached(fail).build();
return ProbableIntersectionCursor.create(record -> record.getPrimaryKey().getItems(), Arrays.asList(leftContinuation -> leftPlan.execute(recordStore, EvaluationContext.EMPTY, leftContinuation, executeProperties), rightContinuation -> rightPlan.execute(recordStore, EvaluationContext.EMPTY, rightContinuation, executeProperties)), continuation, recordStore.getTimer());
};
assertNumberOfRecordsScanned(limit, cursorFunction, fail, "should" + (limit >= maximumToScan ? "not " : "") + " be limited by record scan limit");
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreScanLimitTest method assertNumberOfRecordsScanned.
private void assertNumberOfRecordsScanned(int expected, Function<byte[], RecordCursor<FDBQueriedRecord<Message>>> cursorFunction, boolean failOnLimitReached, String message) throws Exception {
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
if (context.getTimer() != null) {
context.getTimer().reset();
}
try (RecordCursor<FDBQueriedRecord<Message>> cursor = cursorFunction.apply(null)) {
boolean caughtScanLimitReached = false;
RecordCursorResult<FDBQueriedRecord<Message>> result = null;
try {
do {
result = cursor.getNext();
} while (result.hasNext());
} catch (RecordCoreException ex) {
if (failOnLimitReached && ex.getCause() instanceof ScanLimitReachedException) {
caughtScanLimitReached = true;
} else {
throw ex;
}
}
if (failOnLimitReached && !caughtScanLimitReached) {
assertNotEquals(RecordCursor.NoNextReason.SCAN_LIMIT_REACHED, result.getNoNextReason());
}
Optional<Integer> scanned = getRecordScanned(context);
if (context.getTimer() != null) {
context.getTimer().reset();
}
int overrun = BaseCursorCountVisitor.getCount(cursor);
scanned.ifPresent(value -> assertThat(message, value, lessThanOrEqualTo(expected + overrun)));
}
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreScanLimitTest method testExecuteStateReset.
@ParameterizedTest
// for this test, the scan limit must divide 100
@ValueSource(ints = { 2, 5, 10, 20 })
public void testExecuteStateReset(int scanLimit) throws Exception {
final IndexScanParameters fullValueScan = IndexScanComparisons.byValue();
final RecordQueryPlan plan = new RecordQueryIndexPlan("MySimpleRecord$str_value_indexed", fullValueScan, false);
ExecuteProperties properties = ExecuteProperties.newBuilder().setScannedRecordsLimit(scanLimit).build();
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
byte[] continuation = null;
do {
try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan, continuation, properties).asIterator()) {
int retrieved = 0;
while (cursor.hasNext()) {
cursor.next();
retrieved++;
}
continuation = cursor.getContinuation();
if (continuation != null) {
// if this is our last call, we might retrieve 0 results
assertEquals(scanLimit, retrieved);
}
properties = properties.resetState();
}
} while (continuation != null);
}
}
Aggregations