'use strict'; import * as schema from "./templates/schema" // @ts-ignore import PostgreSQLDatabaseDiscovery from './PostgreSQLDatabaseDiscovery'; // @ts-ignore import Converter from './src/utils/Converter'; const jsonMerger = require("json-merger"); //https://github.com/boschni/json-merger const Graph = require("./utils/graph-data-structure"); const _ = require('lodash'); export default class PostgresSchemaGraph { buildEdges = async (foreignKeyReferences) => { let serializedLink let serializedLinks let edgesJson = { edges: {} } let edgeName: string; //foreign key column name let sourceNode: string; //foreign key table name let targetNode: string; //primary key table name //console.log(JSON.stringify(foreignKeyReferences, null, 3)) let graph = new Graph(); let tables = Object.keys(foreignKeyReferences) for (let i = 0; i < tables.length; i++) { let references = foreignKeyReferences[tables[i]] if (references.length === 0) { continue } sourceNode = tables[i] for (let j = 0; j < references.length; j++) { let reference = references[j] targetNode = reference['tableName'] edgeName = reference['columnName'] //console.log(sourceNode) graph.addNode(sourceNode) //original table graph.addNode(targetNode) //foreign table graph.addEdge(sourceNode, targetNode) } serializedLinks = graph.serializeLinks(edgeName) edgesJson.edges[sourceNode] = serializedLinks[edgeName]; graph = new Graph() serializedLinks = {} } //update the edges name edgesJson = await this.updateEdgeNames(edgesJson, foreignKeyReferences) return edgesJson } //update the edgeName to be the right one because if multiple elements in a table, then all the edgeName are the same //the edgename in an array should be diffent updateEdgeNames = (edges, foreignKeyReferences) => { //get the table name let tables = Object.keys(foreignKeyReferences) for (let i = 0; i < tables.length; i++) { let table = tables[i] let references = foreignKeyReferences[table] if (references.length === 0) { continue } for (let j = 0; j < references.length; j++) { let reference = references[j] let edgeName = reference['columnName'] edges['edges'][table][j]['edgeName'] = edgeName } } return edges } //to achieve the bidirectional relationship so we need to create edges that comes from target to source generateBidirectionalEdges = (edges) => { //get the table name let tables = Object.keys(edges['edges']) //console.log(tables) let _tables = {} let _references = [] for (let i = 0; i < tables.length; i++) { let table = tables[i] let references = edges['edges'][table] //console.log(references) let source let target for (let j = 0; j < references.length; j++) { let reference = references[j] let _reference = { ...reference } //generate the reverse edges source = reference['source'] let tmp = source target = reference['target'] _reference.source = target _reference.target = tmp _references.push(_reference) } } //create a json with arrays group by the tablename const property = "source" const reversedEdges = _.groupBy(_references, property); //combine multiple arrays with the same key into one array const bidirectionalEdges = jsonMerger.mergeObjects([edges['edges'], reversedEdges], {defaultArrayMergeOperation: "concat"}) //console.log(JSON.stringify(bidirectionalEdges,null,3)) return bidirectionalEdges } } /*********************************** Main Entry Point ************************************************/ const PostgreSQLConfiguration = { "DBMS" : "Postgres", "HOSTNAME": "localhost", "USER" : "jiskandar", "PASSWORD": "pwd", "DATABASE": "dvdrental", "SCHEMA" : "public" }; /* const PostgreSQLConfiguration = { host: 'localhost', database: 'Adventureworks', schema: 'humanresources', user: 'jiskandar', password: 'pwd' }; */ async function run() { const postgresSchemaGraph = new PostgresSchemaGraph(); const postgreSQLDatabaseDiscovery = new PostgreSQLDatabaseDiscovery(PostgreSQLConfiguration); let extractedSchema = await postgreSQLDatabaseDiscovery.extractPostgreSQLSchema(); //console.log(JSON.stringify(extractedSchema, null , 3)); let foreignKeys = await postgreSQLDatabaseDiscovery.getForeignKeyReferences(extractedSchema) //console.log(JSON.stringify(foreignKeys, null , 3)); //build the edges let edges = await postgresSchemaGraph.buildEdges(foreignKeys) //console.log(JSON.stringify(edges,null,3)) //get the reverse edges let bidirectionalEdges = await postgresSchemaGraph.generateBidirectionalEdges(edges) //console.log(JSON.stringify(bidirectionalEdges, null,3)) extractedSchema = schema.buildPostgresSchema(extractedSchema); //console.log(JSON.stringify(extractedSchema, null , 3)); let nodesGraph = { nodes: [], edges: {} }; nodesGraph.nodes = extractedSchema; nodesGraph.edges = bidirectionalEdges console.log(JSON.stringify(nodesGraph, null , 3)); } //run()