@@ -400,6 +400,7 @@ export default class ERDCore {
400400
401401 const addLink = ( theFk ) => {
402402 if ( ! theFk ) return ;
403+
403404 let newData = {
404405 local_table_uid : tableNode . getID ( ) ,
405406 local_column_attnum : undefined ,
@@ -590,7 +591,7 @@ export default class ERDCore {
590591 }
591592
592593 cloneTableData ( tableData , name ) {
593- const SKIP_CLONE_KEYS = [ 'foreign_key' ] ;
594+ const SKIP_CLONE_KEYS = [ 'oid' , ' foreign_key' , 'original_foreign_keys '] ;
594595
595596 if ( ! tableData ) {
596597 return tableData ;
@@ -635,43 +636,95 @@ export default class ERDCore {
635636
636637 deserializeData ( data ) {
637638 let oidUidMap = { } ;
639+ let newNodes = [ ] ;
638640
639641 /* Add the nodes */
640642 data . forEach ( ( nodeData ) => {
641- let newNode = this . addNode ( TableSchema . getErdSupportedData ( nodeData ) ) ;
643+ const newNode = this . addNode ( TableSchema . getErdSupportedData ( nodeData ) ) ;
642644 oidUidMap [ nodeData . oid ] = newNode . getID ( ) ;
645+ newNodes . push ( newNode ) ;
643646 } ) ;
644647
645- /* Lets use the oidUidMap for creating the links */
646- let tableNodesDict = this . getModel ( ) . getNodesDict ( ) ;
648+ // When generating for schema, there may be a reference to another schema table
649+ // We'll remove the FK completely in such cases
650+ newNodes . forEach ( ( node ) => {
651+ const nodeData = node . getData ( ) ;
652+ nodeData . original_foreign_keys = nodeData . original_foreign_keys ?. filter ( fk =>
653+ fk . columns ?. [ 0 ] ?. references && oidUidMap [ fk . columns [ 0 ] . references ]
654+ ) ;
655+ } ) ;
656+
657+ this . addLinksBetweenNodes ( oidUidMap ) ;
658+ }
659+
660+ addNodeWithLinks ( nodeData , position = [ 50 , 50 ] , metadata = { } ) {
661+ const tableNodesDict = this . getModel ( ) . getNodesDict ( ) ;
662+ const oidExists = Object . values ( tableNodesDict ) . some ( node => node . getData ( ) . oid === nodeData . oid ) ;
663+
664+ if ( oidExists ) {
665+ delete nodeData . oid ;
666+ }
667+
668+ let oidUidMap = { } ;
669+ const newNode = this . addNode ( nodeData , position , metadata ) ;
670+
671+ if ( ! oidExists ) {
672+ oidUidMap [ nodeData . oid ] = newNode . getID ( ) ;
673+ }
674+
647675 _ . forIn ( tableNodesDict , ( node , uid ) => {
648- let nodeData = node . getData ( ) ;
649- if ( nodeData . foreign_key ) {
650- nodeData . foreign_key = nodeData . foreign_key . filter ( ( theFk ) => {
651- delete theFk . oid ;
652- theFk = theFk . columns [ 0 ] ;
653- theFk . references = oidUidMap [ theFk . references ] ;
654- let newData = {
655- local_table_uid : uid ,
656- local_column_attnum : undefined ,
657- referenced_table_uid : theFk . references ,
658- referenced_column_attnum : undefined ,
659- } ;
660- let sourceNode = tableNodesDict [ newData . referenced_table_uid ] ;
661- let targetNode = tableNodesDict [ newData . local_table_uid ] ;
662- // When generating for schema, there may be a reference to another schema table
663- // We'll remove the FK completely in such cases.
664- if ( ! sourceNode || ! targetNode ) {
665- return false ;
666- }
676+ const oid = node . getData ( ) . oid ;
677+ if ( ! oid ) return ;
667678
668- newData . local_column_attnum = _ . find ( targetNode . getColumns ( ) , ( col ) => col . name == theFk . local_column ) . attnum ;
669- newData . referenced_column_attnum = _ . find ( sourceNode . getColumns ( ) , ( col ) => col . name == theFk . referenced ) . attnum ;
679+ oidUidMap [ oid ] = uid ;
680+ } ) ;
670681
671- this . addLink ( newData , 'onetomany' ) ;
672- return true ;
673- } ) ;
674- }
682+ this . addLinksBetweenNodes ( oidUidMap , [ newNode . getID ( ) ] ) ;
683+ return newNode ;
684+ }
685+
686+ addLinksBetweenNodes ( oidUidMap , newNodesUids = null ) {
687+ const tableNodesDict = this . getModel ( ) . getNodesDict ( ) ;
688+
689+ _ . forIn ( tableNodesDict , ( node , uid ) => {
690+ const nodeData = node . getData ( ) ;
691+
692+ nodeData . original_foreign_keys ?. forEach ( ( theFk ) => {
693+ const theFkColumn = theFk . columns [ 0 ] ;
694+ let referencesUid = oidUidMap [ theFkColumn . references ] ;
695+
696+ /* Incomplete reference to missing table */
697+ if ( ! referencesUid ) {
698+ return ;
699+ }
700+
701+ /* Avoid creating duplicate links */
702+ if (
703+ newNodesUids
704+ && ! newNodesUids . includes ( uid )
705+ && ! newNodesUids . includes ( referencesUid )
706+ ) {
707+ return ;
708+ }
709+
710+ const newData = {
711+ local_table_uid : uid ,
712+ local_column_attnum : _ . find (
713+ tableNodesDict [ uid ] . getColumns ( ) ,
714+ ( col ) => col . name == theFkColumn . local_column
715+ ) . attnum ,
716+ referenced_table_uid : referencesUid ,
717+ referenced_column_attnum : _ . find (
718+ tableNodesDict [ referencesUid ] . getColumns ( ) ,
719+ ( col ) => col . name == theFkColumn . referenced
720+ ) . attnum ,
721+ } ;
722+
723+ const newForeignKey = _ . cloneDeep ( theFk ) ;
724+ newForeignKey . columns [ 0 ] . references = referencesUid ;
725+ nodeData . foreign_key . push ( newForeignKey ) ;
726+ this . addLink ( newData , 'onetomany' ) ;
727+ } ) ;
675728 } ) ;
676729 }
677730
0 commit comments