Skip to content

Commit 37fb01c

Browse files
committed
Rethink the dependencies recorded for FieldSelect/FieldStore nodes.
On closer investigation, commits f3ea3e3 et al were a few bricks shy of a load. What we need is not so much to lock down the result type of a FieldSelect, as to lock down the existence of the column it's trying to extract. Otherwise, we can break it by dropping that column. The dependency on the result type is then held indirectly through the column, and doesn't need to be recorded explicitly. Out of paranoia, I left in the code to record a dependency on the result type, but it's used only if we can't identify the pg_class OID for the column. That shouldn't ever happen right now, AFAICS, but it seems possible that in future the input node could be marked as being of type RECORD rather than some specific composite type. Likewise for FieldStore. Like the previous patch, back-patch to all supported branches. Discussion: https://postgr.es/m/22571.1509064146@sss.pgh.pa.us
1 parent 1c715f1 commit 37fb01c

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

src/backend/catalog/dependency.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,10 +1701,24 @@ find_expr_references_walker(Node *node,
17011701
else if (IsA(node, FieldSelect))
17021702
{
17031703
FieldSelect *fselect = (FieldSelect *) node;
1704+
Oid argtype = exprType((Node *) fselect->arg);
1705+
Oid reltype = get_typ_typrelid(argtype);
17041706

1705-
/* result type might not appear anywhere else in expression */
1706-
add_object_address(OCLASS_TYPE, fselect->resulttype, 0,
1707-
context->addrs);
1707+
/*
1708+
* We need a dependency on the specific column named in FieldSelect,
1709+
* assuming we can identify the pg_class OID for it. (Probably we
1710+
* always can at the moment, but in future it might be possible for
1711+
* argtype to be RECORDOID.) If we can make a column dependency then
1712+
* we shouldn't need a dependency on the column's type; but if we
1713+
* can't, make a dependency on the type, as it might not appear
1714+
* anywhere else in the expression.
1715+
*/
1716+
if (OidIsValid(reltype))
1717+
add_object_address(OCLASS_CLASS, reltype, fselect->fieldnum,
1718+
context->addrs);
1719+
else
1720+
add_object_address(OCLASS_TYPE, fselect->resulttype, 0,
1721+
context->addrs);
17081722
/* the collation might not be referenced anywhere else, either */
17091723
if (OidIsValid(fselect->resultcollid) &&
17101724
fselect->resultcollid != DEFAULT_COLLATION_OID)
@@ -1714,10 +1728,20 @@ find_expr_references_walker(Node *node,
17141728
else if (IsA(node, FieldStore))
17151729
{
17161730
FieldStore *fstore = (FieldStore *) node;
1731+
Oid reltype = get_typ_typrelid(fstore->resulttype);
17171732

1718-
/* result type might not appear anywhere else in expression */
1719-
add_object_address(OCLASS_TYPE, fstore->resulttype, 0,
1720-
context->addrs);
1733+
/* similar considerations to FieldSelect, but multiple column(s) */
1734+
if (OidIsValid(reltype))
1735+
{
1736+
ListCell *l;
1737+
1738+
foreach(l, fstore->fieldnums)
1739+
add_object_address(OCLASS_CLASS, reltype, lfirst_int(l),
1740+
context->addrs);
1741+
}
1742+
else
1743+
add_object_address(OCLASS_TYPE, fstore->resulttype, 0,
1744+
context->addrs);
17211745
}
17221746
else if (IsA(node, RelabelType))
17231747
{

src/test/regress/expected/alter_table.out

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2599,6 +2599,23 @@ Table "public.test_tbl2_subclass"
25992599
Inherits: test_tbl2
26002600

26012601
DROP TABLE test_tbl2_subclass;
2602+
CREATE TYPE test_typex AS (a int, b text);
2603+
CREATE TABLE test_tblx (x int, y test_typex check ((y).a > 0));
2604+
ALTER TYPE test_typex DROP ATTRIBUTE a; -- fails
2605+
ERROR: cannot drop composite type test_typex column a because other objects depend on it
2606+
DETAIL: constraint test_tblx_y_check on table test_tblx depends on composite type test_typex column a
2607+
HINT: Use DROP ... CASCADE to drop the dependent objects too.
2608+
ALTER TYPE test_typex DROP ATTRIBUTE a CASCADE;
2609+
NOTICE: drop cascades to constraint test_tblx_y_check on table test_tblx
2610+
\d test_tblx
2611+
Table "public.test_tblx"
2612+
Column | Type | Modifiers
2613+
--------+------------+-----------
2614+
x | integer |
2615+
y | test_typex |
2616+
2617+
DROP TABLE test_tblx;
2618+
DROP TYPE test_typex;
26022619
-- This test isn't that interesting on its own, but the purpose is to leave
26032620
-- behind a table to test pg_upgrade with. The table has a composite type
26042621
-- column in it, and the composite type has a dropped attribute.

src/test/regress/sql/alter_table.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,14 @@ ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE;
16441644

16451645
DROP TABLE test_tbl2_subclass;
16461646

1647+
CREATE TYPE test_typex AS (a int, b text);
1648+
CREATE TABLE test_tblx (x int, y test_typex check ((y).a > 0));
1649+
ALTER TYPE test_typex DROP ATTRIBUTE a; -- fails
1650+
ALTER TYPE test_typex DROP ATTRIBUTE a CASCADE;
1651+
\d test_tblx
1652+
DROP TABLE test_tblx;
1653+
DROP TYPE test_typex;
1654+
16471655
-- This test isn't that interesting on its own, but the purpose is to leave
16481656
-- behind a table to test pg_upgrade with. The table has a composite type
16491657
-- column in it, and the composite type has a dropped attribute.

0 commit comments

Comments
 (0)