use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class FDBLuceneQueryTest method simpleLuceneScans.
@ParameterizedTest
@BooleanSource
public void simpleLuceneScans(boolean shouldDeferFetch) throws Exception {
initializeFlat();
try (FDBRecordContext context = openContext()) {
openRecordStore(context);
final QueryComponent filter1 = new LuceneQueryComponent("civil blood makes civil hands unclean", Lists.newArrayList());
// Query for full records
RecordQuery query = RecordQuery.newBuilder().setRecordType(TextIndexTestUtils.SIMPLE_DOC).setFilter(filter1).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
Matcher<RecordQueryPlan> matcher = indexScan(allOf(indexScan("Complex$text_index"), indexScanType(IndexScanType.BY_LUCENE), bounds(hasTupleString("[[civil blood makes civil hands unclean],[civil blood makes civil hands unclean]]"))));
RecordQueryPlan plan = planner.plan(query);
// assertThat(plan, matcher);
RecordCursor<FDBQueriedRecord<Message>> fdbQueriedRecordRecordCursor = recordStore.executeQuery(plan);
RecordCursor<Tuple> map = fdbQueriedRecordRecordCursor.map(FDBQueriedRecord::getPrimaryKey);
List<Long> primaryKeys = map.map(t -> t.getLong(0)).asList().get();
assertEquals(ImmutableSet.of(2L, 4L), ImmutableSet.copyOf(primaryKeys));
}
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class FDBLuceneQueryTest method testThenExpressionBeforeFieldExpression.
@ParameterizedTest
@BooleanSource
public void testThenExpressionBeforeFieldExpression(boolean shouldDeferFetch) throws Exception {
initializeNestedWithField();
try (FDBRecordContext context = openContext()) {
openRecordStore(context);
final QueryComponent filter1 = new LuceneQueryComponent("*:*", Lists.newArrayList("doc_id"));
RecordQuery query = RecordQuery.newBuilder().setRecordType(MAP_DOC).setFilter(filter1).build();
setDeferFetchAfterUnionAndIntersection(shouldDeferFetch);
RecordQueryPlan plan = planner.plan(query);
RecordCursor<FDBQueriedRecord<Message>> fdbQueriedRecordRecordCursor = recordStore.executeQuery(plan);
RecordCursor<Tuple> map = fdbQueriedRecordRecordCursor.map(FDBQueriedRecord::getPrimaryKey);
List<Long> primaryKeys = map.map(t -> t.getLong(0)).asList().get();
assertEquals(ImmutableSet.of(0L, 1L, 2L), ImmutableSet.copyOf(primaryKeys));
}
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreTest method prefixPrimaryKeysWithNullByteAfterPrefix.
/**
* If there are two primary keys that overlap in the just the right way, then one can have the representation
* of one record's primary key be a strict prefix of the other record's. With older versions of the Record Layer,
* this could lead to problems where attempting to load the record with the shorter key would also read data for
* the record with the longer key. See <a href="https://github.com/FoundationDB/fdb-record-layer/issues/782">Issue #782</a>.
*
* <p>
* This test is parameterized by format version because the fix involves being more particular about the range that
* is scanned. In particular, the scan range is now only over those keys which are strict prefixes of the primary
* key. This is fine as long as there aren't any data stored at that key. Prior to {@link FDBRecordStore#SAVE_UNSPLIT_WITH_SUFFIX_FORMAT_VERSION},
* there could be data in that key was not true if {@code splitLongRecords} was {@code false}. Parameterizing here
* tests those older configurations.
* </p>
*
* @param formatVersion format version to use when running the test
* @param splitLongRecords whether the test should split long records or not
*/
@ParameterizedTest(name = "prefixPrimaryKeysWithNullByteAfterPrefix [formatVersion = {0}, splitLongRecords = {1}]")
@MethodSource("formatVersionAndSplitArgs")
public void prefixPrimaryKeysWithNullByteAfterPrefix(int formatVersion, boolean splitLongRecords) throws Exception {
final RecordMetaDataHook hook = metaData -> {
metaData.setSplitLongRecords(splitLongRecords);
metaData.getRecordType("MySimpleRecord").setPrimaryKey(field("str_value_indexed"));
};
final FDBRecordStore.Builder storeBuilder;
// The primary key for record1 is a prefix of the primary key for record2, and the first byte in record2's primary
// key is a null byte. Because FDB's Tuple layer null terminates its representation of strings, this means that
// the keys used to store record1 forms a prefix of the keys storing record2. However, the null byte should be
// escaped in such a way that it is possible to read only the keys for record1. This is necessary to properly load
// the record by primary key.
final TestRecords1Proto.MySimpleRecord record1 = TestRecords1Proto.MySimpleRecord.newBuilder().setStrValueIndexed("foo").setNumValue3Indexed(1066).build();
final TestRecords1Proto.MySimpleRecord record2 = TestRecords1Proto.MySimpleRecord.newBuilder().setStrValueIndexed("foo\0bar").setNumValue3Indexed(1415).build();
// Save the two records
try (FDBRecordContext context = openContext()) {
uncheckedOpenSimpleRecordStore(context, hook);
storeBuilder = recordStore.asBuilder().setFormatVersion(formatVersion);
final FDBRecordStore store = storeBuilder.create();
store.saveRecord(record1);
store.saveRecord(record2);
commit(context);
}
// Load by scanning records
try (FDBRecordContext context = openContext()) {
final FDBRecordStore store = storeBuilder.setContext(context).open();
final List<FDBStoredRecord<Message>> records = store.scanRecords(null, ScanProperties.FORWARD_SCAN).asList().get();
assertThat(records, hasSize(2));
assertEquals(record1, records.get(0).getRecord());
assertEquals(record2, records.get(1).getRecord());
}
// Load by primary key
try (FDBRecordContext context = openContext()) {
final FDBRecordStore store = storeBuilder.setContext(context).open();
FDBStoredRecord<Message> storedRecord1 = store.loadRecord(Tuple.from(record1.getStrValueIndexed()));
assertNotNull(storedRecord1, "record1 was missing");
assertEquals(record1, storedRecord1.getRecord());
FDBStoredRecord<Message> storedRecord2 = store.loadRecord(Tuple.from(record2.getStrValueIndexed()));
assertNotNull(storedRecord2, "record2 was missing");
assertEquals(record2, storedRecord2.getRecord());
}
// Load by query
try (FDBRecordContext context = openContext()) {
final FDBRecordStore store = storeBuilder.setContext(context).open();
final RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_3_indexed").equalsParameter("num")).build();
final RecordQueryPlan plan = store.planQuery(query);
assertThat(plan, indexScan(allOf(indexName("MySimpleRecord$num_value_3_indexed"), bounds(hasTupleString("[EQUALS $num]")))));
// Record 1
List<FDBQueriedRecord<Message>> record1List = plan.execute(store, EvaluationContext.forBinding("num", 1066)).asList().get();
assertThat(record1List, hasSize(1));
FDBQueriedRecord<Message> queriedRecord1 = record1List.get(0);
assertEquals(record1, queriedRecord1.getRecord());
// Record 2
List<FDBQueriedRecord<Message>> record2List = plan.execute(store, EvaluationContext.forBinding("num", 1415)).asList().get();
assertThat(record2List, hasSize(1));
FDBQueriedRecord<Message> queriedRecord2 = record2List.get(0);
assertEquals(record2, queriedRecord2.getRecord());
}
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreEstimateSizeTest method estimateInTwoRanges.
@Test
public void estimateInTwoRanges() throws Exception {
final int recordCount = 500;
populateStore(recordCount, recordCount * 5_000);
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
long estimatedRecordSize = estimateRecordsSize(recordStore);
final Tuple halfWayTuple = Tuple.from(recordCount / 2);
final TupleRange firstHalf = new TupleRange(null, halfWayTuple, EndpointType.TREE_START, EndpointType.RANGE_EXCLUSIVE);
long estimatedFirstHalf = estimateRecordsSize(recordStore, firstHalf);
final TupleRange secondHalf = new TupleRange(halfWayTuple, null, EndpointType.RANGE_INCLUSIVE, EndpointType.TREE_END);
long estimatedSecondHalf = estimateRecordsSize(recordStore, secondHalf);
LOGGER.info(KeyValueLogMessage.of("estimated both halves of records", "estimated_records_size", estimatedRecordSize, "estimated_first_half_size", estimatedFirstHalf, "estimated_second_half_size", estimatedSecondHalf));
assertEquals(estimatedFirstHalf + estimatedSecondHalf, estimatedRecordSize, "expected first half size (" + estimatedFirstHalf + ") and second half size (" + estimatedSecondHalf + ") to match full size");
commit(context);
}
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class FunctionKeyIndexTest method testFanOutFunction.
@Test
public void testFanOutFunction() throws Exception {
Index index = new Index("str_fields_index", function("indexStrFields"), IndexTypes.VALUE);
Records records = Records.create();
records.add(0, "a,b,c");
for (int i = 1; i < 10; i++) {
records.add(i, "a,b,c_" + i, "a_" + i + ",b,c", "a,b_" + i + ",c");
}
saveRecords(records, index);
try (FDBRecordContext context = openContext()) {
openRecordStore(context, index);
List<IndexEntry> keyValues = getIndexKeyValues(recordStore, index, IndexScanType.BY_VALUE);
int count = 0;
for (IndexEntry kv : keyValues) {
Tuple key = kv.getKey();
assertEquals(4, key.size(), "Wrong key length");
assertTrue(key.getString(0).startsWith("a"), "Invalid value in first key element: " + key.get(0));
assertTrue(key.getString(1).startsWith("b"), "Invalid value in second key element: " + key.get(1));
assertTrue(key.getString(2).startsWith("c"), "Invalid value in third key element: " + key.get(2));
++count;
}
assertEquals(28, count, "Too few index keys");
}
}
Aggregations