use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class VersionIndexTest method saveLoadWithVersion.
@ParameterizedTest(name = "saveLoadWithVersion [formatVersion = {0}, splitLongRecords = {1}]")
@MethodSource("formatVersionArguments")
@SuppressWarnings("try")
public void saveLoadWithVersion(int testFormatVersion, boolean testSplitLongRecords) {
formatVersion = testFormatVersion;
splitLongRecords = testSplitLongRecords;
MySimpleRecord record1 = MySimpleRecord.newBuilder().setRecNo(1066L).setNumValue2(42).build();
TestRecords1Proto.MyOtherRecord record2 = TestRecords1Proto.MyOtherRecord.newBuilder().setRecNo(1776L).setNumValue2(1729).build();
byte[] versionstamp;
try (FDBRecordContext context = openContext(simpleVersionHook)) {
recordStore.saveRecord(record1);
recordStore.saveRecord(record2);
context.commit();
versionstamp = context.getVersionStamp();
assertEquals(2, context.claimLocalVersion());
}
FDBRecordVersion version1;
FDBRecordVersion version2;
try (FDBRecordContext context = openContext(simpleVersionHook)) {
FDBStoredRecord<Message> stored1 = recordStore.loadRecord(Tuple.from(1066L));
assertTrue(stored1.hasVersion());
version1 = stored1.getVersion();
assertNotNull(version1);
assertTrue(version1.isComplete());
assertArrayEquals(versionstamp, version1.getGlobalVersion());
assertEquals(0, version1.getLocalVersion());
FDBStoredRecord<Message> stored2 = recordStore.loadRecord(Tuple.from(1776L));
assertTrue(stored2.hasVersion());
version2 = stored2.getVersion();
assertNotNull(version2);
assertTrue(version2.isComplete());
assertArrayEquals(versionstamp, version2.getGlobalVersion());
assertEquals(1, version2.getLocalVersion());
}
// Saving them again should change the versions.
try (FDBRecordContext context = openContext(simpleVersionHook)) {
recordStore.saveRecord(record1);
recordStore.saveRecord(record2);
context.commit();
versionstamp = context.getVersionStamp();
assertEquals(2, context.claimLocalVersion());
}
try (FDBRecordContext context = openContext(simpleVersionHook)) {
FDBStoredRecord<Message> stored1 = recordStore.loadRecord(Tuple.from(1066L));
assertTrue(stored1.hasVersion());
FDBRecordVersion version1Prime = stored1.getVersion();
assertNotNull(version1Prime);
assertTrue(version1Prime.isComplete());
assertEquals(0, version1Prime.getLocalVersion());
assertArrayEquals(versionstamp, version1Prime.getGlobalVersion());
assertFalse(Arrays.equals(version1.getGlobalVersion(), version1Prime.getGlobalVersion()));
assertNotEquals(version1, version1Prime);
FDBStoredRecord<Message> stored2 = recordStore.loadRecord(Tuple.from(1776L));
assertTrue(stored1.hasVersion());
FDBRecordVersion version2Prime = stored2.getVersion();
assertNotNull(version2Prime);
assertTrue(version2Prime.isComplete());
assertEquals(1, version2Prime.getLocalVersion());
assertArrayEquals(versionstamp, version2Prime.getGlobalVersion());
assertFalse(Arrays.equals(version2.getGlobalVersion(), version2Prime.getGlobalVersion()));
assertNotEquals(version2, version2Prime);
}
// Saving them again with an explicit version should keep the version the same.
try (FDBRecordContext context = openContext(simpleVersionHook)) {
recordStore.saveRecord(record1, version1);
recordStore.saveRecord(record2, version2);
context.commit();
versionstamp = context.getVersionStamp();
assertEquals(0, context.claimLocalVersion());
}
try (FDBRecordContext context = openContext(simpleVersionHook)) {
FDBStoredRecord<Message> stored1 = recordStore.loadRecord(Tuple.from(1066L));
assertTrue(stored1.hasVersion());
FDBRecordVersion version1Prime = stored1.getVersion();
assertNotNull(version1Prime);
assertNotSame(version1, version1Prime);
assertTrue(version1Prime.isComplete());
assertEquals(0, version1Prime.getLocalVersion());
assertFalse(Arrays.equals(versionstamp, version1Prime.getGlobalVersion()));
assertArrayEquals(version1.getGlobalVersion(), version1Prime.getGlobalVersion());
assertEquals(version1, version1Prime);
FDBStoredRecord<Message> stored2 = recordStore.loadRecord(Tuple.from(1776L));
assertTrue(stored2.hasVersion());
FDBRecordVersion version2Prime = stored2.getVersion();
assertNotNull(version2Prime);
assertNotSame(version2, version2Prime);
assertTrue(version2Prime.isComplete());
assertEquals(1, version2Prime.getLocalVersion());
assertFalse(Arrays.equals(versionstamp, version2Prime.getGlobalVersion()));
assertArrayEquals(version2.getGlobalVersion(), version2Prime.getGlobalVersion());
assertEquals(version2, version2Prime);
}
// Saving new records with an explicit NO_VERSION behavior, should set the new records version to null
MySimpleRecord record3 = MySimpleRecord.newBuilder().setRecNo(3066L).setNumValue2(42).build();
TestRecords1Proto.MyOtherRecord record4 = TestRecords1Proto.MyOtherRecord.newBuilder().setRecNo(4776L).setNumValue2(1729).build();
try (FDBRecordContext context = openContext(simpleVersionHook)) {
assertThrows(RecordCoreException.class, () -> {
recordStore.saveRecord(record3, version2, FDBRecordStoreBase.VersionstampSaveBehavior.NO_VERSION);
fail("Save record with NO_VERSION behavior should throw an exception if the supplied version isn't null");
});
}
try (FDBRecordContext context = openContext(simpleVersionHook)) {
recordStore.saveRecord(record3, null, FDBRecordStoreBase.VersionstampSaveBehavior.NO_VERSION);
recordStore.saveRecord(record4, null, FDBRecordStoreBase.VersionstampSaveBehavior.NO_VERSION);
context.commit();
}
try (FDBRecordContext context = openContext(simpleVersionHook)) {
FDBStoredRecord<Message> stored3 = recordStore.loadRecord(Tuple.from(3066L));
assertFalse(stored3.hasVersion());
FDBStoredRecord<Message> stored4 = recordStore.loadRecord(Tuple.from(4776L));
assertFalse(stored4.hasVersion());
}
// default behavior in this case).
try (FDBRecordContext context = openContext(simpleVersionHook)) {
recordStore.saveRecord(record3, null, FDBRecordStoreBase.VersionstampSaveBehavior.WITH_VERSION);
recordStore.saveRecord(record4, null, FDBRecordStoreBase.VersionstampSaveBehavior.WITH_VERSION);
context.commit();
versionstamp = context.getVersionStamp();
assertEquals(2, context.claimLocalVersion());
}
try (FDBRecordContext context = openContext(simpleVersionHook)) {
FDBStoredRecord<Message> stored3 = recordStore.loadRecord(Tuple.from(3066L));
assertTrue(stored3.hasVersion());
FDBRecordVersion version3Prime = stored3.getVersion();
assertNotNull(version3Prime);
assertTrue(version3Prime.isComplete());
assertEquals(0, version3Prime.getLocalVersion());
assertArrayEquals(versionstamp, version3Prime.getGlobalVersion());
FDBStoredRecord<Message> stored4 = recordStore.loadRecord(Tuple.from(4776L));
assertTrue(stored4.hasVersion());
FDBRecordVersion version4Prime = stored4.getVersion();
assertNotNull(version4Prime);
assertTrue(version4Prime.isComplete());
assertEquals(1, version4Prime.getLocalVersion());
assertArrayEquals(versionstamp, version4Prime.getGlobalVersion());
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class TextIndexTest method performQueryWithIndexScan.
@Nonnull
private Set<Long> performQueryWithIndexScan(@Nonnull RecordMetaDataHook hook, @Nonnull Index index, @Nonnull QueryComponent filter) throws Exception {
final ExecuteProperties executeProperties = ExecuteProperties.newBuilder().setTimeLimit(3000).build();
final RecordQuery query = RecordQuery.newBuilder().setRecordType(SIMPLE_DOC).setRequiredResults(Collections.singletonList(field("doc_id"))).setFilter(filter).build();
Set<Long> results = new HashSet<>();
RecordQueryPlan plan;
byte[] continuation;
try (FDBRecordContext context = openContext()) {
openRecordStore(context, hook);
RecordQueryPlanner planner = new RecordQueryPlanner(recordStore.getRecordMetaData(), recordStore.getRecordStoreState());
plan = planner.plan(query);
assertThat(filter, instanceOf(FieldWithComparison.class));
FieldWithComparison fieldFilter = (FieldWithComparison) filter;
if (fieldFilter.getComparison() instanceof Comparisons.TextContainsAllPrefixesComparison && ((Comparisons.TextContainsAllPrefixesComparison) fieldFilter.getComparison()).isStrict()) {
// Strict field field comparisons cannot be covering
assertThat(plan, descendant(textIndexScan(indexName(index.getName()))));
} else {
assertThat(plan, descendant(coveringIndexScan(textIndexScan(indexName(index.getName())))));
}
try (RecordCursor<Long> cursor = recordStore.executeQuery(plan, null, executeProperties).map(record -> record.getPrimaryKey().getLong(0))) {
cursor.forEach(results::add).get();
continuation = cursor.getNext().getContinuation().toBytes();
}
}
while (continuation != null) {
try (FDBRecordContext context = openContext()) {
openRecordStore(context, hook);
try (RecordCursor<Long> cursor = recordStore.executeQuery(plan, continuation, executeProperties).map(record -> record.getPrimaryKey().getLong(0))) {
cursor.forEach(results::add).get();
continuation = cursor.getNext().getContinuation().toBytes();
}
}
}
return results;
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class TextIndexTest method scanWithSkip.
public void scanWithSkip(@Nonnull Index index, @Nonnull String token, int skip, int limit, boolean reverse) throws Exception {
try (FDBRecordContext context = openContext()) {
openRecordStore(context);
final List<IndexEntry> fullResults = scanIndex(recordStore, index, TupleRange.allOf(Tuple.from(token)));
validateSorted(fullResults);
final ScanProperties scanProperties = ExecuteProperties.newBuilder().setReturnedRowLimit(limit).setSkip(skip).build().asScanProperties(reverse);
final RecordCursor<IndexEntry> cursor = recordStore.scanIndex(index, BY_TEXT_TOKEN, TupleRange.allOf(Tuple.from(token)), null, scanProperties);
List<IndexEntry> scanResults = cursor.asList().get();
RecordCursorResult<IndexEntry> noNextResult = cursor.getNext();
assertThat(noNextResult.hasNext(), is(false));
assertEquals((limit != ReadTransaction.ROW_LIMIT_UNLIMITED && scanResults.size() == limit) ? RETURN_LIMIT_REACHED : SOURCE_EXHAUSTED, noNextResult.getNoNextReason());
List<IndexEntry> expectedResults;
if (reverse) {
scanResults = new ArrayList<>(scanResults);
Collections.reverse(scanResults);
expectedResults = fullResults.subList((limit == ReadTransaction.ROW_LIMIT_UNLIMITED || limit == Integer.MAX_VALUE) ? 0 : Math.max(0, fullResults.size() - skip - limit), Math.max(0, fullResults.size() - skip));
} else {
expectedResults = fullResults.subList(Math.min(fullResults.size(), skip), (limit == ReadTransaction.ROW_LIMIT_UNLIMITED || limit == Integer.MAX_VALUE) ? fullResults.size() : Math.min(fullResults.size(), skip + limit));
}
assertEquals(expectedResults, scanResults);
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class TextIndexTest method scanMultipleWithScanRecordLimits.
private void scanMultipleWithScanRecordLimits(@Nonnull Index index, @Nonnull List<String> tokens, int scanRecordLimit, boolean reverse) throws Exception {
try (FDBRecordContext context = openContext()) {
openRecordStore(context);
ScanProperties scanProperties = ExecuteProperties.newBuilder().setScannedRecordsLimit(scanRecordLimit).build().asScanProperties(reverse);
List<RecordCursor<IndexEntry>> cursors = tokens.stream().map(token -> recordStore.scanIndex(index, BY_TEXT_TOKEN, TupleRange.allOf(Tuple.from(token)), null, scanProperties)).collect(Collectors.toList());
int cursorIndex = 0;
int retrieved = 0;
while (!cursors.isEmpty()) {
RecordCursor<IndexEntry> cursor = cursors.get(cursorIndex);
RecordCursorResult<IndexEntry> result = cursor.getNext();
if (result.hasNext()) {
retrieved++;
cursorIndex = (cursorIndex + 1) % cursors.size();
} else {
if (!result.getNoNextReason().isSourceExhausted()) {
assertEquals(SCAN_LIMIT_REACHED, result.getNoNextReason());
}
cursors.remove(cursorIndex);
if (cursorIndex == cursors.size()) {
cursorIndex = 0;
}
}
}
// With the order that they are retrieved, the maximum value is the scanRecordLimit
// or the number of tokens.
assertThat(retrieved, lessThanOrEqualTo(Math.max(scanRecordLimit, tokens.size())));
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext in project fdb-record-layer by FoundationDB.
the class TextIndexTest method queryDocumentsWithScanLimit.
@Test
public void queryDocumentsWithScanLimit() throws Exception {
// Load a big (ish) data set
final int recordCount = 100;
final int batchSize = 10;
for (int i = 0; i < recordCount; i += batchSize) {
try (FDBRecordContext context = openContext()) {
openRecordStore(context);
for (int j = 0; j < batchSize; j++) {
SimpleDocument document = SimpleDocument.newBuilder().setDocId(i + j).setText((i + j) % 2 == 0 ? "some" : "text").build();
recordStore.saveRecord(document);
}
commit(context);
}
}
try (FDBRecordContext context = openContext()) {
openRecordStore(context);
RecordQuery query = RecordQuery.newBuilder().setRecordType(SIMPLE_DOC).setFilter(Query.field("text").text().containsAll("some text")).build();
RecordQueryPlan plan = planner.plan(query);
boolean done = false;
int totalKeysLoaded = 0;
byte[] continuation = null;
while (!done) {
final int priorKeysLoaded = getLoadTextEntryCount(recordStore);
ExecuteProperties executeProperties = ExecuteProperties.newBuilder().setScannedRecordsLimit(50).build();
RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan, continuation, executeProperties);
assertEquals(Collections.emptyList(), cursor.asList().get());
RecordCursorResult<FDBQueriedRecord<Message>> noNextResult = cursor.getNext();
assertThat(noNextResult.hasNext(), is(false));
final int newKeysLoaded = getLoadTextEntryCount(recordStore);
totalKeysLoaded += newKeysLoaded - priorKeysLoaded;
if (!noNextResult.getNoNextReason().isSourceExhausted()) {
assertEquals(50, newKeysLoaded - priorKeysLoaded);
assertEquals(RecordCursor.NoNextReason.SCAN_LIMIT_REACHED, noNextResult.getNoNextReason());
assertNotNull(noNextResult.getContinuation().toBytes());
} else {
assertNull(noNextResult.getContinuation().toBytes());
done = true;
}
continuation = noNextResult.getContinuation().toBytes();
}
assertEquals(recordCount + 2, totalKeysLoaded);
commit(context);
}
}
Aggregations