Add support for generating ERD for a schema. #4580

This commit is contained in:
Aditya Toshniwal 2023-11-28 16:42:51 +05:30 committed by GitHub
parent c9590b2d62
commit 377216caec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 13 deletions

View File

@ -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 <preferences>`.
Toolbar
*******

View File

@ -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(

View File

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

View File

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

View File

@ -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')