Search in sources :

Example 11 with JoinedRecordTypeBuilder

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

the class SyntheticRecordPlannerTest method clique.

@Test
public void clique() throws Exception {
    final JoinedRecordTypeBuilder clique = metaDataBuilder.addJoinedRecordType("Clique");
    clique.addConstituent("type_a", "TypeA");
    clique.addConstituent("type_b", "TypeB");
    clique.addConstituent("type_c", "TypeC");
    clique.addJoin("type_a", "type_b_rec_no", "type_b", "rec_no");
    clique.addJoin("type_b", "type_c_rec_no", "type_c", "rec_no");
    clique.addJoin("type_c", "type_a_rec_no", "type_a", "rec_no");
    try (FDBRecordContext context = openContext()) {
        final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).create();
        for (int i = 0; i < 3; i++) {
            TestRecordsJoinIndexProto.TypeA.Builder typeA = TestRecordsJoinIndexProto.TypeA.newBuilder();
            typeA.setRecNo(100 + i).setTypeBRecNo(200 + i);
            recordStore.saveRecord(typeA.build());
            TestRecordsJoinIndexProto.TypeB.Builder typeB = TestRecordsJoinIndexProto.TypeB.newBuilder();
            typeB.setRecNo(200 + i).setTypeCRecNo(300 + i);
            recordStore.saveRecord(typeB.build());
            TestRecordsJoinIndexProto.TypeC.Builder typeC = TestRecordsJoinIndexProto.TypeC.newBuilder();
            typeC.setRecNo(300 + i).setTypeARecNo(100 + i);
            recordStore.saveRecord(typeC.build());
        }
        context.commit();
    }
    try (FDBRecordContext context = openContext()) {
        final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).open();
        final SyntheticRecordPlanner planner = new SyntheticRecordPlanner(recordStore);
        SyntheticRecordPlan plan1 = planner.scanForType(recordStore.getRecordMetaData().getSyntheticRecordType("Clique"));
        Multiset<Tuple> expected1 = ImmutableMultiset.of(Tuple.from(-1, Tuple.from(100), Tuple.from(200), Tuple.from(300)), Tuple.from(-1, Tuple.from(101), Tuple.from(201), Tuple.from(301)), Tuple.from(-1, Tuple.from(102), Tuple.from(202), Tuple.from(302)));
        Multiset<Tuple> results1 = HashMultiset.create(plan1.execute(recordStore).map(FDBSyntheticRecord::getPrimaryKey).asList().join());
        assertEquals(expected1, results1);
        // Make sure that the extra join condition is checked.
        TestRecordsJoinIndexProto.TypeC.Builder typeC = TestRecordsJoinIndexProto.TypeC.newBuilder();
        typeC.setRecNo(301).setTypeARecNo(999);
        recordStore.saveRecord(typeC.build());
        SyntheticRecordPlan plan2 = planner.scanForType(recordStore.getRecordMetaData().getSyntheticRecordType("Clique"));
        Multiset<Tuple> expected2 = ImmutableMultiset.of(Tuple.from(-1, Tuple.from(100), Tuple.from(200), Tuple.from(300)), Tuple.from(-1, Tuple.from(102), Tuple.from(202), Tuple.from(302)));
        Multiset<Tuple> results2 = HashMultiset.create(plan2.execute(recordStore).map(FDBSyntheticRecord::getPrimaryKey).asList().join());
        assertEquals(expected2, results2);
    }
}
Also used : FDBRecordStore(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore) JoinedRecordTypeBuilder(com.apple.foundationdb.record.metadata.JoinedRecordTypeBuilder) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) Tuple(com.apple.foundationdb.tuple.Tuple) Test(org.junit.jupiter.api.Test)

Example 12 with JoinedRecordTypeBuilder

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

the class SyntheticRecordPlannerTest method multiFieldKeys.

@Test
public void multiFieldKeys() throws Exception {
    metaDataBuilder.getRecordType("MySimpleRecord").setPrimaryKey(concatenateFields("num_value", "rec_no"));
    metaDataBuilder.getRecordType("MyOtherRecord").setPrimaryKey(concatenateFields("num_value", "rec_no"));
    final JoinedRecordTypeBuilder joined = metaDataBuilder.addJoinedRecordType("MultiFieldJoin");
    joined.addConstituent("simple", "MySimpleRecord");
    joined.addConstituent("other", "MyOtherRecord");
    // TODO: Not supported alternative would be to join concatenateFields("num_value", "other_rec_no") with concatenateFields("num_value", "rec_no").
    joined.addJoin("simple", "num_value", "other", "num_value");
    joined.addJoin("simple", "other_rec_no", "other", "rec_no");
    metaDataBuilder.addIndex(joined, new Index("simple.str_value_other.num_value_3", concat(field("simple").nest("str_value"), field("other").nest("num_value_3"))));
    try (FDBRecordContext context = openContext()) {
        final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).create();
        for (int n = 1; n <= 2; n++) {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < i; j++) {
                    TestRecordsJoinIndexProto.MySimpleRecord.Builder simple = TestRecordsJoinIndexProto.MySimpleRecord.newBuilder();
                    simple.setNumValue(n);
                    simple.setRecNo(100 * i + j).setOtherRecNo(1000 + i);
                    simple.setStrValue((i + j) % 2 == 0 ? "even" : "odd");
                    recordStore.saveRecord(simple.build());
                }
                TestRecordsJoinIndexProto.MyOtherRecord.Builder other = TestRecordsJoinIndexProto.MyOtherRecord.newBuilder();
                other.setNumValue(n);
                other.setRecNo(1000 + i);
                other.setNumValue3(i);
                recordStore.saveRecord(other.build());
            }
        }
        context.commit();
    }
    try (FDBRecordContext context = openContext()) {
        final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).open();
        List<FDBSyntheticRecord> recs = recordStore.scanIndex(recordStore.getRecordMetaData().getIndex("simple.str_value_other.num_value_3"), IndexScanType.BY_VALUE, TupleRange.allOf(Tuple.from("even", 2)), null, ScanProperties.FORWARD_SCAN).mapPipelined(entry -> recordStore.loadSyntheticRecord(entry.getPrimaryKey()), 1).asList().join();
        for (FDBSyntheticRecord record : recs) {
            TestRecordsJoinIndexProto.MySimpleRecord.Builder simple = TestRecordsJoinIndexProto.MySimpleRecord.newBuilder();
            TestRecordsJoinIndexProto.MyOtherRecord.Builder other = TestRecordsJoinIndexProto.MyOtherRecord.newBuilder();
            simple.mergeFrom(record.getConstituent("simple").getRecord());
            other.mergeFrom(record.getConstituent("other").getRecord());
            assertEquals(200, simple.getRecNo());
            assertEquals(1002, other.getRecNo());
            assertEquals(record.getPrimaryKey(), record.getRecordType().getPrimaryKey().evaluateSingleton(record).toTuple());
        }
    }
}
Also used : FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) FDBSyntheticRecord(com.apple.foundationdb.record.provider.foundationdb.FDBSyntheticRecord) Index(com.apple.foundationdb.record.metadata.Index) FDBRecordStore(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore) JoinedRecordTypeBuilder(com.apple.foundationdb.record.metadata.JoinedRecordTypeBuilder) Test(org.junit.jupiter.api.Test)

Example 13 with JoinedRecordTypeBuilder

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

the class SyntheticRecordPlannerTest method nestedRepeated.

@Test
public void nestedRepeated() throws Exception {
    final KeyExpression key = field("repeated", KeyExpression.FanType.FanOut).nest("nums", KeyExpression.FanType.FanOut);
    metaDataBuilder.addIndex("NestedA", "repeatedA", key);
    metaDataBuilder.addIndex("NestedB", "repeatedB", key);
    final JoinedRecordTypeBuilder nested = metaDataBuilder.addJoinedRecordType("NestedRepeated");
    nested.addConstituent("nested_a", "NestedA");
    nested.addConstituent("nested_b", "NestedB");
    nested.addJoin("nested_a", key, "nested_b", key);
    try (FDBRecordContext context = openContext()) {
        final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).create();
        TestRecordsJoinIndexProto.NestedA.Builder nestedA = TestRecordsJoinIndexProto.NestedA.newBuilder();
        nestedA.setRecNo(101);
        nestedA.addRepeatedBuilder().addNums(1).addNums(2);
        nestedA.addRepeatedBuilder().addNums(3).addNums(4);
        recordStore.saveRecord(nestedA.build());
        nestedA.setRecNo(102);
        nestedA.clearRepeated();
        nestedA.addRepeatedBuilder().addNums(2);
        recordStore.saveRecord(nestedA.build());
        TestRecordsJoinIndexProto.NestedB.Builder nestedB = TestRecordsJoinIndexProto.NestedB.newBuilder();
        nestedB.setRecNo(201);
        nestedB.addRepeatedBuilder().addNums(2).addNums(4);
        recordStore.saveRecord(nestedB.build());
        nestedB.setRecNo(202);
        nestedB.clearRepeated();
        nestedB.addRepeatedBuilder().addNums(1).addNums(3);
        nestedB.addRepeatedBuilder().addNums(2);
        recordStore.saveRecord(nestedB.build());
        nestedB.setRecNo(203);
        nestedB.clearRepeated();
        recordStore.saveRecord(nestedB.build());
        context.commit();
    }
    try (FDBRecordContext context = openContext()) {
        final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).open();
        final SyntheticRecordPlanner planner = new SyntheticRecordPlanner(recordStore);
        SyntheticRecordPlan plan1 = planner.scanForType(recordStore.getRecordMetaData().getSyntheticRecordType("NestedRepeated"));
        Multiset<Tuple> expected1 = ImmutableMultiset.of(Tuple.from(-1, Tuple.from(101), Tuple.from(201)), Tuple.from(-1, Tuple.from(101), Tuple.from(202)), Tuple.from(-1, Tuple.from(102), Tuple.from(201)), Tuple.from(-1, Tuple.from(102), Tuple.from(202)));
        Multiset<Tuple> results1 = HashMultiset.create(plan1.execute(recordStore).map(FDBSyntheticRecord::getPrimaryKey).asList().join());
        assertEquals(expected1, results1);
        FDBStoredRecord<Message> record = recordStore.loadRecord(Tuple.from(101));
        SyntheticRecordFromStoredRecordPlan plan2 = planner.fromStoredType(record.getRecordType(), false);
        // TODO: IN can generate duplicates from repeated field (https://github.com/FoundationDB/fdb-record-layer/issues/98)
        Multiset<Tuple> expected2 = ImmutableMultiset.of(Tuple.from(-1, Tuple.from(101), Tuple.from(201)), Tuple.from(-1, Tuple.from(101), Tuple.from(201)), Tuple.from(-1, Tuple.from(101), Tuple.from(202)), Tuple.from(-1, Tuple.from(101), Tuple.from(202)), Tuple.from(-1, Tuple.from(101), Tuple.from(202)));
        Multiset<Tuple> results2 = HashMultiset.create(plan2.execute(recordStore, record).map(FDBSyntheticRecord::getPrimaryKey).asList().join());
        assertEquals(expected2, results2);
    }
}
Also used : Message(com.google.protobuf.Message) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FDBRecordStore(com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore) JoinedRecordTypeBuilder(com.apple.foundationdb.record.metadata.JoinedRecordTypeBuilder) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) Tuple(com.apple.foundationdb.tuple.Tuple) Test(org.junit.jupiter.api.Test)

Example 14 with JoinedRecordTypeBuilder

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

the class RecordMetaDataBuilder method addJoinedRecordType.

/**
 * Add a new joined record type.
 * @param name the name of the new record type
 * @return a new uninitialized joined record type
 */
@Nonnull
@API(API.Status.EXPERIMENTAL)
public JoinedRecordTypeBuilder addJoinedRecordType(@Nonnull String name) {
    if (recordTypes.containsKey(name)) {
        throw new MetaDataException("There is already a record type named " + name);
    }
    if (syntheticRecordTypes.containsKey(name)) {
        throw new MetaDataException("There is already a synthetic record type named " + name);
    }
    JoinedRecordTypeBuilder recordType = new JoinedRecordTypeBuilder(name, getNextRecordTypeKey(), this);
    syntheticRecordTypes.put(name, recordType);
    return recordType;
}
Also used : JoinedRecordTypeBuilder(com.apple.foundationdb.record.metadata.JoinedRecordTypeBuilder) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) Nonnull(javax.annotation.Nonnull) API(com.apple.foundationdb.annotation.API)

Aggregations

JoinedRecordTypeBuilder (com.apple.foundationdb.record.metadata.JoinedRecordTypeBuilder)14 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)12 FDBRecordStore (com.apple.foundationdb.record.provider.foundationdb.FDBRecordStore)12 Test (org.junit.jupiter.api.Test)12 Tuple (com.apple.foundationdb.tuple.Tuple)11 Index (com.apple.foundationdb.record.metadata.Index)7 Message (com.google.protobuf.Message)5 IndexEntry (com.apple.foundationdb.record.IndexEntry)3 GroupingKeyExpression (com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression)3 KeyExpression (com.apple.foundationdb.record.metadata.expressions.KeyExpression)3 RecordMetaDataBuilder (com.apple.foundationdb.record.RecordMetaDataBuilder)2 TupleRange (com.apple.foundationdb.record.TupleRange)2 FDBSyntheticRecord (com.apple.foundationdb.record.provider.foundationdb.FDBSyntheticRecord)2 Comparisons (com.apple.foundationdb.record.query.expressions.Comparisons)2 ScanComparisons (com.apple.foundationdb.record.query.plan.ScanComparisons)2 API (com.apple.foundationdb.annotation.API)1 FormerIndex (com.apple.foundationdb.record.metadata.FormerIndex)1 IndexAggregateFunction (com.apple.foundationdb.record.metadata.IndexAggregateFunction)1 IndexRecordFunction (com.apple.foundationdb.record.metadata.IndexRecordFunction)1 MetaDataException (com.apple.foundationdb.record.metadata.MetaDataException)1