diff --git a/doc/src/sgml/ref/alter_domain.sgml b/doc/src/sgml/ref/alter_domain.sgml index 4735d42405..fdbf08e6d4 100644 --- a/doc/src/sgml/ref/alter_domain.sgml +++ b/doc/src/sgml/ref/alter_domain.sgml @@ -1,5 +1,5 @@ @@ -29,6 +29,8 @@ ALTER DOMAIN domain ADD domain_constraint ALTER DOMAIN domain DROP CONSTRAINT constraint_name [ RESTRICT | CASCADE ] +ALTER DOMAIN domain + OWNER TO new_owner @@ -73,7 +75,7 @@ ALTER DOMAIN domain CASCADE - Automatically drop objects that depend constraint. + Automatically drop objects that depend on the constraint. @@ -88,6 +90,15 @@ ALTER DOMAIN domain + + new_owner + + + The user name of the new owner of the domain. + + + + @@ -141,9 +152,9 @@ ALTER DOMAIN domain SET/DROP DEFAULT - These forms set or remove the default value for a column. Note + These forms set or remove the default value for a domain. Note that defaults only apply to subsequent INSERT - commands; they do not cause rows already in a table using the domain. + commands; they do not affect rows already in a table using the domain. @@ -154,8 +165,7 @@ ALTER DOMAIN domain These forms change whether a domain is marked to allow NULL values or to reject NULL values. You may only SET NOT NULL - when the tables using the domain contain no null values in the domain - based column. + when the columns using the domain contain no null values. @@ -164,8 +174,10 @@ ALTER DOMAIN domain ADD domain_constraint - This form adds a new constraint to a table using the same syntax as - . + This form adds a new constraint to a domain using the same syntax as + . + This will only succeed if all columns using the domain satisfy the + new constraint. @@ -179,11 +191,19 @@ ALTER DOMAIN domain + + OWNER + + + This form changes the owner of the domain to the specified user. + + + You must own the domain to use ALTER DOMAIN; except for - ALTER TABLE OWNER, which may only be executed by a superuser. + ALTER DOMAIN OWNER, which may only be executed by a superuser. diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 33f2fa7c2b..bd29033c72 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.26 2003/01/04 00:46:08 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.27 2003/01/06 00:31:44 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -1673,3 +1673,61 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, */ return ccbin; } + +/* + * ALTER DOMAIN .. OWNER TO + * + * Eventually this should allow changing ownership of other kinds of types, + * but some thought must be given to handling complex types. (A table's + * rowtype probably shouldn't be allowed as target, but what of a standalone + * composite type?) + * + * Assumes that permission checks have been completed earlier. + */ +void +AlterTypeOwner(List *names, AclId newOwnerSysId) +{ + TypeName *typename; + Oid typeOid; + Relation rel; + HeapTuple tup; + Form_pg_type typTup; + + /* Make a TypeName so we can use standard type lookup machinery */ + typename = makeNode(TypeName); + typename->names = names; + typename->typmod = -1; + typename->arrayBounds = NIL; + + /* Lock the type table */ + rel = heap_openr(TypeRelationName, RowExclusiveLock); + + /* Use LookupTypeName here so that shell types can be processed (why?) */ + typeOid = LookupTypeName(typename); + if (!OidIsValid(typeOid)) + elog(ERROR, "Type \"%s\" does not exist", + TypeNameToString(typename)); + + tup = SearchSysCacheCopy(TYPEOID, + ObjectIdGetDatum(typeOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "AlterDomain: type \"%s\" does not exist", + TypeNameToString(typename)); + typTup = (Form_pg_type) GETSTRUCT(tup); + + /* Check that this is actually a domain */ + if (typTup->typtype != 'd') + elog(ERROR, "%s is not a domain", + TypeNameToString(typename)); + + /* Modify the owner --- okay to scribble on typTup because it's a copy */ + typTup->typowner = newOwnerSysId; + + simple_heap_update(rel, &tup->t_self, tup); + + CatalogUpdateIndexes(rel, tup); + + /* Clean up */ + heap_close(rel, RowExclusiveLock); +} diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index c19673fc42..921099b792 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.389 2002/12/30 15:31:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.390 2003/01/06 00:31:44 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -3764,6 +3764,15 @@ AlterDomainStmt: n->behavior = $7; $$ = (Node *)n; } + /* ALTER DOMAIN OWNER TO UserId */ + | ALTER DOMAIN_P any_name OWNER TO UserId + { + AlterDomainStmt *n = makeNode(AlterDomainStmt); + n->subtype = 'U'; + n->typename = $3; + n->name = $6; + $$ = (Node *)n; + } ; opt_as: AS {} diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 962c531150..68c02c5f62 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.187 2002/12/30 18:42:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.188 2003/01/06 00:31:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -439,11 +439,11 @@ ProcessUtility(Node *parsetree, stmt->newname); /* new att name */ break; case RENAME_RULE: - elog(ERROR, "ProcessUtility: Invalid target for RENAME: %d", + elog(ERROR, "ProcessUtility: Invalid type for RENAME: %d", stmt->renameType); break; default: - elog(ERROR, "ProcessUtility: Invalid target for RENAME: %d", + elog(ERROR, "ProcessUtility: Invalid type for RENAME: %d", stmt->renameType); } } @@ -553,7 +553,8 @@ ProcessUtility(Node *parsetree, get_usesysid(stmt->name)); break; default: /* oops */ - elog(ERROR, "T_AlterTableStmt: unknown subtype"); + elog(ERROR, "ProcessUtility: Invalid type for AlterTableStmt: %d", + stmt->subtype); break; } } @@ -595,8 +596,17 @@ ProcessUtility(Node *parsetree, stmt->name, stmt->behavior); break; + case 'U': /* OWNER TO */ + /* check that we are the superuser */ + if (!superuser()) + elog(ERROR, "ALTER DOMAIN: permission denied"); + /* get_usesysid raises an error if no such user */ + AlterTypeOwner(stmt->typename, + get_usesysid(stmt->name)); + break; default: /* oops */ - elog(ERROR, "T_AlterDomainStmt: unknown subtype"); + elog(ERROR, "ProcessUtility: Invalid type for AlterDomainStmt: %d", + stmt->subtype); break; } } diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h index 2757d54276..8f21aef7f4 100644 --- a/src/include/commands/typecmds.h +++ b/src/include/commands/typecmds.h @@ -7,15 +7,17 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: typecmds.h,v 1.2 2002/12/10 16:12:53 tgl Exp $ + * $Id: typecmds.h,v 1.3 2003/01/06 00:31:44 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef TYPECMDS_H #define TYPECMDS_H +#include "miscadmin.h" #include "nodes/parsenodes.h" + #define DEFAULT_TYPDELIM ',' extern void DefineType(List *names, List *parameters); @@ -31,4 +33,6 @@ extern void AlterDomainAddConstraint(List *names, Node *constr); extern void AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior behavior); +extern void AlterTypeOwner(List *names, AclId newOwnerSysId); + #endif /* TYPECMDS_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 0f9b7613a0..6ca3894b0d 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.224 2002/12/30 15:31:51 momjian Exp $ + * $Id: parsenodes.h,v 1.225 2003/01/06 00:31:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -711,7 +711,7 @@ typedef struct AlterTableStmt * Alter Domain * * The fields are used in different ways by the different variants of - * this command. Subtypes should match AlterTable subtypes + * this command. Subtypes should match AlterTable subtypes where possible. * ---------------------- */ typedef struct AlterDomainStmt