diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/unique_constraint.svg b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/unique_constraint.svg index 2fb31e358..7a1f42b88 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/unique_constraint.svg +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/unique_constraint.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.ui.js index 93fe02712..0197f6671 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.ui.js @@ -87,8 +87,8 @@ export class ConstraintsSchema extends BaseUISchema { changeColumnOptions(colOptions) { this.primaryKeyObj.changeColumnOptions(colOptions); this.fkObj.changeColumnOptions(colOptions); + this.uniqueConsObj.changeColumnOptions(colOptions); if(!this.inErd) { - this.uniqueConsObj.changeColumnOptions(colOptions); this.exConsObj.changeColumnOptions(colOptions); } } @@ -163,7 +163,7 @@ export class ConstraintsSchema extends BaseUISchema { columns : ['name', 'consrc'], disabled: this.inCatalog, },{ - id: 'unique_group', type: 'group', label: gettext('Unique'), visible: !this.inErd, + id: 'unique_group', type: 'group', label: gettext('Unique'), },{ id: 'unique_constraint', label: '', schema: this.uniqueConsObj, @@ -338,7 +338,7 @@ export default class TableSchema extends BaseUISchema { const SUPPORTED_KEYS = [ 'name', 'schema', 'description', 'rlspolicy', 'forcerlspolicy', 'fillfactor', 'toast_tuple_target', 'parallel_workers', 'relhasoids', 'relpersistence', - 'columns', 'primary_key', 'foreign_key', + 'columns', 'primary_key', 'foreign_key', 'unique_constraint', ]; newData = _.pick(newData, SUPPORTED_KEYS); @@ -975,7 +975,7 @@ export default class TableSchema extends BaseUISchema { id: 'seclabels', label: gettext('Security labels'), canEdit: false, schema: new SecLabelSchema(), editable: false, canAdd: true, type: 'collection', min_version: 90100, mode: ['edit', 'create'], - group: 'security_group', canDelete: true, control: 'unique-col-collection', + group: 'security_group', canDelete: true, },{ id: 'vacuum_settings_str', label: gettext('Storage settings'), type: 'multiline', group: 'advanced', mode: ['properties'], diff --git a/web/pgadmin/static/js/Theme/index.jsx b/web/pgadmin/static/js/Theme/index.jsx index da58fafa8..d2a070f15 100644 --- a/web/pgadmin/static/js/Theme/index.jsx +++ b/web/pgadmin/static/js/Theme/index.jsx @@ -200,7 +200,7 @@ basicSettings = createMuiTheme(basicSettings, { create: () => 'none', }, zIndex: { - modal: 2000, + modal: 3001, }, props: { MuiTextField: { 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 0265668a9..5048ffb3c 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js +++ b/web/pgadmin/tools/erd/static/js/erd_tool/ERDCore.js @@ -268,10 +268,55 @@ export default class ERDCore { } syncTableLinks(tableNode, oldTableData) { + let self = this; let tableData = tableNode.getData(); - let tableNodesDict = this.getModel().getNodesDict(); + const tableNodesDict = this.getModel().getNodesDict(); + + /* Remove the links if column dropped or primary key removed */ + _.differenceWith(oldTableData.columns, tableData.columns, function(existing, incoming) { + if(existing.attnum == incoming.attnum && existing.is_primary_key && !incoming.is_primary_key) { + return false; + } + return existing.attnum == incoming.attnum; + }).forEach((col)=>{ + let existPort = tableNode.getPort(tableNode.getPortName(col.attnum)); + if(existPort) { + Object.values(existPort.getLinks()).forEach((link)=>{ + self.removeOneToManyLink(link); + }); + } + tableNode.removePort(existPort); + }); + + /* Sync the name changes in references FK */ + Object.values(tableNode.getPorts()).forEach((port)=>{ + if(port.getSubtype() != 'one') { + return; + } + Object.values(port.getLinks()).forEach((link)=>{ + let linkData = link.getData(); + let fkTableNode = this.getModel().getNodesDict()[linkData.local_table_uid]; + + let newForeingKeys = []; + fkTableNode.getData().foreign_key?.forEach((theFkRow)=>{ + for(let fkColumn of theFkRow.columns) { + let attnum = _.find(oldTableData.columns, (c)=>c.name==fkColumn.referenced).attnum; + fkColumn.referenced = _.find(tableData.columns, (colm)=>colm.attnum==attnum).name; + fkColumn.references_table_name = tableData.name; + } + newForeingKeys.push(theFkRow); + }); + fkTableNode.setData({ + ...fkTableNode.getData(), + foreign_key: newForeingKeys, + }); + }); + }); + /* Sync the changed/removed/added foreign keys */ + tableData = tableNode.getData(); const addLink = (theFk)=>{ + if(!theFk) return; let newData = { local_table_uid: tableNode.getID(), local_column_attnum: undefined, @@ -287,6 +332,7 @@ export default class ERDCore { }; const removeLink = (theFk)=>{ + if(!theFk) return; let attnum = _.find(tableNode.getColumns(), (col)=>col.name==theFk.local_column).attnum; let existPort = tableNode.getPort(tableNode.getPortName(attnum)); if(existPort && existPort.getSubtype() == 'many') { @@ -316,9 +362,12 @@ export default class ERDCore { tableData.foreign_key[rowIndx].columns, 'cid' ); - if(changeDiffCols.removed.length > 0 || changeDiffCols.added.length > 0) { - removeLink(changeDiffCols.removed[0]); - addLink(changeDiffCols.added[0]); + if(changeDiffCols.removed.length > 0) { + /* any change in columns length remove all and create new link */ + oldTableData.foreign_key[rowIndx].columns.forEach((col)=>{ + removeLink(col); + }); + addLink(tableData.foreign_key[rowIndx].columns[0]); } } } 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 7dcfe5aa3..8c3686f09 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 @@ -17,6 +17,7 @@ import TableIcon from 'top/browser/server_groups/servers/databases/schemas/table import PrimaryKeyIcon from 'top/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/primary_key.svg'; import ForeignKeyIcon from 'top/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/img/foreign_key.svg'; import ColumnIcon from 'top/browser/server_groups/servers/databases/schemas/tables/columns/static/img/column.svg'; +import UniqueKeyIcon from 'top/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/img/unique_constraint.svg'; import PropTypes from 'prop-types'; import gettext from 'sources/gettext'; @@ -94,17 +95,6 @@ export class TableNodeModel extends DefaultNodeModel { } setData(data) { - let self = this; - /* Remove the links if column dropped or primary key removed */ - _.differenceWith(this._data.columns, data.columns, function(existing, incoming) { - return existing.attnum == incoming.attnum && incoming.is_primary_key == true; - }).forEach((col)=>{ - let existPort = self.getPort(self.getPortName(col.attnum)); - if(existPort && existPort.getSubtype() == 'one') { - existPort.removeAllLinks(); - self.removePort(existPort); - } - }); this._data = data; this.fireEvent({}, 'nodeUpdated'); } @@ -172,18 +162,23 @@ export class TableNodeWidget extends React.Component { }); } - generateColumn(col, tableData) { + generateColumn(col, localFkCols, localUkCols) { let port = this.props.node.getPort(this.props.node.getPortName(col.attnum)); let icon = ColumnIcon; - let localFkCols = []; - (tableData.foreign_key||[]).forEach((fk)=>{ - localFkCols.push(...fk.columns.map((c)=>c.local_column)); - }); + /* Less priority */ + if(localUkCols.indexOf(col.name) > -1) { + icon = UniqueKeyIcon; + } if(col.is_primary_key) { icon = PrimaryKeyIcon; } else if(localFkCols.indexOf(col.name) > -1) { icon = ForeignKeyIcon; } + + let cltype = col.cltype; + if(col.attlen) { + cltype += '('+ col.attlen + (col.attprecision ? ',' + col.attprecision : '') +')'; + } return (