Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/en_US/release_notes_9_16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Bug fixes
| `Issue #6308 <https://github.com/pgadmin-org/pgadmin4/issues/6308>`_ - Fix the infinite loading spinner after an idle database connection is silently dropped, by detecting stale connections and offering a reconnect dialog.
| `Issue #7596 <https://github.com/pgadmin-org/pgadmin4/issues/7596>`_ - Fix the Query Tool turning into a blank white screen when the runtime has a malformed default locale, by guarding the Query History date/time formatting against the resulting RangeError.
| `Issue #8318 <https://github.com/pgadmin-org/pgadmin4/issues/8318>`_ - Fixed an error ("i.default.find(...) is undefined") that prevented deleting a table or relationship link in the ERD tool when a foreign key referenced a column that had been renamed.
| `Issue #9060 <https://github.com/pgadmin-org/pgadmin4/issues/9060>`_ - Fixed an issue in the Create Table dialog where renaming a column did not update the column references in foreign key and unique constraint definitions for the new table.
| `Issue #9091 <https://github.com/pgadmin-org/pgadmin4/issues/9091>`_ - Fix the Query Tool re-prompting for an unsaved password in a loop and rejecting the re-entered password, by caching the entered password on the server manager when the primary connection is already established.
| `Issue #9128 <https://github.com/pgadmin-org/pgadmin4/issues/9128>`_ - Fixed an issue where the object breadcrumbs popup blocked clicks on the object explorer items beneath it.
| `Issue #9595 <https://github.com/pgadmin-org/pgadmin4/issues/9595>`_ - Fix missing ALTER ... SET DEFAULT statements for inherited columns in the generated table SQL/EDIT script.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,25 @@ export class ConstraintsSchema extends BaseUISchema {
disabled: this.inCatalog,
canAddRow: obj.anyColumnAdded,
expandEditOnAdd: true,
depChange: (state)=>{
depChange: (state, source, topState, actionObj)=>{
if (state.is_partitioned && obj.top.getServerVersion() < 110000 || state.columns?.length <= 0) {
return {foreign_key: []};
}
/* If a column is renamed, sync the foreign key local column references. #9060 */
if(actionObj.type == SCHEMA_STATE_ACTIONS.SET_VALUE && actionObj.path[0] == 'columns' &&
actionObj.path[actionObj.path.length-1] == 'name' && state.oid === undefined &&
state.foreign_key?.length) {
let oldName = actionObj.oldState.columns[actionObj.path[1]]?.name,
newName = _.get(state, _.slice(actionObj.path, 0, -1))?.name;
if(oldName && newName && oldName !== newName) {
return {foreign_key: state.foreign_key.map((fk)=>({
...fk,
columns: fk.columns?.map((c)=>(
c.local_column === oldName ? {...c, local_column: newName} : c
)),
}))};
}
Comment thread
asheshv marked this conversation as resolved.
}
}
},{
id: 'check_group', type: 'group', label: gettext('Check'), visible: !this.inErd,
Expand All @@ -223,18 +238,34 @@ export class ConstraintsSchema extends BaseUISchema {
schema: this.uniqueConsObj,
editable: false, type: 'collection',
group: 'unique_group', mode: ['edit', 'create'],
canEdit: true, canDelete: true, deps:['is_partitioned', 'typname'],
canEdit: true, canDelete: true, deps:['is_partitioned', 'typname', 'columns'],
columns : ['name', 'columns'],
disabled: this.inCatalog,
canAdd: function(state) {
return obj.canAdd(state);
},
canAddRow: obj.anyColumnAdded,
expandEditOnAdd: true,
depChange: (state)=>{
depChange: (state, source, topState, actionObj)=>{
if (state.is_partitioned && obj.top.getServerVersion() < 110000 || state.columns?.length <= 0) {
return {unique_constraint: []};
}
/* If a column is renamed, sync the unique constraint column references. #9060 */
if(actionObj.type == SCHEMA_STATE_ACTIONS.SET_VALUE && actionObj.path[0] == 'columns' &&
actionObj.path[actionObj.path.length-1] == 'name' && state.oid === undefined &&
state.unique_constraint?.length) {
let oldName = actionObj.oldState.columns[actionObj.path[1]]?.name,
newName = _.get(state, _.slice(actionObj.path, 0, -1))?.name;
if(oldName && newName && oldName !== newName) {
return {unique_constraint: state.unique_constraint.map((uc)=>({
...uc,
columns: uc.columns?.map((c)=>(
c.column === oldName ? {...c, column: newName} : c
)),
include: uc.include?.map((c)=>(c === oldName ? newName : c)),
}))};
}
}
}
},{
id: 'exclude_group', type: 'group', label: gettext('Exclude'), visible: !this.inErd,
Expand Down
83 changes: 83 additions & 0 deletions web/regression/javascript/schema_ui_files/table.ui.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,89 @@ describe('TableSchema', () => {
});
});

it('depChange column rename propagation', () => {
jest.spyOn(schemaObj, 'getServerVersion').mockReturnValue(110000);
schemaObj.constraintsObj.top = schemaObj;

let actionObj = {
type: SCHEMA_STATE_ACTIONS.SET_VALUE,
path: ['columns', 0, 'name'],
oldState: {
columns: [{ name: 'old_col' }],
},
};

// Foreign key local_column should be renamed (Create path only).
let fkState = {
oid: undefined,
is_partitioned: false,
columns: [{ name: 'new_col' }],
foreign_key: [{
name: 'fk1',
columns: [
{ local_column: 'old_col', referenced: 'r1' },
{ local_column: 'other', referenced: 'r2' },
],
}],
};
expect(getFieldDepChange(schemaObj.constraintsObj, 'foreign_key')(
fkState, ['columns'], null, actionObj)).toEqual({
foreign_key: [{
name: 'fk1',
columns: [
{ local_column: 'new_col', referenced: 'r1' },
{ local_column: 'other', referenced: 'r2' },
],
}],
});

// Unique constraint columns should be renamed.
let ucState = {
oid: undefined,
is_partitioned: false,
columns: [{ name: 'new_col' }],
unique_constraint: [{
name: 'uc1',
columns: [
{ column: 'old_col' },
{ column: 'other' },
],
include: ['inc1', 'inc2'],
}],
};
expect(getFieldDepChange(schemaObj.constraintsObj, 'unique_constraint')(
ucState, ['columns'], null, actionObj)).toEqual({
unique_constraint: [{
name: 'uc1',
columns: [
{ column: 'new_col' },
{ column: 'other' },
],
include: ['inc1', 'inc2'],
}],
});

// Unique constraint INCLUDE list should be renamed too (Fix #9060).
let ucIncludeState = {
oid: undefined,
is_partitioned: false,
columns: [{ name: 'new_col' }],
unique_constraint: [{
name: 'uc2',
columns: [{ column: 'keycol' }],
include: ['old_col', 'inc2'],
}],
};
expect(getFieldDepChange(schemaObj.constraintsObj, 'unique_constraint')(
ucIncludeState, ['columns'], null, actionObj)).toEqual({
unique_constraint: [{
name: 'uc2',
columns: [{ column: 'keycol' }],
include: ['new_col', 'inc2'],
}],
});
});

it('validate', () => {
let state = {is_partitioned: true};
let setError = jest.fn();
Expand Down
Loading