Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -129,60 +129,47 @@ export default class ForeignTableSchema extends BaseUISchema {
options: obj.fieldOptions.tables,
optionsLoaded: (res)=>obj.inheritedTableList=res,
deferredDepChange: (state, source, topState, actionObj)=>{
return new Promise((resolve)=>{
// current table list and previous table list
let newColInherits = state.inherits || [];
let oldColInherits = actionObj.oldState.inherits || [];

let tabName;
let tabColsResponse;

// Add columns logic
// If new table is added in list
if(newColInherits.length > 1 && newColInherits.length > oldColInherits.length) {
// Find newly added table from current list
tabName = _.difference(newColInherits, oldColInherits);
tabColsResponse = obj.getColumns({attrelid: this.getTableOid(tabName[0])});
} else if (newColInherits.length == 1) {
// First table added
tabColsResponse = obj.getColumns({attrelid: this.getTableOid(newColInherits[0])});
}

if(tabColsResponse) {
tabColsResponse.then((res)=>{
resolve((tmpstate)=>{
let finalCols = res.map((col)=>obj.columnsObj.getNewData(col));
finalCols = [...tmpstate.columns, ...finalCols];
return {
adding_inherit_cols: false,
columns: finalCols,
};
});
});
}
const newColInherits = state.inherits || [];
const oldColInherits = actionObj.oldState.inherits || [];
const added = _.difference(newColInherits, oldColInherits);
const removed = _.difference(oldColInherits, newColInherits);

// REMOVE takes precedence: any removed parent means stale
// columns to clean up. Covers pure shrink AND same-length
// swap (e.g. multi-select replace) — without this branch a
// swap would leave the removed parent's columns sitting in
// the grid until the user did something else.
if(removed.length > 0) {
const removeOid = this.getTableOid(removed[0]);
// Guard: if inheritedTableList is stale and the removed
// table can't be resolved to an OID, opt out. Filtering on
// `inheritedid != undefined` would silently drop local
// user-added columns (`null == undefined` in JS).
if(removeOid == null) return undefined;
return Promise.resolve((tmpstate)=>({
adding_inherit_cols: false,
columns: (tmpstate.columns || [])
.filter((col)=>col.inheritedid != removeOid),
}));
}

// Remove columns logic
let removeOid;
if(newColInherits.length > 0 && newColInherits.length < oldColInherits.length) {
// Find deleted table from previous list
tabName = _.difference(oldColInherits, newColInherits);
removeOid = this.getTableOid(tabName[0]);
} else if (oldColInherits.length === 1 && newColInherits.length < 1) {
// We got last table from list
tabName = oldColInherits[0];
removeOid = this.getTableOid(tabName);
}
if(removeOid) {
resolve((tmpstate)=>{
let finalCols = tmpstate.columns;
_.remove(tmpstate.columns, (col)=>col.inheritedid==removeOid);
// Pure ADD: list grew without any removals.
if(added.length > 0) {
const fetchOid = this.getTableOid(added[0]);
if(fetchOid == null) return undefined;
return obj.getColumns({attrelid: fetchOid}).then((res)=>(
(tmpstate)=>{
const fetched = res.map((col)=>obj.columnsObj.getNewData(col));
return {
adding_inherit_cols: false,
columns: finalCols
columns: [...(tmpstate.columns || []), ...fetched],
};
});
}
});
}
));
}

// Lists are equivalent — no work to do.
return undefined;
},
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,21 @@ export default class ColumnSchema extends BaseUISchema {
}

if(this.nodeInfo && ('schema' in this.nodeInfo)) {
if(this.isNew(state)) {
return false;
}

// We will disable control if it's system columns
// inheritedfrom check is useful when we use this schema in table node
// inheritedfrom has value then we should disable it
// Parent-table inheritance locks the column in BOTH create and
// edit modes — its Name and datatype mirror the parent. The
// `isNew(state)` shortcut below must NOT run first, otherwise
// inherited columns become editable on a fresh child-table
// dialog. (`OF TYPE` inheritance uses `inheritedfromtype` and is
// handled by the dedicated `editable` callback further down —
// not by this method.)
if (!isEmptyString(state.inheritedfrom)){
return true;
}

if(this.isNew(state)) {
return false;
}

// ie: it's position is less than 1
return !(!_.isUndefined(state.attnum) && state.attnum > 0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,16 @@ export default class ExclusionConstraintSchema extends BaseUISchema {
type: 'select', group: gettext('Definition'),
options: this.fieldOptions.amname,
deferredDepChange: (state, source, topState, actionObj)=>{
// Opt out cleanly when nothing would change: amname unchanged
// or no columns to wipe. Previously this queued a confirmation
// dialog unconditionally.
// actionObj.oldState is guaranteed by the reducer to be the
// pre-dispatch clone; no need for optional chaining (and the
// cancel branch below accesses it unconditionally).
if(state.amname === actionObj.oldState.amname
|| !state.columns?.length) {
return undefined;
}
return new Promise((resolve)=>{
pgAdmin.Browser.notifier.confirm(
gettext('Change access method?'),
Expand Down Expand Up @@ -311,11 +321,9 @@ export default class ExclusionConstraintSchema extends BaseUISchema {
}));
},
function() {
resolve(()=>{
return {
amname: actionObj.oldState.amname,
};
});
resolve(()=>({
amname: actionObj.oldState.amname,
}));
}
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,35 +476,25 @@ export default class IndexSchema extends BaseUISchema {
};
},
deferredDepChange: (state, source, topState, actionObj) => {
const setColumns = (resolve)=>{
resolve(()=>{
state.columns.splice(0, state.columns?.length);
return {
columns: state.columns,
};
});
};
if((state.amname != actionObj?.oldState.amname) && state.columns?.length > 0) {
return new Promise((resolve)=>{
pgAdmin.Browser.notifier.confirm(
gettext('Warning'),
gettext('Changing access method will clear columns collection. Do you want to continue?'),
function () {
setColumns(resolve);
},
function() {
resolve(()=>{
state.amname = actionObj?.oldState.amname;
return {
amname: state.amname,
};
});
}
);
});
} else {
return Promise.resolve(()=>{/*This is intentional (SonarQube)*/});
// No-op when amname didn't change or there's nothing to clear.
// Returning undefined opts out of the deferred queue.
// actionObj.oldState is guaranteed by the reducer to be the
// pre-dispatch clone; no need for optional chaining (and the
// cancel branch below accesses it unconditionally).
if (state.amname === actionObj.oldState.amname
|| !state.columns?.length) {
return undefined;
}
return new Promise((resolve)=>{
pgAdmin.Browser.notifier.confirm(
gettext('Warning'),
gettext('Changing access method will clear columns collection. Do you want to continue?'),
// Confirmed — clear the columns collection.
() => resolve(() => ({ columns: [] })),
// Cancelled — revert amname to its previous value.
() => resolve(() => ({ amname: actionObj.oldState.amname })),
);
});
},
},
{
Expand Down
Loading
Loading