Search in sources :

Example 26 with Key

use of com.apple.foundationdb.record.metadata.Key in project fdb-record-layer by FoundationDB.

the class FunctionKeyRecordTest method testCoveringIndexFunction.

@Test
public void testCoveringIndexFunction() throws Exception {
    // This index parses each entry of str_array_field of the form "X:Y:Z" and produces a keyWithValue
    // index of the form X -> (Y, Z).
    final Index index = new Index("covering", keyWithValue(function("regex", concat(field("str_array_field", KeyExpression.FanType.FanOut), value("(\\d+):(\\w+):(\\d+)"), value("LONG"), value("STRING"), value("LONG"))), 1));
    final RecordMetaDataHook hook = metadata -> {
        RecordTypeBuilder type = metadata.getRecordType("StringRecordId");
        type.setPrimaryKey(field("rec_id"));
        metadata.addIndex(type, index);
    };
    final BiFunction<Integer, Integer, String> makeId = (id1, id2) -> id1 + ":" + Character.toString((char) ('a' + id2)) + ":" + id2;
    // Create some records
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context, hook);
        for (int i = 0; i < 5; i++) {
            TestRecords8Proto.StringRecordId.Builder builder = TestRecords8Proto.StringRecordId.newBuilder().setRecId("record_" + i).setIntValue(i);
            for (int j = 0; j < 4; j++) {
                builder.addStrArrayField(makeId.apply((i * 4) + j, j));
            }
            recordStore.saveRecord(builder.build());
        }
        commit(context);
    }
    Function<FDBIndexedRecord<Message>, TestRecords8Proto.StringRecordId> validate = message -> {
        final Tuple key = message.getIndexEntry().getKey();
        final Tuple value = message.getIndexEntry().getValue();
        // Key is X,<record_id> where X is the first part of the str_array_field
        Assertions.assertEquals(2, key.size());
        // Value is the last two pieces of the str_array_field
        Assertions.assertEquals(2, value.size());
        // Check the record itself
        final TestRecords8Proto.StringRecordId record = TestRecords8Proto.StringRecordId.newBuilder().mergeFrom(message.getRecord()).build();
        // Get the portions of the key and the value that are needed to reconstruct the
        // full value that is supposed to be stored in the str_array_field.
        final int id1 = (int) key.getLong(0);
        final int id2 = (int) value.getLong(1);
        final int recordId = (id1 / 4);
        Assertions.assertEquals(recordId, record.getIntValue());
        Assertions.assertEquals("record_" + recordId, record.getRecId());
        Assertions.assertTrue(record.getStrArrayFieldList().contains(makeId.apply(id1, id2)), "str_array_field does not contain entry");
        Assertions.assertEquals(Character.toString((char) ('a' + id2)), value.getString(0));
        return record;
    };
    // let's just scan all of the records
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context, hook);
        List<FDBIndexedRecord<Message>> messages = recordStore.getRecordContext().asyncToSync(FDBStoreTimer.Waits.WAIT_SCAN_INDEX_RECORDS, recordStore.scanIndexRecords(index.getName(), IndexScanType.BY_VALUE, TupleRange.ALL, null, ScanProperties.FORWARD_SCAN).asList());
        Assertions.assertEquals(20, messages.size(), "Wrong record count");
        for (FDBIndexedRecord<Message> message : messages) {
            validate.apply(message);
        }
    }
    // Next, scan a subset of them based upon the first value of the covering index
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context, hook);
        TupleRange range = new TupleRange(Tuple.from(2), Tuple.from(4), EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_EXCLUSIVE);
        List<FDBIndexedRecord<Message>> messages = recordStore.getRecordContext().asyncToSync(FDBStoreTimer.Waits.WAIT_SCAN_INDEX_RECORDS, recordStore.scanIndexRecords(index.getName(), IndexScanType.BY_VALUE, range, null, ScanProperties.FORWARD_SCAN).asList());
        Assertions.assertEquals(2, messages.size(), "Wrong record count");
        for (FDBIndexedRecord<Message> message : messages) {
            TestRecords8Proto.StringRecordId record = validate.apply(message);
            Assertions.assertTrue(record.getIntValue() == 0, "Invalid int value");
        }
    }
}
Also used : RecordMetaData(com.apple.foundationdb.record.RecordMetaData) FunctionKeyExpression(com.apple.foundationdb.record.metadata.expressions.FunctionKeyExpression) LiteralKeyExpression(com.apple.foundationdb.record.metadata.expressions.LiteralKeyExpression) BiFunction(java.util.function.BiFunction) TestRecords8Proto(com.apple.foundationdb.record.TestRecords8Proto) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Function(java.util.function.Function) PlanHashable(com.apple.foundationdb.record.PlanHashable) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) IndexScanType(com.apple.foundationdb.record.IndexScanType) Tuple(com.apple.foundationdb.tuple.Tuple) Matcher(java.util.regex.Matcher) EndpointType(com.apple.foundationdb.record.EndpointType) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ScanProperties(com.apple.foundationdb.record.ScanProperties) Expressions.concat(com.apple.foundationdb.record.metadata.Key.Expressions.concat) Tag(org.junit.jupiter.api.Tag) Nonnull(javax.annotation.Nonnull) Expressions.field(com.apple.foundationdb.record.metadata.Key.Expressions.field) Nullable(javax.annotation.Nullable) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) PatternSyntaxException(java.util.regex.PatternSyntaxException) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) RecordTypeBuilder(com.apple.foundationdb.record.metadata.RecordTypeBuilder) Tags(com.apple.test.Tags) Expressions.keyWithValue(com.apple.foundationdb.record.metadata.Key.Expressions.keyWithValue) TupleRange(com.apple.foundationdb.record.TupleRange) Test(org.junit.jupiter.api.Test) List(java.util.List) Index(com.apple.foundationdb.record.metadata.Index) Expressions.value(com.apple.foundationdb.record.metadata.Key.Expressions.value) ObjectPlanHash(com.apple.foundationdb.record.ObjectPlanHash) AutoService(com.google.auto.service.AutoService) Message(com.google.protobuf.Message) Assertions(org.junit.jupiter.api.Assertions) RecordCursor(com.apple.foundationdb.record.RecordCursor) Expressions.function(com.apple.foundationdb.record.metadata.Key.Expressions.function) Pattern(java.util.regex.Pattern) ThenKeyExpression(com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression) Collections(java.util.Collections) Message(com.google.protobuf.Message) Index(com.apple.foundationdb.record.metadata.Index) RecordTypeBuilder(com.apple.foundationdb.record.metadata.RecordTypeBuilder) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TestRecords8Proto(com.apple.foundationdb.record.TestRecords8Proto) TupleRange(com.apple.foundationdb.record.TupleRange) Tuple(com.apple.foundationdb.tuple.Tuple) Test(org.junit.jupiter.api.Test)

Example 27 with Key

use of com.apple.foundationdb.record.metadata.Key in project fdb-record-layer by FoundationDB.

the class KeyComparisonsTest method keyComparator.

@Test
@Tag(Tags.Slow)
public void keyComparator() {
    Random r = new Random(0x5ca1ab1e);
    // Type 1: Integers.
    List<Key.Evaluated> intKeys = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        intKeys.add(Key.Evaluated.scalar(r.nextInt()));
    }
    intKeys.add(Key.Evaluated.NULL);
    testKeyComparator(intKeys);
    // Type 2: Int-Strings
    List<Key.Evaluated> intStringKeys = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        intStringKeys.add(Key.Evaluated.concatenate(r.nextInt(5), randomString(r)));
    }
    intStringKeys.add(Key.Evaluated.NULL);
    testKeyComparator(intStringKeys);
    // Type 3: Int-String lists
    List<Key.Evaluated> intStringListKeys = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        int length = (int) (Math.abs(r.nextGaussian() + 0.2) * 10);
        int first = r.nextInt(5);
        List<String> list = new ArrayList<>();
        for (int j = 0; j < length; j++) {
            list.add(randomString(r));
            if (r.nextDouble() < 0.4) {
                intStringListKeys.add(Key.Evaluated.concatenate(first, new ArrayList<>(list)));
            }
        }
        intStringListKeys.add(Key.Evaluated.concatenate(first, list));
    }
    intStringListKeys.add(Key.Evaluated.NULL);
    testKeyComparator(intStringListKeys);
    // Type 4: Int-Byte arrays
    List<Key.Evaluated> intByteArraysKeys = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        int length = (int) (Math.abs(r.nextGaussian() + 0.2) * 10);
        byte[] arr = new byte[length];
        r.nextBytes(arr);
        intByteArraysKeys.add(Key.Evaluated.concatenate(r.nextInt(5), arr));
    }
    intByteArraysKeys.add(Key.Evaluated.NULL);
    testKeyComparator(intByteArraysKeys);
    // Type 5: Mix of ints and int byte arrays.
    List<Key.Evaluated> mixedKeys = new ArrayList<>();
    mixedKeys.addAll(intKeys);
    mixedKeys.addAll(intByteArraysKeys);
    for (Key.Evaluated key : intByteArraysKeys) {
        List<Object> list = key.toList();
        if (list.size() > 0) {
            mixedKeys.add(Key.Evaluated.scalar(list.get(0)));
        }
    }
    testKeyComparator(mixedKeys);
}
Also used : Random(java.util.Random) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) Test(org.junit.jupiter.api.Test) Tag(org.junit.jupiter.api.Tag)

Example 28 with Key

use of com.apple.foundationdb.record.metadata.Key in project fdb-record-layer by FoundationDB.

the class FDBCoveringIndexQueryTest method coveringMultiValue.

/**
 * Verify that an index can be covering if some of the required fields are in the value part of the index.
 */
@DualPlannerTest
void coveringMultiValue() throws Exception {
    RecordMetaDataHook hook = metaData -> {
        metaData.removeIndex("MySimpleRecord$num_value_unique");
        metaData.addIndex("MySimpleRecord", new Index("multi_index_value", field("num_value_unique"), field("num_value_2"), IndexTypes.VALUE, IndexOptions.UNIQUE_OPTIONS));
    };
    complexQuerySetup(hook);
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("num_value_unique").greaterThan(990)).setSort(field("num_value_unique")).setRequiredResults(Arrays.asList(field("num_value_unique"), field("num_value_2"))).build();
    // Covering(Index(multi_index_value ([990],>) -> [num_value_2: VALUE[0], num_value_unique: KEY[0], rec_no: KEY[1]])
    RecordQueryPlan plan = planner.plan(query);
    final BindingMatcher<? extends RecordQueryPlan> planMatcher = coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("multi_index_value")).and(scanComparisons(range("([990],>")))));
    assertMatchesExactly(plan, planMatcher);
    assertEquals(-782505942, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
    assertEquals(450250048, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
    assertEquals(368845640, 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).asIterator()) {
            while (cursor.hasNext()) {
                FDBQueriedRecord<Message> rec = cursor.next();
                TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
                myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
                assertTrue(myrec.getNumValueUnique() > 990);
                assertEquals(myrec.getNumValue2(), (999 - i) % 3);
                i++;
            }
        }
        assertEquals(10, i);
        assertDiscardedNone(context);
    }
}
Also used : RecordQueryPlanMatchers.coveringIndexPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.coveringIndexPlan) Arrays(java.util.Arrays) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQueryPlanMatchers.predicates(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicates) Disabled(org.junit.jupiter.api.Disabled) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) TestHelpers.assertDiscardedNone(com.apple.foundationdb.record.TestHelpers.assertDiscardedNone) RecordQueryPlanMatchers.fetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.fetchFromPartialRecordPlan) Pair(org.apache.commons.lang3.tuple.Pair) ListMatcher.only(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.only) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) Expressions.concatenateFields(com.apple.foundationdb.record.metadata.Key.Expressions.concatenateFields) RecordQueryPlanMatchers.indexName(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexName) Expressions.concat(com.apple.foundationdb.record.metadata.Key.Expressions.concat) Tag(org.junit.jupiter.api.Tag) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ImmutableSet(com.google.common.collect.ImmutableSet) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) IndexOptions(com.apple.foundationdb.record.metadata.IndexOptions) Expressions.keyWithValue(com.apple.foundationdb.record.metadata.Key.Expressions.keyWithValue) Matchers.startsWith(org.hamcrest.Matchers.startsWith) Test(org.junit.jupiter.api.Test) Objects(java.util.Objects) List(java.util.List) ScanComparisons.range(com.apple.foundationdb.record.query.plan.ScanComparisons.range) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) 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.is(org.hamcrest.Matchers.is) RecordQueryPlanMatchers.predicatesFilterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicatesFilterPlan) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) RecordQueryPlanMatchers.indexPlanOf(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexPlanOf) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) PrimitiveMatchers.equalsObject(com.apple.foundationdb.record.query.plan.temp.matchers.PrimitiveMatchers.equalsObject) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) PlanHashable(com.apple.foundationdb.record.PlanHashable) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) PlannerRuleSet(com.apple.foundationdb.record.query.plan.temp.PlannerRuleSet) ImmutableList(com.google.common.collect.ImmutableList) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) Matchers.lessThan(org.hamcrest.Matchers.lessThan) RecordQueryPlanMatchers.scanComparisons(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.scanComparisons) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Expressions.field(com.apple.foundationdb.record.metadata.Key.Expressions.field) ScanComparisons.unbounded(com.apple.foundationdb.record.query.plan.ScanComparisons.unbounded) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) Tags(com.apple.test.Tags) QueryPredicateMatchers.valuePredicate(com.apple.foundationdb.record.query.plan.temp.matchers.QueryPredicateMatchers.valuePredicate) RecordQueryPlanMatchers.queryComponents(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.queryComponents) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) RecordQueryPlanMatchers.filterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.filterPlan) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) Index(com.apple.foundationdb.record.metadata.Index) RecordQueryPlanMatchers.indexPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexPlan) Message(com.google.protobuf.Message) ListMatcher.exactly(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.exactly) Collections(java.util.Collections) ValueMatchers.fieldValue(com.apple.foundationdb.record.query.plan.temp.matchers.ValueMatchers.fieldValue) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Message(com.google.protobuf.Message) Index(com.apple.foundationdb.record.metadata.Index) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQuery(com.apple.foundationdb.record.query.RecordQuery)

Example 29 with Key

use of com.apple.foundationdb.record.metadata.Key in project fdb-record-layer by FoundationDB.

the class FDBCoveringIndexQueryTest method coveringWithAdditionalFilter.

/**
 * Verify that a filter not satisfied by the index scan itself but using fields present in the index
 * can still allow a covering scan with the filter on the partial records.
 */
@DualPlannerTest
void coveringWithAdditionalFilter() throws Exception {
    RecordMetaDataHook hook = metaData -> {
        metaData.removeIndex("MySimpleRecord$num_value_3_indexed");
        metaData.addIndex("MySimpleRecord", new Index("multi_index", "num_value_3_indexed", "num_value_2"));
    };
    complexQuerySetup(hook);
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.and(Query.field("num_value_3_indexed").lessThan(1), Query.field("num_value_2").lessThan(2))).setRequiredResults(Collections.singletonList(field("num_value_3_indexed"))).build();
    // Covering(Index(multi_index ([null],[1])) -> [num_value_2: KEY[1], num_value_3_indexed: KEY[0], rec_no: KEY[2]]) | num_value_2 LESS_THAN 2
    RecordQueryPlan plan = planner.plan(query);
    if (planner instanceof RecordQueryPlanner) {
        final BindingMatcher<? extends RecordQueryPlan> planMatcher = filterPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("multi_index")).and(scanComparisons(range("([null],[1])")))))).where(queryComponents(exactly(equalsObject(Query.field("num_value_2").lessThan(2)))));
        assertMatchesExactly(plan, planMatcher);
        assertEquals(-1374002128, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(1359983418, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-1492450855, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    } else {
        final BindingMatcher<? extends RecordQueryPlan> planMatcher = predicatesFilterPlan(coveringIndexPlan().where(indexPlanOf(indexPlan().where(indexName("multi_index")).and(scanComparisons(range("([null],[1])")))))).where(predicates(only(valuePredicate(fieldValue("num_value_2"), new Comparisons.SimpleComparison(Comparisons.Type.LESS_THAN, 2)))));
        assertMatchesExactly(plan, planMatcher);
        assertEquals(762957369, plan.planHash(PlanHashable.PlanHashKind.LEGACY));
        assertEquals(-2135370744, plan.planHash(PlanHashable.PlanHashKind.FOR_CONTINUATION));
        assertEquals(-692837721, plan.planHash(PlanHashable.PlanHashKind.STRUCTURAL_WITHOUT_LITERALS));
    }
}
Also used : RecordQueryPlanMatchers.coveringIndexPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.coveringIndexPlan) Arrays(java.util.Arrays) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQueryPlanMatchers.predicates(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicates) Disabled(org.junit.jupiter.api.Disabled) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) TestHelpers.assertDiscardedNone(com.apple.foundationdb.record.TestHelpers.assertDiscardedNone) RecordQueryPlanMatchers.fetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.fetchFromPartialRecordPlan) Pair(org.apache.commons.lang3.tuple.Pair) ListMatcher.only(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.only) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) Expressions.concatenateFields(com.apple.foundationdb.record.metadata.Key.Expressions.concatenateFields) RecordQueryPlanMatchers.indexName(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexName) Expressions.concat(com.apple.foundationdb.record.metadata.Key.Expressions.concat) Tag(org.junit.jupiter.api.Tag) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ImmutableSet(com.google.common.collect.ImmutableSet) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) IndexOptions(com.apple.foundationdb.record.metadata.IndexOptions) Expressions.keyWithValue(com.apple.foundationdb.record.metadata.Key.Expressions.keyWithValue) Matchers.startsWith(org.hamcrest.Matchers.startsWith) Test(org.junit.jupiter.api.Test) Objects(java.util.Objects) List(java.util.List) ScanComparisons.range(com.apple.foundationdb.record.query.plan.ScanComparisons.range) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) 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.is(org.hamcrest.Matchers.is) RecordQueryPlanMatchers.predicatesFilterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicatesFilterPlan) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) RecordQueryPlanMatchers.indexPlanOf(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexPlanOf) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) PrimitiveMatchers.equalsObject(com.apple.foundationdb.record.query.plan.temp.matchers.PrimitiveMatchers.equalsObject) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) PlanHashable(com.apple.foundationdb.record.PlanHashable) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) PlannerRuleSet(com.apple.foundationdb.record.query.plan.temp.PlannerRuleSet) ImmutableList(com.google.common.collect.ImmutableList) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) Matchers.lessThan(org.hamcrest.Matchers.lessThan) RecordQueryPlanMatchers.scanComparisons(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.scanComparisons) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Expressions.field(com.apple.foundationdb.record.metadata.Key.Expressions.field) ScanComparisons.unbounded(com.apple.foundationdb.record.query.plan.ScanComparisons.unbounded) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) Tags(com.apple.test.Tags) QueryPredicateMatchers.valuePredicate(com.apple.foundationdb.record.query.plan.temp.matchers.QueryPredicateMatchers.valuePredicate) RecordQueryPlanMatchers.queryComponents(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.queryComponents) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) RecordQueryPlanMatchers.filterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.filterPlan) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) Index(com.apple.foundationdb.record.metadata.Index) RecordQueryPlanMatchers.indexPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexPlan) Message(com.google.protobuf.Message) ListMatcher.exactly(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.exactly) Collections(java.util.Collections) ValueMatchers.fieldValue(com.apple.foundationdb.record.query.plan.temp.matchers.ValueMatchers.fieldValue) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Index(com.apple.foundationdb.record.metadata.Index) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordQuery(com.apple.foundationdb.record.query.RecordQuery)

Example 30 with Key

use of com.apple.foundationdb.record.metadata.Key in project fdb-record-layer by FoundationDB.

the class FDBCoveringIndexQueryTest method queryCoveringAggregate.

/**
 * Verify that selecting the group key and the aggregate function from a grouped aggregate index can be planned
 * by a covering aggregate index.
 */
@Test
void queryCoveringAggregate() {
    Index sumIndex = new Index("value3sum", field("num_value_3_indexed").groupBy(Key.Expressions.concatenateFields("str_value_indexed", "num_value_2")), IndexTypes.SUM);
    RecordMetaDataHook hook = metaData -> metaData.addIndex("MySimpleRecord", sumIndex);
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, hook);
        for (int i = 0; i < 20; i++) {
            TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
            recBuilder.setRecNo(i);
            recBuilder.setStrValueIndexed((i & 1) == 1 ? "odd" : "even");
            recBuilder.setNumValue2(i % 3);
            recBuilder.setNumValue3Indexed(i % 5);
            recordStore.saveRecord(recBuilder.build());
        }
        commit(context);
    }
    RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.field("str_value_indexed").equalsValue("even")).setRequiredResults(Arrays.asList(field("str_value_indexed"), field("num_value_2"))).build();
    // This is here since the main planner doesn't currently support planning aggregates, so it's basically a
    // separate "mini-planner".
    // TODO: Support aggregate planning in the main query planner (https://github.com/FoundationDB/fdb-record-layer/issues/14)
    RecordQueryPlan plan = ((RecordQueryPlanner) planner).planCoveringAggregateIndex(query, "value3sum");
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context, hook);
        int i = 0;
        try (RecordCursorIterator<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(Objects.requireNonNull(plan)).asIterator()) {
            while (cursor.hasNext()) {
                FDBQueriedRecord<Message> rec = cursor.next();
                TestRecords1Proto.MySimpleRecord.Builder myrec = TestRecords1Proto.MySimpleRecord.newBuilder();
                myrec.mergeFrom(Objects.requireNonNull(rec).getRecord());
                assertEquals("even", myrec.getStrValueIndexed());
                int sum = 0;
                for (int j = 0; j < 20; j += 2) {
                    if (j % 3 == myrec.getNumValue2()) {
                        sum += j % 5;
                    }
                }
                assertEquals(sum, Objects.requireNonNull(rec.getIndexEntry()).getValue().getLong(0));
                i++;
            }
        }
        assertEquals(3, i);
        assertDiscardedNone(context);
    }
}
Also used : RecordQueryPlanMatchers.coveringIndexPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.coveringIndexPlan) Arrays(java.util.Arrays) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQueryPlanMatchers.predicates(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicates) Disabled(org.junit.jupiter.api.Disabled) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) TestHelpers.assertDiscardedNone(com.apple.foundationdb.record.TestHelpers.assertDiscardedNone) RecordQueryPlanMatchers.fetchFromPartialRecordPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.fetchFromPartialRecordPlan) Pair(org.apache.commons.lang3.tuple.Pair) ListMatcher.only(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.only) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) Expressions.concatenateFields(com.apple.foundationdb.record.metadata.Key.Expressions.concatenateFields) RecordQueryPlanMatchers.indexName(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexName) Expressions.concat(com.apple.foundationdb.record.metadata.Key.Expressions.concat) Tag(org.junit.jupiter.api.Tag) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ImmutableSet(com.google.common.collect.ImmutableSet) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) IndexOptions(com.apple.foundationdb.record.metadata.IndexOptions) Expressions.keyWithValue(com.apple.foundationdb.record.metadata.Key.Expressions.keyWithValue) Matchers.startsWith(org.hamcrest.Matchers.startsWith) Test(org.junit.jupiter.api.Test) Objects(java.util.Objects) List(java.util.List) ScanComparisons.range(com.apple.foundationdb.record.query.plan.ScanComparisons.range) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) 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.is(org.hamcrest.Matchers.is) RecordQueryPlanMatchers.predicatesFilterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.predicatesFilterPlan) RecordMetaData(com.apple.foundationdb.record.RecordMetaData) RecordQueryPlanMatchers.indexPlanOf(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexPlanOf) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) PrimitiveMatchers.equalsObject(com.apple.foundationdb.record.query.plan.temp.matchers.PrimitiveMatchers.equalsObject) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) PlanHashable(com.apple.foundationdb.record.PlanHashable) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) PlannerRuleSet(com.apple.foundationdb.record.query.plan.temp.PlannerRuleSet) ImmutableList(com.google.common.collect.ImmutableList) RecordCursorIterator(com.apple.foundationdb.record.RecordCursorIterator) Matchers.lessThan(org.hamcrest.Matchers.lessThan) RecordQueryPlanMatchers.scanComparisons(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.scanComparisons) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Expressions.field(com.apple.foundationdb.record.metadata.Key.Expressions.field) ScanComparisons.unbounded(com.apple.foundationdb.record.query.plan.ScanComparisons.unbounded) RecordMetaDataBuilder(com.apple.foundationdb.record.RecordMetaDataBuilder) Tags(com.apple.test.Tags) QueryPredicateMatchers.valuePredicate(com.apple.foundationdb.record.query.plan.temp.matchers.QueryPredicateMatchers.valuePredicate) RecordQueryPlanMatchers.queryComponents(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.queryComponents) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) RecordQueryPlanMatchers.filterPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.filterPlan) BindingMatcher(com.apple.foundationdb.record.query.plan.temp.matchers.BindingMatcher) Index(com.apple.foundationdb.record.metadata.Index) RecordQueryPlanMatchers.indexPlan(com.apple.foundationdb.record.query.plan.temp.matchers.RecordQueryPlanMatchers.indexPlan) Message(com.google.protobuf.Message) ListMatcher.exactly(com.apple.foundationdb.record.query.plan.temp.matchers.ListMatcher.exactly) Collections(java.util.Collections) ValueMatchers.fieldValue(com.apple.foundationdb.record.query.plan.temp.matchers.ValueMatchers.fieldValue) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Message(com.google.protobuf.Message) Index(com.apple.foundationdb.record.metadata.Index) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) Test(org.junit.jupiter.api.Test)

Aggregations

Key (com.apple.foundationdb.record.metadata.Key)39 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)31 List (java.util.List)31 Index (com.apple.foundationdb.record.metadata.Index)30 Message (com.google.protobuf.Message)30 Query (com.apple.foundationdb.record.query.expressions.Query)29 ArrayList (java.util.ArrayList)27 Collections (java.util.Collections)26 RecordMetaData (com.apple.foundationdb.record.RecordMetaData)25 IndexTypes (com.apple.foundationdb.record.metadata.IndexTypes)25 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)25 Test (org.junit.jupiter.api.Test)25 Expressions.field (com.apple.foundationdb.record.metadata.Key.Expressions.field)24 RecordQuery (com.apple.foundationdb.record.query.RecordQuery)24 Tag (org.junit.jupiter.api.Tag)24 Tags (com.apple.test.Tags)23 Expressions.concat (com.apple.foundationdb.record.metadata.Key.Expressions.concat)22 RecordMetaDataBuilder (com.apple.foundationdb.record.RecordMetaDataBuilder)20 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)20 RecordCoreException (com.apple.foundationdb.record.RecordCoreException)18