Search in sources :

Example 71 with Tuple

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));
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) LuceneQueryComponent(com.apple.foundationdb.record.query.expressions.LuceneQueryComponent) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) LuceneQueryComponent(com.apple.foundationdb.record.query.expressions.LuceneQueryComponent) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) Tuple(com.apple.foundationdb.tuple.Tuple) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) BooleanSource(com.apple.test.BooleanSource)

Example 72 with Tuple

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));
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) LuceneQueryComponent(com.apple.foundationdb.record.query.expressions.LuceneQueryComponent) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) LuceneQueryComponent(com.apple.foundationdb.record.query.expressions.LuceneQueryComponent) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) Tuple(com.apple.foundationdb.tuple.Tuple) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) BooleanSource(com.apple.test.BooleanSource)

Example 73 with Tuple

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());
    }
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) DescriptorProtos(com.google.protobuf.DescriptorProtos) DELETE_INDEX_ENTRY(com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer.Events.DELETE_INDEX_ENTRY) Arrays(java.util.Arrays) PlanMatchers.bounds(com.apple.foundationdb.record.query.plan.match.PlanMatchers.bounds) RecordCoreStorageException(com.apple.foundationdb.record.RecordCoreStorageException) ByteBuffer(java.nio.ByteBuffer) RecordSerializer(com.apple.foundationdb.record.provider.common.RecordSerializer) RecordSerializationException(com.apple.foundationdb.record.provider.common.RecordSerializationException) IndexScanType(com.apple.foundationdb.record.IndexScanType) Tuple(com.apple.foundationdb.tuple.Tuple) Range(com.apple.foundationdb.Range) FDBError(com.apple.foundationdb.FDBError) RecordCoreException(com.apple.foundationdb.record.RecordCoreException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Expressions.concatenateFields(com.apple.foundationdb.record.metadata.Key.Expressions.concatenateFields) RecordMetaDataProto(com.apple.foundationdb.record.RecordMetaDataProto) RecordMetaDataOptionsProto(com.apple.foundationdb.record.RecordMetaDataOptionsProto) Is.is(org.hamcrest.core.Is.is) Expressions.concat(com.apple.foundationdb.record.metadata.Key.Expressions.concat) Tag(org.junit.jupiter.api.Tag) MethodSource(org.junit.jupiter.params.provider.MethodSource) TestRecords7Proto(com.apple.foundationdb.record.TestRecords7Proto) ByteArrayUtil(com.apple.foundationdb.tuple.ByteArrayUtil) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) Matchers.allOf(org.hamcrest.Matchers.allOf) Set(java.util.Set) Collectors(java.util.stream.Collectors) TupleRange(com.apple.foundationdb.record.TupleRange) ByteString(com.google.protobuf.ByteString) Test(org.junit.jupiter.api.Test) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) KeySpacePath(com.apple.foundationdb.record.provider.foundationdb.keyspace.KeySpacePath) PlanMatchers.hasTupleString(com.apple.foundationdb.record.query.plan.match.PlanMatchers.hasTupleString) List(java.util.List) PlanMatchers.indexName(com.apple.foundationdb.record.query.plan.match.PlanMatchers.indexName) RecordMetaDataProvider(com.apple.foundationdb.record.RecordMetaDataProvider) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) Matchers.equalTo(org.hamcrest.Matchers.equalTo) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) IndexTypes(com.apple.foundationdb.record.metadata.IndexTypes) TestRecordsWithHeaderProto(com.apple.foundationdb.record.TestRecordsWithHeaderProto) Matchers.greaterThan(org.hamcrest.Matchers.greaterThan) Matchers.containsString(org.hamcrest.Matchers.containsString) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) Assertions.fail(org.junit.jupiter.api.Assertions.fail) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) TestNoUnionProto(com.apple.foundationdb.record.TestNoUnionProto) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) TestRecordsDuplicateUnionFields(com.apple.foundationdb.record.TestRecordsDuplicateUnionFields) DynamicMessage(com.google.protobuf.DynamicMessage) Descriptors(com.google.protobuf.Descriptors) PlanMatchers.indexScan(com.apple.foundationdb.record.query.plan.match.PlanMatchers.indexScan) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) CompletableFuture(java.util.concurrent.CompletableFuture) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Strings(com.google.common.base.Strings) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) ScanProperties(com.apple.foundationdb.record.ScanProperties) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) Matchers.lessThan(org.hamcrest.Matchers.lessThan) Assumptions.assumeTrue(org.junit.jupiter.api.Assumptions.assumeTrue) Matchers.hasSize(org.hamcrest.Matchers.hasSize) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Nonnull(javax.annotation.Nonnull) Expressions.field(com.apple.foundationdb.record.metadata.Key.Expressions.field) Nullable(javax.annotation.Nullable) Charsets(com.google.common.base.Charsets) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) Tags(com.apple.test.Tags) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) Assertions.assertSame(org.junit.jupiter.api.Assertions.assertSame) ExecutionException(java.util.concurrent.ExecutionException) Consumer(java.util.function.Consumer) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) TestRecordsImportProto(com.apple.foundationdb.record.TestRecordsImportProto) Index(com.apple.foundationdb.record.metadata.Index) FDBException(com.apple.foundationdb.FDBException) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) Collections(java.util.Collections) SAVE_INDEX_ENTRY(com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer.Events.SAVE_INDEX_ENTRY) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) DynamicMessage(com.google.protobuf.DynamicMessage) Message(com.google.protobuf.Message) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 74 with Tuple

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);
    }
}
Also used : TupleRange(com.apple.foundationdb.record.TupleRange) Tuple(com.apple.foundationdb.tuple.Tuple) Test(org.junit.jupiter.api.Test)

Example 75 with Tuple

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");
    }
}
Also used : IndexEntry(com.apple.foundationdb.record.IndexEntry) Index(com.apple.foundationdb.record.metadata.Index) Tuple(com.apple.foundationdb.tuple.Tuple) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Aggregations

Tuple (com.apple.foundationdb.tuple.Tuple)163 Nonnull (javax.annotation.Nonnull)80 List (java.util.List)66 Test (org.junit.jupiter.api.Test)66 TupleRange (com.apple.foundationdb.record.TupleRange)62 ArrayList (java.util.ArrayList)57 Message (com.google.protobuf.Message)56 Nullable (javax.annotation.Nullable)50 IndexEntry (com.apple.foundationdb.record.IndexEntry)48 Index (com.apple.foundationdb.record.metadata.Index)47 Subspace (com.apple.foundationdb.subspace.Subspace)47 CompletableFuture (java.util.concurrent.CompletableFuture)46 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)45 ScanProperties (com.apple.foundationdb.record.ScanProperties)43 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)42 AsyncUtil (com.apple.foundationdb.async.AsyncUtil)41 Collectors (java.util.stream.Collectors)41 Collections (java.util.Collections)40 Transaction (com.apple.foundationdb.Transaction)38 RecordCursor (com.apple.foundationdb.record.RecordCursor)38