diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2017-08-09 17:03:09 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2017-08-09 17:03:09 -0400 |
commit | 749c7c41701c62d96a56af1531e4f51e39173be3 (patch) | |
tree | 40023ce9b85a28e427ae68f0115be6de14d8230f /src/backend/commands/typecmds.c | |
parent | a76200de8462aa0551dde8132c11d648d0ad6e99 (diff) | |
download | postgresql-749c7c41701c62d96a56af1531e4f51e39173be3.tar.gz postgresql-749c7c41701c62d96a56af1531e4f51e39173be3.zip |
Fix handling of container types in find_composite_type_dependencies.
find_composite_type_dependencies correctly found columns that are of
the specified type, and columns that are of arrays of that type, but
not columns that are domains or ranges over the given type, its array
type, etc. The most general way to handle this seems to be to assume
that any type that is directly dependent on the specified type can be
treated as a container type, and processed recursively (allowing us
to handle nested cases such as ranges over domains over arrays ...).
Since a type's array type already has such a dependency, we can drop
the existing special case for the array type.
The very similar logic in get_rels_with_domain was likewise a few
bricks shy of a load, as it supposed that a directly dependent type
could *only* be a sub-domain. This is already wrong for ranges over
domains, and it'll someday be wrong for arrays over domains.
Add test cases illustrating the problems, and back-patch to all
supported branches.
Discussion: https://postgr.es/m/15268.1502309024@sss.pgh.pa.us
Diffstat (limited to 'src/backend/commands/typecmds.c')
-rw-r--r-- | src/backend/commands/typecmds.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index c2fc59d1aa0..29ac5d569d7 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -2787,10 +2787,9 @@ validateDomainConstraint(Oid domainoid, char *ccbin) * risk by using the weakest suitable lock (ShareLock for most callers). * * XXX the API for this is not sufficient to support checking domain values - * that are inside composite types or arrays. Currently we just error out - * if a composite type containing the target domain is stored anywhere. - * There are not currently arrays of domains; if there were, we could take - * the same approach, but it'd be nicer to fix it properly. + * that are inside container types, such as composite types, arrays, or + * ranges. Currently we just error out if a container type containing the + * target domain is stored anywhere. * * Generally used for retrieving a list of tests when adding * new constraints to a domain. @@ -2799,6 +2798,7 @@ static List * get_rels_with_domain(Oid domainOid, LOCKMODE lockmode) { List *result = NIL; + char *domainTypeName = format_type_be(domainOid); Relation depRel; ScanKeyData key[2]; SysScanDesc depScan; @@ -2806,6 +2806,9 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode) Assert(lockmode != NoLock); + /* since this function recurses, it could be driven to stack overflow */ + check_stack_depth(); + /* * We scan pg_depend to find those things that depend on the domain. (We * assume we can ignore refobjsubid for a domain.) @@ -2832,20 +2835,32 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode) Form_pg_attribute pg_att; int ptr; - /* Check for directly dependent types --- must be domains */ + /* Check for directly dependent types */ if (pg_depend->classid == TypeRelationId) { - Assert(get_typtype(pg_depend->objid) == TYPTYPE_DOMAIN); - - /* - * Recursively add dependent columns to the output list. This is - * a bit inefficient since we may fail to combine RelToCheck - * entries when attributes of the same rel have different derived - * domain types, but it's probably not worth improving. - */ - result = list_concat(result, - get_rels_with_domain(pg_depend->objid, - lockmode)); + if (get_typtype(pg_depend->objid) == TYPTYPE_DOMAIN) + { + /* + * This is a sub-domain, so recursively add dependent columns + * to the output list. This is a bit inefficient since we may + * fail to combine RelToCheck entries when attributes of the + * same rel have different derived domain types, but it's + * probably not worth improving. + */ + result = list_concat(result, + get_rels_with_domain(pg_depend->objid, + lockmode)); + } + else + { + /* + * Otherwise, it is some container type using the domain, so + * fail if there are any columns of this type. + */ + find_composite_type_dependencies(pg_depend->objid, + NULL, + domainTypeName); + } continue; } @@ -2882,7 +2897,7 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode) if (OidIsValid(rel->rd_rel->reltype)) find_composite_type_dependencies(rel->rd_rel->reltype, NULL, - format_type_be(domainOid)); + domainTypeName); /* * Otherwise, we can ignore relations except those with both |