diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 5c77e210c5..ebdd08094b 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1642,10 +1642,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) @@ -1655,10 +1669,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 e970110c68..042cccec9b 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -2488,6 +2488,23 @@ Table "public.test_tbl2_subclass" 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 | Modifiers +--------+------------+----------- + 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 cdb4f21265..5994343441 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -1558,6 +1558,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.