@Test public void manyToMany() throws Exception { final JoinedRecordTypeBuilder joined = metaDataBuilder.addJoinedRecordType("ManyToMany"); joined.addConstituent("simple", "MySimpleRecord"); joined.addConstituent("other", "MyOtherRecord"); joined.addConstituent("joining", "JoiningRecord"); joined.addJoin("joining", "simple_rec_no", "simple", "rec_no"); joined.addJoin("joining", "other_rec_no", "other", "rec_no"); try (FDBRecordContext context = openContext()) { final FDBRecordStore recordStore = recordStoreBuilder.setContext(context).create(); for (int i = 0; i < 3; i++) { TestRecordsJoinIndexProto.MySimpleRecord.Builder simple = TestRecordsJoinIndexProto.MySimpleRecord.newBuilder(); simple.setRecNo(i); recordStore.saveRecord(simple.build()); TestRecordsJoinIndexProto.MyOtherRecord.Builder other = TestRecordsJoinIndexProto.MyOtherRecord.newBuilder(); other.setRecNo(1000 + i); recordStore.saveRecord(other.build()); } TestRecordsJoinIndexProto.JoiningRecord.Builder joining = TestRecordsJoinIndexProto.JoiningRecord.newBuilder(); joining.setRecNo(100).setSimpleRecNo(1).setOtherRecNo(1000); recordStore.saveRecord(joining.build()); joining.setRecNo(101).setSimpleRecNo(2).setOtherRecNo(1000); recordStore.saveRecord(joining.build()); joining.setRecNo(102).setSimpleRecNo(2).setOtherRecNo(1002); recordStore.saveRecord(joining.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("ManyToMany")); Multiset<Tuple> expected1 = ImmutableMultiset.of( Tuple.from(-1, Tuple.from(1), Tuple.from(1000), Tuple.from(100)), Tuple.from(-1, Tuple.from(2), Tuple.from(1000), Tuple.from(101)), Tuple.from(-1, Tuple.from(2), Tuple.from(1002), Tuple.from(102))); Multiset<Tuple> results1 = HashMultiset.create(plan1.execute(recordStore).map(FDBSyntheticRecord::getPrimaryKey).asList().join()); assertEquals(expected1, results1); } }
@Nonnull public SyntheticRecordPlan scanForType(@Nonnull SyntheticRecordType<?> syntheticRecordType) { final SyntheticRecordFromStoredRecordPlan fromRecord = forType(syntheticRecordType); RecordQueryPlan query = queryPlanner.plan(RecordQuery.newBuilder().setRecordTypes(fromRecord.getStoredRecordTypes()).build()); return new SyntheticRecordScanPlan(query, fromRecord, true); }
SyntheticRecordPlanner { @Nonnull public SyntheticRecordPlan scanForType(@Nonnull SyntheticRecordType<?> syntheticRecordType) { final SyntheticRecordFromStoredRecordPlan fromRecord = forType(syntheticRecordType); RecordQueryPlan query = queryPlanner.plan(RecordQuery.newBuilder().setRecordTypes(fromRecord.getStoredRecordTypes()).build()); return new SyntheticRecordScanPlan(query, fromRecord, true); } }
SyntheticRecordPlanner { @Nonnull public SyntheticRecordPlan scanForType(@Nonnull SyntheticRecordType<?> syntheticRecordType) { final SyntheticRecordFromStoredRecordPlan fromRecord = forType(syntheticRecordType); RecordQueryPlan query = queryPlanner.plan(RecordQuery.newBuilder().setRecordTypes(fromRecord.getStoredRecordTypes()).build()); return new SyntheticRecordScanPlan(query, fromRecord, true); } SyntheticRecordPlanner(@Nonnull RecordMetaData recordMetaData, @Nonnull RecordStoreState storeState);  SyntheticRecordPlanner(@Nonnull FDBRecordStore store); }
SyntheticRecordPlanner { @Nonnull public SyntheticRecordPlan scanForType(@Nonnull SyntheticRecordType<?> syntheticRecordType) { final SyntheticRecordFromStoredRecordPlan fromRecord = forType(syntheticRecordType); RecordQueryPlan query = queryPlanner.plan(RecordQuery.newBuilder().setRecordTypes(fromRecord.getStoredRecordTypes()).build()); return new SyntheticRecordScanPlan(query, fromRecord, true); } SyntheticRecordPlanner(@Nonnull RecordMetaData recordMetaData, @Nonnull RecordStoreState storeState);  SyntheticRecordPlanner(@Nonnull FDBRecordStore store); @Nonnull SyntheticRecordPlan scanForType(@Nonnull SyntheticRecordType<?> syntheticRecordType); @Nonnull SyntheticRecordFromStoredRecordPlan forType(@Nonnull SyntheticRecordType<?> syntheticRecordType); @Nonnull SyntheticRecordFromStoredRecordPlan forType(@Nonnull JoinedRecordType joinedRecordType); @Nullable SyntheticRecordFromStoredRecordPlan fromStoredType(@Nonnull RecordType storedRecordType, boolean onlyIfIndexed); Set<RecordType> storedRecordTypesForIndex(@Nonnull Index index, @Nullable Collection<RecordType> recordTypes); @Nonnull SyntheticRecordFromStoredRecordPlan forIndex(@Nonnull Index index); @Nonnull SyntheticRecordFromStoredRecordPlan forJoinConstituent(@Nonnull JoinedRecordType joinedRecordType,
                                                                  @Nonnull JoinedRecordType.JoinConstituent joinConstituent); }
SyntheticRecordPlanner { @Nonnull public SyntheticRecordPlan scanForType(@Nonnull SyntheticRecordType<?> syntheticRecordType) { final SyntheticRecordFromStoredRecordPlan fromRecord = forType(syntheticRecordType); RecordQueryPlan query = queryPlanner.plan(RecordQuery.newBuilder().setRecordTypes(fromRecord.getStoredRecordTypes()).build()); return new SyntheticRecordScanPlan(query, fromRecord, true); } SyntheticRecordPlanner(@Nonnull RecordMetaData recordMetaData, @Nonnull RecordStoreState storeState);  SyntheticRecordPlanner(@Nonnull FDBRecordStore store); @Nonnull SyntheticRecordPlan scanForType(@Nonnull SyntheticRecordType<?> syntheticRecordType); @Nonnull SyntheticRecordFromStoredRecordPlan forType(@Nonnull SyntheticRecordType<?> syntheticRecordType); @Nonnull SyntheticRecordFromStoredRecordPlan forType(@Nonnull JoinedRecordType joinedRecordType); @Nullable SyntheticRecordFromStoredRecordPlan fromStoredType(@Nonnull RecordType storedRecordType, boolean onlyIfIndexed); Set<RecordType> storedRecordTypesForIndex(@Nonnull Index index, @Nullable Collection<RecordType> recordTypes); @Nonnull SyntheticRecordFromStoredRecordPlan forIndex(@Nonnull Index index); @Nonnull SyntheticRecordFromStoredRecordPlan forJoinConstituent(@Nonnull JoinedRecordType joinedRecordType,
                                                                  @Nonnull JoinedRecordType.JoinConstituent joinConstituent);  }