From 2fc65589c8cc52db85da9e759dd62e105ccc2457 Mon Sep 17 00:00:00 2001 From: Pravesh Sharma Date: Mon, 10 Feb 2025 14:40:20 +0530 Subject: [PATCH] Add support for one to one relationship in the ERD tool. #5128 --- docs/en_US/erd_tool.rst | 16 +++ docs/en_US/images/erd_11_dialog.png | Bin 0 -> 89174 bytes web/pgadmin/tools/erd/__init__.py | 18 +++ .../erd/static/js/erd_tool/ERDConstants.js | 1 + .../tools/erd/static/js/erd_tool/ERDCore.js | 48 ++++++-- .../static/js/erd_tool/components/ERDTool.jsx | 27 ++++- .../js/erd_tool/components/MainToolBar.jsx | 11 +- .../js/erd_tool/dialogs/OneToOneDialog.js | 106 ++++++++++++++++++ .../erd/static/js/erd_tool/dialogs/index.jsx | 3 + .../js/erd_tool/links/OneToManyLink.jsx | 41 ++++++- .../static/js/erd_tool/nodes/TableNode.jsx | 38 ++++++- .../javascript/erd/onetomany_link_spec.js | 44 +++++++- 12 files changed, 334 insertions(+), 19 deletions(-) create mode 100644 docs/en_US/images/erd_11_dialog.png create mode 100644 web/pgadmin/tools/erd/static/js/erd_tool/dialogs/OneToOneDialog.js diff --git a/docs/en_US/erd_tool.rst b/docs/en_US/erd_tool.rst index 954c169cf..ea1a8c815 100644 --- a/docs/en_US/erd_tool.rst +++ b/docs/en_US/erd_tool.rst @@ -207,6 +207,22 @@ The table node shows table details in a graphical representation: * you can click on the node and drag to move on the canvas. * Upon double click on the table node or by clicking the edit button from the toolbar, the table dialog opens where you can change the table details. Refer :ref:`table dialog ` for information on different fields. +The One to One Link Dialog +*************************** + +.. image:: images/erd_11_dialog.png + :alt: ERD tool 1-1 dialog + :align: center + +The one to one link dialog allows you to: + +* Add a one to one relationship between two tables. +* *Local Table* is the table that references a table and has the *one* end point. +* *Local Column* the column that references. +* *Select Constraint* To implement one to one relationship, the *Local Column* must have primaty key or unique constraint. The default is a unique constraint. Please note that this field is visible only when the selected *Local Column* does not have either of the mentioned constraints. +* *Referenced Table* is the table that is being referred and has the *one* end point. +* *Referenced Column* the column that is being referred. + The One to Many Link Dialog *************************** diff --git a/docs/en_US/images/erd_11_dialog.png b/docs/en_US/images/erd_11_dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..bd14d0f28b39418cfb72239830a546105ab308f5 GIT binary patch literal 89174 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 ! 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

L&59-8IllW3@q<>*&>~HOS(m;Iuq`h~9 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�g9Y)*CD^vq%@*2f1hH75=EqOft!Y_r1Wb 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 - let existPort = tableNode.getPort(tableNode.getPortName(col.attnum)); - if(existPort) { - Object.values(existPort.getLinks()).forEach((link)=>{ - self.removeOneToManyLink(link); - }); - tableNode.removePort(existPort); - } + this.getLeftRightPorts(tableNode, col.attnum).forEach(port => { + if (port) { + Object.values(port.getLinks()).forEach(link => { + self.removeOneToManyLink(link); + }); + tableNode.removePort(port); + } + }); + }); + Object.values(tableNode.getLinks()).forEach(link=>{ + link.fireEvent({},'updateLink'); }); } @@ -482,6 +485,31 @@ export default class ERDCore { columns: [col], }) ); + // Below logic is to add one to one relationship + if(onetomanyData.constraint_type === 'primary_key') { + let newPk = new PrimaryKeySchema({},{}); + let pkCol = {}; + let column = _.find(targetNode.getColumns(), (colm)=>colm.attnum==onetomanyData.local_column_attnum); + column.is_primary_key = true; + pkCol.column =column.name; + tableData.primary_key = tableData.primary_key || []; + tableData.primary_key.push( + newPk.getNewData({ + columns: [pkCol] + }) + ); + + } else if (onetomanyData.constraint_type === 'unique') { + let newUk = new UniqueConstraintSchema({},{}); + let ukCol = {}; + ukCol.column = _.find(targetNode.getColumns(), (colm)=>colm.attnum==onetomanyData.local_column_attnum).name; + tableData.unique_constraint = tableData.unique_constraint || []; + tableData.unique_constraint.push( + newUk.getNewData({ + columns: [ukCol] + }) + ); + } targetNode.setData(tableData); let newLink = this.addLink(onetomanyData, 'onetomany'); this.clearSelection(); diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx index 51bc3d02e..5154cf448 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx @@ -145,7 +145,7 @@ export default class ERDTool extends React.Component { _.bindAll(this, ['onLoadDiagram', 'onSaveDiagram', 'onSQLClick', 'onImageClick', 'onAddNewNode', 'onEditTable', 'onCloneNode', 'onDeleteNode', 'onNoteClick', - 'onNoteClose', 'onOneToManyClick', 'onManyToManyClick', 'onAutoDistribute', 'onDetailsToggle', + 'onNoteClose', 'onOneToOneClick', 'onOneToManyClick', 'onManyToManyClick', 'onAutoDistribute', 'onDetailsToggle', 'onChangeColors', 'onDropNode', 'onNotationChange', 'closePanel' ]); @@ -220,6 +220,7 @@ export default class ERDTool extends React.Component { this.eventBus.registerListener(ERD_EVENTS.CLONE_NODE, this.onCloneNode); this.eventBus.registerListener(ERD_EVENTS.DELETE_NODE, this.onDeleteNode); this.eventBus.registerListener(ERD_EVENTS.SHOW_NOTE, this.onNoteClick); + this.eventBus.registerListener(ERD_EVENTS.ONE_TO_ONE, this.onOneToOneClick); this.eventBus.registerListener(ERD_EVENTS.ONE_TO_MANY, this.onOneToManyClick); this.eventBus.registerListener(ERD_EVENTS.MANY_TO_MANY, this.onManyToManyClick); this.eventBus.registerListener(ERD_EVENTS.AUTO_DISTRIBUTE, this.onAutoDistribute); @@ -265,6 +266,9 @@ export default class ERDTool extends React.Component { [this.state.preferences.add_edit_note, ()=>{ this.eventBus.fireEvent(ERD_EVENTS.SHOW_NOTE); }], + [this.state.preferences.one_to_one, ()=>{ + this.eventBus.fireEvent(ERD_EVENTS.ONE_TO_ONE); + }], [this.state.preferences.one_to_many, ()=>{ this.eventBus.fireEvent(ERD_EVENTS.ONE_TO_MANY); }], @@ -397,7 +401,7 @@ export default class ERDTool extends React.Component { serverInfo, callback }); }; - } else if(dialogName === 'onetomany_dialog' || dialogName === 'manytomany_dialog') { + } else if(dialogName === 'onetomany_dialog' || dialogName === 'manytomany_dialog' || dialogName === 'onetoone_dialog') { return (title, attributes, callback)=>{ this.erdDialogs.showRelationDialog(dialogName, { title, attributes, tableNodes: this.diagram.getModel().getNodesDict(), @@ -429,6 +433,17 @@ export default class ERDTool extends React.Component { if(this.diagram.anyDuplicateNodeName(newData, oldData)) { return gettext('Table name already exists'); } + // If a column that is part of a foreign key is removed, the foreign key constraint should also be removed. + _.differenceWith(oldData.columns, newData.columns, function(existing, incoming) { + return existing.attnum == incoming.attnum; + }).forEach(colm=>{ + newData.foreign_key?.forEach((theFkRow, index)=>{ + let fkCols = theFkRow.columns[0]; + if (fkCols.local_column === colm.name) { + newData.foreign_key.splice(index,1); + } + }); + }); node.setData(newData); this.diagram.syncTableLinks(node, oldData); this.diagram.repaint(); @@ -774,6 +789,14 @@ export default class ERDTool extends React.Component { }, 1000); } + onOneToOneClick() { + let dialog = this.getDialog('onetoone_dialog'); + let initData = {local_table_uid: this.diagram.getSelectedNodes()[0].getID()}; + dialog(gettext('One to one relation'), initData, (newData)=>{ + this.diagram.addOneToManyLink(newData); + }); + } + onOneToManyClick() { let dialog = this.getDialog('onetomany_dialog'); let initData = {local_table_uid: this.diagram.getSelectedNodes()[0].getID()}; diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx index 200b6f250..a2bc51837 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx @@ -54,6 +54,7 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati 'save': true, 'edit-table': true, 'clone-table': true, + 'one-to-one': true, 'one-to-many': true, 'many-to-many': true, 'show-note': true, @@ -121,6 +122,7 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati [ERD_EVENTS.SINGLE_NODE_SELECTED, (selected)=>{ setDisableButton('edit-table', !selected); setDisableButton('clone-table', !selected); + setDisableButton('one-to-one', !selected); setDisableButton('one-to-many', !selected); setDisableButton('many-to-many', !selected); setDisableButton('show-note', !selected); @@ -210,12 +212,17 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati }} /> - 1M} + 1 - 1} + shortcut={preferences.one_to_one} disabled={buttonsDisabled['one-to-one']} + onClick={()=>{ + eventBus.fireEvent(ERD_EVENTS.ONE_TO_ONE); + }} /> + 1 - M} shortcut={preferences.one_to_many} disabled={buttonsDisabled['one-to-many']} onClick={()=>{ eventBus.fireEvent(ERD_EVENTS.ONE_TO_MANY); }} /> - MM} + M - M} shortcut={preferences.many_to_many} disabled={buttonsDisabled['many-to-many']} onClick={()=>{ eventBus.fireEvent(ERD_EVENTS.MANY_TO_MANY); diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/dialogs/OneToOneDialog.js b/web/pgadmin/tools/erd/static/js/erd_tool/dialogs/OneToOneDialog.js new file mode 100644 index 000000000..eb1b233ee --- /dev/null +++ b/web/pgadmin/tools/erd/static/js/erd_tool/dialogs/OneToOneDialog.js @@ -0,0 +1,106 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2024, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// + +import gettext from 'sources/gettext'; +import { isEmptyString } from 'sources/validators'; +import BaseUISchema from 'sources/SchemaView/base_schema.ui'; +import _ from 'lodash'; + +class OneToOneSchema extends BaseUISchema { + constructor(fieldOptions={}, initValues={}, localTableData={}) { + super({ + local_table_uid: undefined, + local_column_attnum: undefined, + referenced_table_uid: undefined, + referenced_column_attnum: undefined, + constraint_type: undefined, + ...initValues, + }); + this.fieldOptions = fieldOptions; + this.localTableData = localTableData; + } + + isVisible (state) { + let colName = _.find(this.localTableData.getData().columns, col => col.attnum === state.local_column_attnum)?.name; + let {pkCols, ukCols} = this.localTableData.getConstraintCols(); + return !((pkCols.includes(colName) || ukCols.includes(colName)) || isEmptyString(state.local_column_attnum)); + } + get baseFields() { + return [{ + id: 'local_table_uid', label: gettext('Local Table'), + type: 'select', readonly: true, controlProps: {allowClear: false}, + options: this.fieldOptions.local_table_uid, + },{ + id: 'local_column_attnum', label: gettext('Local Column'), + type: 'select', options: this.fieldOptions.local_column_attnum, + controlProps: {allowClear: false}, noEmpty: true, + },{ + id: 'constraint_type', label: gettext('Select constraint'), + type: 'toggle', deps: ['local_column_attnum'], + options: [ + {label: 'Primary Key', value: 'primary_key'}, + {label: 'Unique', value: 'unique'}, + ], + visible: this.isVisible, + depChange: (state, source)=>{ + if (source[0] === 'local_column_attnum' && this.isVisible(state)) { + return {constraint_type: 'unique'}; + } else if (source[0] === 'local_column_attnum') { + return {constraint_type: ''}; + } + }, helpMessage: gettext('A constraint is required to implement One to One relationship.') + }, { + id: 'referenced_table_uid', label: gettext('Referenced Table'), + type: 'select', options: this.fieldOptions.referenced_table_uid, + controlProps: {allowClear: false}, noEmpty: true, + },{ + id: 'referenced_column_attnum', label: gettext('Referenced Column'), + controlProps: {allowClear: false}, deps: ['referenced_table_uid'], noEmpty: true, + type: (state)=>({ + type: 'select', + options: state.referenced_table_uid ? ()=>this.fieldOptions.getRefColumns(state.referenced_table_uid) : [], + optionsReloadBasis: state.referenced_table_uid, + }), + }]; + } + + validate(state, setError) { + let tableData = this.localTableData.getData(); + if (tableData.primary_key.length && state.constraint_type === 'primary_key') { + setError('constraint_type', gettext('Primary key already exists, please select different constraint.')); + return true; + } + return false; + } +} + +export function getOneToOneDialogSchema(attributes, tableNodesDict) { + let tablesData = []; + _.forEach(tableNodesDict, (node, uid)=>{ + let [schema, name] = node.getSchemaTableName(); + tablesData.push({value: uid, label: `(${schema}) ${name}`, image: 'icon-table'}); + }); + + return new OneToOneSchema({ + local_table_uid: tablesData, + local_column_attnum: tableNodesDict[attributes.local_table_uid].getColumns().map((col)=>{ + return { + value: col.attnum, label: col.name, 'image': 'icon-column', + }; + }), + referenced_table_uid: tablesData, + getRefColumns: (uid)=>{ + return tableNodesDict[uid].getColumns().map((col)=>{ + return { + value: col.attnum, label: col.name, 'image': 'icon-column', + }; + }); + }, + }, attributes, tableNodesDict[attributes.local_table_uid]); +} diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/dialogs/index.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/dialogs/index.jsx index f46d43ebe..5241cea75 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/dialogs/index.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/dialogs/index.jsx @@ -10,6 +10,7 @@ import {getTableDialogSchema} from './TableDialog'; import {getOneToManyDialogSchema} from './OneToManyDialog'; import {getManyToManyDialogSchema} from './ManyToManyDialog'; +import {getOneToOneDialogSchema} from './OneToOneDialog'; import pgAdmin from 'sources/pgadmin'; import SchemaView from '../../../../../../static/js/SchemaView'; @@ -67,6 +68,8 @@ export default class ERDDialogs { schema = getOneToManyDialogSchema(params.attributes, params.tableNodes); } else if(dialogName === 'manytomany_dialog') { schema = getManyToManyDialogSchema(params.attributes, params.tableNodes); + } else if(dialogName === 'onetoone_dialog') { + schema = getOneToOneDialogSchema(params.attributes, params.tableNodes); } this.modal.showModal(params.title, (closeModal)=>{ diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/links/OneToManyLink.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/links/OneToManyLink.jsx index a3a0f0734..424e3fa94 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/links/OneToManyLink.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/links/OneToManyLink.jsx @@ -45,6 +45,10 @@ export class OneToManyLinkModel extends RightAngleLinkModel { this._data = { ...data, }; + this._linkPointType = { + sourceType: 'one', + targetType: 'many' + }; } getData() { @@ -77,6 +81,22 @@ export class OneToManyLinkModel extends RightAngleLinkModel { data: this.getData(), }; } + + setPointType(nodesDict) { + let data = this.getData(); + let target = nodesDict[data['local_table_uid']].getData(); + let colName = _.find(target.columns, (col)=>data.local_column_attnum == col.attnum).name; + let {pkCols=[], ukCols=[]} = nodesDict[data['local_table_uid']].getConstraintCols(); + let targetType = pkCols.includes(colName) || ukCols.includes(colName) ? 'one' : 'many'; + this._linkPointType = { + ...this._linkPointType, + targetType, + }; + } + + getPointType() { + return this._linkPointType; + } } const svgLinkSelected = keyframes` @@ -173,6 +193,22 @@ CustomLinkEndWidget.propTypes = { export class OneToManyLinkWidget extends RightAngleLinkWidget { constructor(props) { super(props); + this.state = {}; + this.setPointType(); + this.updateLinkListener = this.props.link.registerListener({ + updateLink: ()=>{ + this.setPointType(); + this.setState({}); + } + }); + } + + componentWillUnmount() { + this.props.link.deregisterListener(this.updateLinkListener); + } + + setPointType() { + this.props.link.setPointType(this.props.diagramEngine.getModel().getNodesDict()); } endPointTranslation(alignment) { @@ -259,9 +295,10 @@ export class OneToManyLinkWidget extends RightAngleLinkWidget { //ensure id is present for all points on the path let points = this.props.link.getPoints(); let paths = []; + let {sourceType, targetType} = this.props.link.getPointType(); - let onePoint = this.addCustomWidgetPoint('one', this.props.link.getSourcePort(), points[0]); - let manyPoint = this.addCustomWidgetPoint('many', this.props.link.getTargetPort(), points[points.length-1]); + let onePoint = this.addCustomWidgetPoint(sourceType, this.props.link.getSourcePort(), points[0]); + let manyPoint = this.addCustomWidgetPoint(targetType, this.props.link.getTargetPort(), points[points.length-1]); if (!this.state.canDrag && points.length > 2) { // Those points and its position only will be moved diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx index a1f412737..a49996968 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx @@ -44,6 +44,7 @@ export class TableNodeModel extends DefaultNodeModel { is_promise: Boolean(otherInfo.data?.then || (otherInfo.metadata?.data_failed && !otherInfo.data)), }; this._data = null; + this._constraintCols = {}; if(otherInfo.data?.then) { otherInfo.data.then((data)=>{ /* Once the data is available, it is no more a promise */ @@ -53,6 +54,7 @@ export class TableNodeModel extends DefaultNodeModel { data_failed: false, is_promise: false, }; + this.generateOnetoOneData(data); this.fireEvent(this._metadata, 'dataAvaiable'); this.fireEvent({}, 'nodeUpdated'); this.fireEvent({}, 'selectionChanged'); @@ -69,6 +71,7 @@ export class TableNodeModel extends DefaultNodeModel { columns: [], ...otherInfo.data, }; + this.generateOnetoOneData(otherInfo.data); } } @@ -132,6 +135,7 @@ export class TableNodeModel extends DefaultNodeModel { setData(data) { this._data = data; + this.generateOnetoOneData(data); this.fireEvent({}, 'nodeUpdated'); } @@ -164,6 +168,34 @@ export class TableNodeModel extends DefaultNodeModel { }, }; } + + setConstraintCols(colsData) { + this._constraintCols = colsData; + } + + getConstraintCols() { + return this._constraintCols; + } + + generateOnetoOneData = (tableData) => { + if (tableData){ + let ukCols = [], pkCols = []; + (tableData.unique_constraint||[]).forEach((uk)=>{ + if(uk.columns.length === 1){ + ukCols.push(...uk.columns.map((c)=>c.column)); + } + }); + (tableData.primary_key||[]).forEach((pk)=>{ + if(pk.columns.length === 1){ + pkCols.push(...pk.columns.map((c)=>c.column)); + } + }); + this.setConstraintCols({ + ukCols, + pkCols + }); + } + }; } function RowIcon({icon}) { @@ -239,7 +271,7 @@ export class TableNodeWidget extends React.Component { show_details: true, }; - this.props.node.registerListener({ + this.tableNodeEventListener = this.props.node.registerListener({ toggleDetails: (event) => { this.setState({show_details: event.show_details}); }, @@ -256,6 +288,10 @@ export class TableNodeWidget extends React.Component { }); } + componentWillUnmount() { + this.props.node.deregisterListener(this.tableNodeEventListener); + } + generateColumn(col, localFkCols, localUkCols) { let leftPort = this.props.node.getPort(this.props.node.getPortName(col.attnum, PortModelAlignment.LEFT)); let rightPort = this.props.node.getPort(this.props.node.getPortName(col.attnum, PortModelAlignment.RIGHT)); diff --git a/web/regression/javascript/erd/onetomany_link_spec.js b/web/regression/javascript/erd/onetomany_link_spec.js index f3863928b..fa44de59c 100644 --- a/web/regression/javascript/erd/onetomany_link_spec.js +++ b/web/regression/javascript/erd/onetomany_link_spec.js @@ -15,6 +15,7 @@ import { import OneToManyPortModel from 'pgadmin.tools.erd/erd_tool/ports/OneToManyPort'; import {OneToManyLinkModel, OneToManyLinkWidget, OneToManyLinkFactory} from 'pgadmin.tools.erd/erd_tool/links/OneToManyLink'; +import ERDModel from 'pgadmin.tools.erd/erd_tool/ERDModel'; import { render } from '@testing-library/react'; import Theme from '../../../pgadmin/static/js/Theme'; @@ -108,14 +109,14 @@ describe('ERD OneToManyLinkModel', ()=>{ describe('ERD OneToManyLinkWidget', ()=>{ let linkFactory = new OneToManyLinkFactory(); + let model = new ERDModel(); let engine = { getFactoryForLink: ()=>linkFactory, + getModel: ()=>model }; let link = null; beforeEach(()=>{ - - link = new OneToManyLinkModel({ color: '#000', data: { @@ -129,6 +130,45 @@ describe('ERD OneToManyLinkWidget', ()=>{ link.setTargetPort(new OneToManyPortModel({options: {}})); }); + jest.spyOn(model, 'getNodes').mockReturnValue([ + { + name: 'test1', + getID: function() { + return 'id1'; + }, + getData: function(){ return { + 'name': 'table1', + 'schema': 'erd1', + 'columns': [ + {'name': 'col11', attnum: 0}, + {'name': 'col12', attnum: 1}, + ], + };}, + getConstraintCols: function(){ return { + ukCols: [], + pkCols: [] + };} + }, + { + name: 'test2', + getID: function() { + return 'id2'; + }, + getData: function(){ return { + 'name': 'table2', + 'schema': 'erd2', + 'columns': [ + {'name': 'col21', attnum: 0}, + {'name': 'col22', attnum: 1}, + ], + };}, + getConstraintCols: function(){ return { + ukCols: [], + pkCols: [] + };} + }, + ]); + it('render', ()=>{ let linkWidget = render(