diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/tablecmds.c | 40 | ||||
-rw-r--r-- | src/backend/commands/typecmds.c | 43 |
2 files changed, 63 insertions, 20 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 7e347b27f0e..b506b617b4e 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.206.2.2 2007/02/02 00:07:27 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.206.2.3 2007/05/11 20:17:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -204,8 +204,6 @@ static void ATSimpleRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd, bool recurse); static void ATOneLevelRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd); -static void find_composite_type_dependencies(Oid typeOid, - const char *origTblName); static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd); static void ATExecAddColumn(AlteredTableInfo *tab, Relation rel, @@ -2590,7 +2588,8 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap) */ if (newrel) find_composite_type_dependencies(oldrel->rd_rel->reltype, - RelationGetRelationName(oldrel)); + RelationGetRelationName(oldrel), + NULL); /* * Generate the constraint and default execution states @@ -2992,16 +2991,21 @@ ATOneLevelRecursion(List **wqueue, Relation rel, /* * find_composite_type_dependencies * - * Check to see if a table's rowtype is being used as a column in some + * Check to see if a composite type is being used as a column in some * other table (possibly nested several levels deep in composite types!). * Eventually, we'd like to propagate the check or rewrite operation * into other such tables, but for now, just error out if we find any. * + * Caller should provide either a table name or a type name (not both) to + * report in the error message, if any. + * * We assume that functions and views depending on the type are not reasons * to reject the ALTER. (How safe is this really?) */ -static void -find_composite_type_dependencies(Oid typeOid, const char *origTblName) +void +find_composite_type_dependencies(Oid typeOid, + const char *origTblName, + const char *origTypeName) { Relation depRel; ScanKeyData key[2]; @@ -3043,12 +3047,20 @@ find_composite_type_dependencies(Oid typeOid, const char *origTblName) if (rel->rd_rel->relkind == RELKIND_RELATION) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot alter table \"%s\" because column \"%s\".\"%s\" uses its rowtype", - origTblName, - RelationGetRelationName(rel), - NameStr(att->attname)))); + if (origTblName) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot alter table \"%s\" because column \"%s\".\"%s\" uses its rowtype", + origTblName, + RelationGetRelationName(rel), + NameStr(att->attname)))); + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot alter type \"%s\" because column \"%s\".\"%s\" uses it", + origTypeName, + RelationGetRelationName(rel), + NameStr(att->attname)))); } else if (OidIsValid(rel->rd_rel->reltype)) { @@ -3057,7 +3069,7 @@ find_composite_type_dependencies(Oid typeOid, const char *origTblName) * recursively check for indirect dependencies via its rowtype. */ find_composite_type_dependencies(rel->rd_rel->reltype, - origTblName); + origTblName, origTypeName); } relation_close(rel, AccessShareLock); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 53cca73a9dd..462419e7fe5 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.97 2006/10/04 00:29:51 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.97.2.1 2007/05/11 20:18:10 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -1600,6 +1600,10 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) * the domain type. We have opened each rel and acquired the specified lock * type on it. * + * We support nested domains by including attributes that are of derived + * domain types. Current callers do not need to distinguish between attributes + * that are of exactly the given domain and those that are of derived domains. + * * XXX this is completely broken because there is no way to lock the domain * to prevent columns from being added or dropped while our command runs. * We can partially protect against column drops by locking relations as we @@ -1609,9 +1613,11 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) * trivial risk of deadlock. We can minimize but not eliminate the deadlock * risk by using the weakest suitable lock (ShareLock for most callers). * - * XXX to support domains over domains, we'd need to make this smarter, - * or make its callers smarter, so that we could find columns of derived - * domains. Arrays of domains would be a problem too. + * 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. * * Generally used for retrieving a list of tests when adding * new constraints to a domain. @@ -1653,7 +1659,23 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode) Form_pg_attribute pg_att; int ptr; - /* Ignore dependees that aren't user columns of relations */ + /* Check for directly dependent types --- must be domains */ + if (pg_depend->classid == TypeRelationId) + { + Assert(get_typtype(pg_depend->objid) == 'd'); + /* + * 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)); + continue; + } + + /* Else, ignore dependees that aren't user columns of relations */ /* (we assume system columns are never of domain types) */ if (pg_depend->classid != RelationRelationId || pg_depend->objsubid <= 0) @@ -1679,7 +1701,16 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode) /* Acquire requested lock on relation */ rel = relation_open(pg_depend->objid, lockmode); - /* It could be a view or composite type; if so ignore it */ + /* + * Check to see if rowtype is stored anyplace as a composite-type + * column; if so we have to fail, for now anyway. + */ + if (OidIsValid(rel->rd_rel->reltype)) + find_composite_type_dependencies(rel->rd_rel->reltype, + NULL, + format_type_be(domainOid)); + + /* Otherwise we can ignore views, composite types, etc */ if (rel->rd_rel->relkind != RELKIND_RELATION) { relation_close(rel, lockmode); |