use of com.apple.foundationdb.record.RecordCursor in project fdb-record-layer by FoundationDB.
the class UnorderedUnionCursorTest method errorAndLimitInChild.
@Test
public void errorAndLimitInChild() {
CompletableFuture<Integer> future = new CompletableFuture<>();
RecordCursor<Integer> cursor = UnorderedUnionCursor.create(Arrays.asList(continuation -> RecordCursor.fromList(Arrays.asList(1, 2), continuation).limitRowsTo(1), continuation -> RecordCursor.fromFuture(future)), null, null);
RecordCursorResult<Integer> cursorResult = cursor.getNext();
assertEquals(1, (int) cursorResult.get());
CompletableFuture<RecordCursorResult<Integer>> cursorResultFuture = cursor.onNext();
final RecordCoreException ex = new RecordCoreException("something bad happened!");
future.completeExceptionally(ex);
ExecutionException executionException = assertThrows(ExecutionException.class, cursorResultFuture::get);
assertNotNull(executionException.getCause());
assertSame(ex, executionException.getCause());
}
use of com.apple.foundationdb.record.RecordCursor in project fdb-record-layer by FoundationDB.
the class UnorderedUnionCursorTest method errorInChild.
@Test
public void errorInChild() {
CompletableFuture<Integer> future = new CompletableFuture<>();
RecordCursor<Integer> cursor = UnorderedUnionCursor.create(Arrays.asList(continuation -> RecordCursor.fromList(Arrays.asList(1, 2), continuation), continuation -> RecordCursor.fromFuture(future)), null, null);
RecordCursorResult<Integer> cursorResult = cursor.getNext();
assertEquals(1, (int) cursorResult.get());
cursorResult = cursor.getNext();
assertEquals(2, (int) cursorResult.get());
CompletableFuture<RecordCursorResult<Integer>> cursorResultFuture = cursor.onNext();
final RecordCoreException ex = new RecordCoreException("something bad happened!");
future.completeExceptionally(ex);
ExecutionException executionException = assertThrows(ExecutionException.class, cursorResultFuture::get);
assertNotNull(executionException.getCause());
assertSame(ex, executionException.getCause());
}
use of com.apple.foundationdb.record.RecordCursor in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreByteLimitTest method testPlansReturnSameRecordsRegardlessOfLimit.
@ParameterizedTest(name = "plansByContinuation() [{index}] {0}")
@MethodSource("plans")
public void testPlansReturnSameRecordsRegardlessOfLimit(String description, boolean notUsed, RecordQueryPlan plan) throws Exception {
setupSimpleRecordStore();
final Function<FDBQueriedRecord<Message>, Long> getRecNo = r -> {
TestRecords1Proto.MySimpleRecord.Builder record = TestRecords1Proto.MySimpleRecord.newBuilder();
record.mergeFrom(r.getRecord());
return record.getRecNo();
};
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
final List<Long> allAtOnce;
try (RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan)) {
allAtOnce = cursor.map(getRecNo).asList().get();
}
for (long byteLimit = 0; byteLimit < 1000; byteLimit += 100) {
final ExecuteProperties executeProperties = ExecuteProperties.newBuilder().setScannedBytesLimit(byteLimit).build();
final List<Long> byContinuation = new ArrayList<>(allAtOnce.size());
byte[] continuation = null;
do {
try (RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan, continuation, executeProperties)) {
RecordCursorResult<Long> result;
do {
result = cursor.onNext().get().map(getRecNo);
if (result.hasNext()) {
byContinuation.add(result.get());
}
} while (result.hasNext());
continuation = result.getContinuation().toBytes();
}
} while (continuation != null);
assertEquals(allAtOnce, byContinuation);
}
}
}
use of com.apple.foundationdb.record.RecordCursor in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreByteLimitTest method queryWithWideOrOfFullTextPrefixPredicates.
/**
* Queries with an OR of {@link com.apple.foundationdb.record.query.expressions.Text#containsPrefix(String)}
* predicates get planned as {@link com.apple.foundationdb.record.query.plan.plans.RecordQueryUnorderedUnionPlan}s,
* which have unusual semantics where results are returned in an undefined order as soon as any child has one.
* Therefore, the assertions made in {@link #assertPlanLimitsWithCorrectExecution(List, FDBRecordContext, RecordQueryPlan)}
* are far too strong for plans like this. Instead, we make very weak assertions that the byte scan limit does
* <em>something</em>.
*/
@ParameterizedTest
@MethodSource("complexTextQueries")
public void queryWithWideOrOfFullTextPrefixPredicates(@Nonnull RecordQuery query, int numPredicates) throws Exception {
deleteSimpleRecords();
final List<String> textSamples = ImmutableList.of(TextSamples.ANGSTROM, TextSamples.ROMEO_AND_JULIET_PROLOGUE, TextSamples.AETHELRED, TextSamples.FRENCH, TextSamples.KOREAN);
RecordMetaDataHook indexHook = metaDataBuilder -> metaDataBuilder.addIndex(metaDataBuilder.getRecordType(SIMPLE_DOC), SIMPLE_TEXT_PREFIX);
try (FDBRecordContext context = openContext()) {
openTextRecordStore(context, indexHook);
for (int i = 0; i < textSamples.size(); i++) {
recordStore.saveRecord(TestRecordsTextProto.SimpleDocument.newBuilder().setDocId(i).setGroup(i % 2).setText(textSamples.get(i)).build());
}
commit(context);
}
setupPlanner(null);
RecordQueryPlan plan = planner.plan(query);
assertThat(plan, descendant(unorderedUnion(Collections.nCopies(numPredicates, any(RecordQueryPlan.class)))));
long totalBytes;
Set<Long> noLimitRecordIds = new HashSet<>();
try (FDBRecordContext context = openContext()) {
openTextRecordStore(context, indexHook);
context.getTimer().reset();
RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(query, null, ExecuteProperties.SERIAL_EXECUTE);
RecordCursorResult<FDBQueriedRecord<Message>> result;
do {
result = cursor.onNext().get();
if (result.hasNext()) {
TestRecordsTextProto.SimpleDocument.Builder record = TestRecordsTextProto.SimpleDocument.newBuilder();
record.mergeFrom(result.get().getRecord());
noLimitRecordIds.add(record.getDocId());
}
} while (result.hasNext());
totalBytes = byteCounter.getBytesScanned(context);
}
Set<Long> limitRecordIds = new HashSet<>();
try (FDBRecordContext context = openContext()) {
openTextRecordStore(context);
ExecuteProperties.Builder executeProperties = ExecuteProperties.newBuilder().setScannedBytesLimit(0);
byte[] continuation = null;
do {
context.getTimer().reset();
RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(query, continuation, executeProperties.build());
RecordCursorResult<FDBQueriedRecord<Message>> result;
do {
result = cursor.onNext().get();
if (result.hasNext()) {
TestRecordsTextProto.SimpleDocument.Builder record = TestRecordsTextProto.SimpleDocument.newBuilder();
record.mergeFrom(result.get().getRecord());
limitRecordIds.add(record.getDocId());
}
} while (result.hasNext());
assertThat(byteCounter.getBytesScanned(context), lessThan(totalBytes));
continuation = result.getContinuation().toBytes();
if (continuation != null) {
assertEquals(RecordCursor.NoNextReason.BYTE_LIMIT_REACHED, result.getNoNextReason());
}
} while (continuation != null);
assertEquals(noLimitRecordIds, limitRecordIds);
}
}
use of com.apple.foundationdb.record.RecordCursor in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreScanLimitTest method plansByContinuation.
@ParameterizedTest(name = "plansByContinuation() [{index}] {0}")
@MethodSource("plansWithoutFail")
public void plansByContinuation(String description, boolean fail, RecordQueryPlan plan) throws Exception {
int maximumToScan = getMaximumToScan(plan);
// include a scanLimit of 0, in which case all progress happens via the first "free" key-value scan.
for (int scanLimit = 0; scanLimit <= maximumToScan * 2; scanLimit = 2 * scanLimit + 1) {
final Function<FDBQueriedRecord<Message>, Long> getRecNo = r -> {
TestRecords1Proto.MySimpleRecord.Builder record = TestRecords1Proto.MySimpleRecord.newBuilder();
record.mergeFrom(r.getRecord());
return record.getRecNo();
};
final ExecuteProperties.Builder properties = ExecuteProperties.newBuilder().setScannedRecordsLimit(scanLimit);
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
final List<Long> allAtOnce;
try (RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan)) {
allAtOnce = cursor.map(getRecNo).asList().get();
}
final List<Long> byContinuation = new ArrayList<>();
byte[] continuation = null;
do {
try (RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan, continuation, properties.build())) {
if (context.getTimer() != null) {
context.getTimer().reset();
}
RecordCursorResult<FDBQueriedRecord<Message>> result;
while ((result = cursor.getNext()).hasNext()) {
byContinuation.add(getRecNo.apply(result.get()));
}
continuation = result.getContinuation().toBytes();
int overrun = BaseCursorCountVisitor.getCount(cursor);
Optional<Integer> recordScanned = getRecordScanned(context);
if (recordScanned.isPresent()) {
assertThat(recordScanned.get(), lessThanOrEqualTo(Math.min(scanLimit + overrun, maximumToScan)));
}
}
} while (continuation != null);
assertEquals(allAtOnce, byContinuation);
}
}
}
Aggregations