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