diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index c12b34f5075ad3258ed55178d6926ed17db49a2a..132916aa70218ffdc183461b74aa276dfc566725 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1716,10 +1716,24 @@ find_expr_references_walker(Node *node, else if (IsA(node, FieldSelect)) { FieldSelect *fselect = (FieldSelect *) node; + Oid argtype = exprType((Node *) fselect->arg); + Oid reltype = get_typ_typrelid(argtype); - /* result type might not appear anywhere else in expression */ - add_object_address(OCLASS_TYPE, fselect->resulttype, 0, - context->addrs); + /* + * We need a dependency on the specific column named in FieldSelect, + * assuming we can identify the pg_class OID for it. (Probably we + * always can at the moment, but in future it might be possible for + * argtype to be RECORDOID.) If we can make a column dependency then + * we shouldn't need a dependency on the column's type; but if we + * can't, make a dependency on the type, as it might not appear + * anywhere else in the expression. + */ + if (OidIsValid(reltype)) + add_object_address(OCLASS_CLASS, reltype, fselect->fieldnum, + context->addrs); + else + add_object_address(OCLASS_TYPE, fselect->resulttype, 0, + context->addrs); /* the collation might not be referenced anywhere else, either */ if (OidIsValid(fselect->resultcollid) && fselect->resultcollid != DEFAULT_COLLATION_OID) @@ -1729,10 +1743,20 @@ find_expr_references_walker(Node *node, else if (IsA(node, FieldStore)) { FieldStore *fstore = (FieldStore *) node; + Oid reltype = get_typ_typrelid(fstore->resulttype); - /* result type might not appear anywhere else in expression */ - add_object_address(OCLASS_TYPE, fstore->resulttype, 0, - context->addrs); + /* similar considerations to FieldSelect, but multiple column(s) */ + if (OidIsValid(reltype)) + { + ListCell *l; + + foreach(l, fstore->fieldnums) + add_object_address(OCLASS_CLASS, reltype, lfirst_int(l), + context->addrs); + } + else + add_object_address(OCLASS_TYPE, fstore->resulttype, 0, + context->addrs); } else if (IsA(node, RelabelType)) { diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index bcf8c33ce2164ab4de462f58983fe0d449c7c8ed..9bc1f4fc733419a279b6f5b42190ff8b21fd77a4 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -2682,6 +2682,23 @@ Typed table of type: test_type2 Inherits: test_tbl2 DROP TABLE test_tbl2_subclass; +CREATE TYPE test_typex AS (a int, b text); +CREATE TABLE test_tblx (x int, y test_typex check ((y).a > 0)); +ALTER TYPE test_typex DROP ATTRIBUTE a; -- fails +ERROR: cannot drop composite type test_typex column a because other objects depend on it +DETAIL: constraint test_tblx_y_check on table test_tblx depends on composite type test_typex column a +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER TYPE test_typex DROP ATTRIBUTE a CASCADE; +NOTICE: drop cascades to constraint test_tblx_y_check on table test_tblx +\d test_tblx + Table "public.test_tblx" + Column | Type | Collation | Nullable | Default +--------+------------+-----------+----------+--------- + x | integer | | | + y | test_typex | | | + +DROP TABLE test_tblx; +DROP TYPE test_typex; -- This test isn't that interesting on its own, but the purpose is to leave -- behind a table to test pg_upgrade with. The table has a composite type -- column in it, and the composite type has a dropped attribute. diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index 9a20dd141a2543df9749ea6d29d30d7152e0bf10..2ed9bccb58ad2458dfc49609657a3d722922c2a9 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -1698,6 +1698,14 @@ ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE; DROP TABLE test_tbl2_subclass; +CREATE TYPE test_typex AS (a int, b text); +CREATE TABLE test_tblx (x int, y test_typex check ((y).a > 0)); +ALTER TYPE test_typex DROP ATTRIBUTE a; -- fails +ALTER TYPE test_typex DROP ATTRIBUTE a CASCADE; +\d test_tblx +DROP TABLE test_tblx; +DROP TYPE test_typex; + -- This test isn't that interesting on its own, but the purpose is to leave -- behind a table to test pg_upgrade with. The table has a composite type -- column in it, and the composite type has a dropped attribute.