diff --git a/docs/en_US/erd_tool.rst b/docs/en_US/erd_tool.rst index 7d838d6da..6f3404076 100644 --- a/docs/en_US/erd_tool.rst +++ b/docs/en_US/erd_tool.rst @@ -18,7 +18,14 @@ The Entity-Relationship Diagram (ERD) tool is a database design tool that provid :alt: ERD tool window :align: center -You can open multiple copies of the ERD tool in individual tabs simultaneously. To close a copy of the ERD tool, click the *X* in the upper-right hand corner of the tab bar. +You can open multiple copies of the ERD tool in individual tabs simultaneously. +You can also generate an ERD from a database, schema or a table. + +* The ERD for database will fetch all the tables from all the schemas of the database and plot them with foreign key links. +* The ERD for schema will fetch all the tables from a schema and plot them with foreign key links. If any table refers to a table in another + schema, then that link/foreign key will be removed. +* The ERD for table will fetch all the tables linked directly or indirectly to mentioned table. You can change the depth of traversal from :ref:`Preferences `. + Toolbar ******* diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js index 2fb4d8059..74a544979 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js @@ -13,8 +13,8 @@ import { getNodeListByName } from '../../../../../../static/js/node_ajax'; define('pgadmin.node.schema', [ 'sources/gettext', 'sources/url_for', - 'pgadmin.browser', 'pgadmin.browser.collection', -], function(gettext, url_for, pgBrowser) { + 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.browser.collection', +], function(gettext, url_for, pgAdmin, pgBrowser) { // Extend the browser's collection class for schema collection if (!pgBrowser.Nodes['coll-schema']) { @@ -61,12 +61,25 @@ define('pgadmin.node.schema', [ applies: ['object', 'context'], callback: 'show_obj_properties', category: 'create', priority: 1, label: gettext('Schema...'), data: {action: 'create'}, enable: 'can_create_schema', - }, - ]); + },{ + name: 'generate_erd', node: 'schema', module: this, + applies: ['object', 'context'], callback: 'generate_erd', + category: 'erd', priority: 5, label: gettext('ERD For Schema') + }]); }, can_create_schema: function(node) { return pgBrowser.Nodes['database'].is_conn_allow.call(this, node); }, + callbacks: { + /* Generate the ERD */ + generate_erd: function(args) { + let input = args || {}, + t = pgBrowser.tree, + i = input.item || t.selected(), + d = i ? t.itemData(i) : undefined; + pgAdmin.Tools.ERD.showErdTool(d, i, true); + }, + }, getSchema: function(treeNodeInfo, itemNodeData) { let schemaObj = pgBrowser.Nodes['schema']; return new PGSchema( diff --git a/web/pgadmin/tools/erd/static/js/ERDModule.js b/web/pgadmin/tools/erd/static/js/ERDModule.js index 6ffeea6ca..3c1de1ab8 100644 --- a/web/pgadmin/tools/erd/static/js/ERDModule.js +++ b/web/pgadmin/tools/erd/static/js/ERDModule.js @@ -131,9 +131,11 @@ export default class ERDModule { +`&did=${parentData.database._id}` +`&gen=${gen}`; + if(parentData.schema) { + openUrl += `&scid=${parentData.schema._id}`; + } if(parentData.table) { - openUrl += `&scid=${parentData.schema._id}` - +`&tid=${parentData.table._id}`; + openUrl += `&tid=${parentData.table._id}`; } return openUrl; diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js b/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js index 76fc8d923..53203fd02 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js +++ b/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js @@ -615,7 +615,7 @@ export default class ERDCore { _.forIn(tableNodesDict, (node, uid)=>{ let nodeData = node.getData(); if(nodeData.foreign_key) { - nodeData.foreign_key.forEach((theFk)=>{ + nodeData.foreign_key = nodeData.foreign_key.filter((theFk)=>{ delete theFk.oid; theFk = theFk.columns[0]; theFk.references = oidUidMap[theFk.references]; @@ -627,11 +627,17 @@ export default class ERDCore { }; let sourceNode = tableNodesDict[newData.referenced_table_uid]; let targetNode = tableNodesDict[newData.local_table_uid]; + // When generating for schema, there may be a reference to another schema table + // We'll remove the FK completely in such cases. + if(!sourceNode || !targetNode) { + return false; + } newData.local_column_attnum = _.find(targetNode.getColumns(), (col)=>col.name==theFk.local_column).attnum; newData.referenced_column_attnum = _.find(sourceNode.getColumns(), (col)=>col.name==theFk.referenced).attnum; this.addLink(newData, 'onetomany'); + return true; }); } }); diff --git a/web/pgadmin/tools/erd/utils.py b/web/pgadmin/tools/erd/utils.py index 3a12b2dcc..2d41bced0 100644 --- a/web/pgadmin/tools/erd/utils.py +++ b/web/pgadmin/tools/erd/utils.py @@ -32,12 +32,16 @@ class ERDTableView(BaseTableView, DataTypeReader): return DataTypeReader.get_types(self, self.conn, condition, True) @BaseTableView.check_precondition - def fetch_all_tables(self, did=None, sid=None): - status, schemas = get_schemas(self.conn, show_system_objects=False) - if not status: - return status, schemas - + def fetch_all_tables(self, did=None, sid=None, scid=None): all_tables = [] + schemas = {'rows': []} + if scid is None: + status, schemas = get_schemas(self.conn, show_system_objects=False) + if not status: + return status, schemas + else: + schemas['rows'].append({'oid': scid}) + for row in schemas['rows']: status, res = \ BaseTableView.fetch_tables(self, sid, did, row['oid'], @@ -111,6 +115,9 @@ class ERDHelper: if tid is None and scid is None: status, res = self.table_view.fetch_all_tables( did=self.did, sid=self.sid) + elif tid is None: + status, res = self.table_view.fetch_all_tables( + did=self.did, sid=self.sid, scid=scid) else: prefs = Preferences.module('erd') table_relation_depth = prefs.preference('table_relation_depth')