Remove inherited columns from the Columns tab when their parent table is removed after reopening a table. #10470 (#10504)

get_formatted_columns() copied the parent table name onto inherited columns
loaded from a saved table's properties, but not the parent's OID, so the
table dialog could not match those columns when the parent was removed from
'Inherited from'. Keep the first parent's OID, matching what the dialog does
when parents are added interactively.
This commit is contained in:
Yousif Wael authored and Dave Page committed 2026-10-12 17:06:12 +01:00
1 parent aaa0c8f14d
commit bdb652b772
2 files changed
+62 -2

No files matched your search

@@ -51,23 +51,28 @@ class TestSerialColumnDetection(BaseTestGenerator):
dict(test_method='test_genuine_serial_is_detected')),
('Identity column is never reprojected',
dict(test_method='test_identity_column_not_serial')),
('Inherited column preserves parent OID',
dict(test_method='test_inherited_column_preserves_parent_oid')),
]
@patch(UTILS_MODULE + '.render_template', return_value='SELECT 1;')
def runTest(self, mock_render):
getattr(self, self.test_method)()
def _run(self, column_row):
def _run(self, column_row, other_columns=None):
from pgadmin.browser.server_groups.servers.databases.schemas.\
tables.columns.utils import get_formatted_columns
if other_columns is None:
other_columns = []
conn = MagicMock()
conn.execute_dict.return_value = (True, {'rows': [column_row]})
conn.execute_2darray.return_value = (True, {'rows': []})
with patch(UTILS_MODULE + '.column_formatter'):
data = get_formatted_columns(
conn, tid=1, data={}, other_columns=[],
conn, tid=1, data={}, other_columns=other_columns,
table_or_type='table', template_path='columns/sql/default')
return data['columns'][0]
@@ -98,6 +103,59 @@ class TestSerialColumnDetection(BaseTestGenerator):
self.assertEqual(result['cltype'], 'serial')
self.assertEqual(result['defval'], '')
def test_inherited_column_preserves_parent_oid(self):
result = self._run(
_make_column(),
[{
'name': 'id',
'inheritedfrom': 'public.parent',
'inheritedid': 987654,
}]
)
self.assertEqual(result['inheritedfromtable'], 'public.parent')
self.assertEqual(result['inheritedid'], 987654)
# A column provided by two parents keeps the first parent's OID,
# matching what the UI does when the parents are added
# interactively.
result = self._run(
_make_column(),
[
{
'name': 'id',
'inheritedfrom': 'public.parent_a',
'inheritedid': 987654,
},
{
'name': 'id',
'inheritedfrom': 'public.parent_b',
'inheritedid': 123456,
},
]
)
self.assertEqual(result['inheritedid'], 987654)
# An OID already supplied by properties.sql is not overwritten.
result = self._run(
_make_column(inheritedid=140391),
[
{
'name': 'id',
'inheritedfrom': 'public.parent_a',
'inheritedid': 987654,
},
{
'name': 'id',
'inheritedfrom': 'public.parent_b',
'inheritedid': 123456,
},
]
)
self.assertEqual(result['inheritedid'], 140391)
def test_identity_column_not_serial(self):
# Identity columns can carry an internal sequence dependency on
# both sides, but must never be reprojected as SERIAL.
@@ -330,6 +330,8 @@ def get_formatted_columns(conn, tid, data, other_columns,
if col['name'] == other_col['name']:
col['inheritedfrom' + table_or_type] = \
other_col['inheritedfrom']
if col.get('inheritedid') is None:
col['inheritedid'] = other_col['inheritedid']
if with_serial:
reproject_serial_column(col)