@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); 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); } }
@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);  }