aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/aggregatecmds.c66
-rw-r--r--src/backend/commands/alter.c71
-rw-r--r--src/backend/commands/conversioncmds.c54
-rw-r--r--src/backend/commands/dbcommands.c42
-rw-r--r--src/backend/commands/functioncmds.c56
-rw-r--r--src/backend/commands/opclasscmds.c91
-rw-r--r--src/backend/commands/operatorcmds.c55
-rw-r--r--src/backend/commands/schemacmds.c47
-rw-r--r--src/backend/commands/tablecmds.c78
-rw-r--r--src/backend/commands/tablespace.c122
-rw-r--r--src/backend/commands/typecmds.c42
11 files changed, 643 insertions, 81 deletions
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index c8865b3dbde..a787f7ad43f 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.18 2004/05/26 04:41:09 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.19 2004/06/25 21:55:53 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -223,10 +223,9 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
/*
* if a basetype is passed in, then attempt to find an aggregate for
- * that specific type.
- *
- * else attempt to find an aggregate with a basetype of ANYOID. This
- * means that the aggregate is to apply to all basetypes (eg, COUNT).
+ * that specific type; else attempt to find an aggregate with a basetype
+ * of ANYOID. This means that the aggregate applies to all basetypes
+ * (eg, COUNT).
*/
if (basetype)
basetypeOid = typenameTypeId(basetype);
@@ -288,3 +287,60 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
heap_close(rel, NoLock);
heap_freetuple(tup);
}
+
+/*
+ * Change aggregate owner
+ */
+void
+AlterAggregateOwner(List *name, TypeName *basetype, AclId newOwnerSysId)
+{
+ Oid basetypeOid;
+ Oid procOid;
+ HeapTuple tup;
+ Form_pg_proc procForm;
+ Relation rel;
+
+ /*
+ * if a basetype is passed in, then attempt to find an aggregate for
+ * that specific type; else attempt to find an aggregate with a basetype
+ * of ANYOID. This means that the aggregate applies to all basetypes
+ * (eg, COUNT).
+ */
+ if (basetype)
+ basetypeOid = typenameTypeId(basetype);
+ else
+ basetypeOid = ANYOID;
+
+ rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
+
+ procOid = find_aggregate_func(name, basetypeOid, false);
+
+ tup = SearchSysCacheCopy(PROCOID,
+ ObjectIdGetDatum(procOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for function %u", procOid);
+ procForm = (Form_pg_proc) GETSTRUCT(tup);
+
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
+ */
+ if (procForm->proowner != newOwnerSysId)
+ {
+ /* Otherwise, must be superuser to change object ownership */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change owner")));
+
+ /* Modify the owner --- okay to scribble on tup because it's a copy */
+ procForm->proowner = newOwnerSysId;
+
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+ }
+
+ heap_close(rel, NoLock);
+ heap_freetuple(tup);
+}
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 40a28103c77..50516e1f046 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.7 2004/05/26 04:41:09 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.8 2004/06/25 21:55:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -25,7 +25,9 @@
#include "commands/proclang.h"
#include "commands/schemacmds.h"
#include "commands/tablecmds.h"
+#include "commands/tablespace.h"
#include "commands/trigger.h"
+#include "commands/typecmds.h"
#include "commands/user.h"
#include "miscadmin.h"
#include "parser/parse_clause.h"
@@ -35,6 +37,10 @@
#include "utils/syscache.h"
+/*
+ * Executes an ALTER OBJECT / RENAME TO statement. Based on the object
+ * type, the function appropriate to that type is executed.
+ */
void
ExecRenameStmt(RenameStmt *stmt)
{
@@ -74,6 +80,10 @@ ExecRenameStmt(RenameStmt *stmt)
RenameSchema(stmt->subname, stmt->newname);
break;
+ case OBJECT_TABLESPACE:
+ RenameTableSpace(stmt->subname, stmt->newname);
+ break;
+
case OBJECT_USER:
RenameUser(stmt->subname, stmt->newname);
break;
@@ -133,3 +143,62 @@ ExecRenameStmt(RenameStmt *stmt)
(int) stmt->renameType);
}
}
+
+/*
+ * Executes an ALTER OBJECT / OWNER TO statement. Based on the object
+ * type, the function appropriate to that type is executed.
+ */
+void
+ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
+{
+ AclId newowner = get_usesysid(stmt->newowner);
+
+ switch (stmt->objectType)
+ {
+ case OBJECT_AGGREGATE:
+ AlterAggregateOwner(stmt->object,
+ (TypeName *) linitial(stmt->objarg),
+ newowner);
+ break;
+
+ case OBJECT_CONVERSION:
+ AlterConversionOwner(stmt->object, newowner);
+ break;
+
+ case OBJECT_DATABASE:
+ AlterDatabaseOwner((char *) linitial(stmt->object), newowner);
+ break;
+
+ case OBJECT_FUNCTION:
+ AlterFunctionOwner(stmt->object, stmt->objarg, newowner);
+ break;
+
+ case OBJECT_OPERATOR:
+ AlterOperatorOwner(stmt->object,
+ (TypeName *) linitial(stmt->objarg),
+ (TypeName *) lsecond(stmt->objarg),
+ newowner);
+ break;
+
+ case OBJECT_OPCLASS:
+ AlterOpClassOwner(stmt->object, stmt->addname, newowner);
+ break;
+
+ case OBJECT_SCHEMA:
+ AlterSchemaOwner((char *) linitial(stmt->object), newowner);
+ break;
+
+ case OBJECT_TABLESPACE:
+ AlterTableSpaceOwner((char *) linitial(stmt->object), newowner);
+ break;
+
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN: /* same as TYPE */
+ AlterTypeOwner(stmt->object, newowner);
+ break;
+
+ default:
+ elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
+ (int) stmt->objectType);
+ }
+}
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index 1e55398f86e..298085f160b 100644
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.12 2003/11/29 19:51:47 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.13 2004/06/25 21:55:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -171,3 +171,55 @@ RenameConversion(List *name, const char *newname)
heap_close(rel, NoLock);
heap_freetuple(tup);
}
+
+/*
+ * Change conversion owner
+ */
+void
+AlterConversionOwner(List *name, AclId newOwnerSysId)
+{
+ Oid conversionOid;
+ HeapTuple tup;
+ Relation rel;
+ Form_pg_conversion convForm;
+
+ rel = heap_openr(ConversionRelationName, RowExclusiveLock);
+
+ conversionOid = FindConversionByName(name);
+ if (!OidIsValid(conversionOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("conversion \"%s\" does not exist",
+ NameListToString(name))));
+
+ tup = SearchSysCacheCopy(CONOID,
+ ObjectIdGetDatum(conversionOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for conversion %u", conversionOid);
+
+ convForm = (Form_pg_conversion) GETSTRUCT(tup);
+
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
+ */
+ if (convForm->conowner != newOwnerSysId)
+ {
+ /* Otherwise, must be superuser to change object ownership */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change owner")));
+
+ /* Modify the owner --- okay to scribble on tup because it's a copy */
+ convForm->conowner = newOwnerSysId;
+
+ simple_heap_update(rel, &tup->t_self, tup);
+
+ CatalogUpdateIndexes(rel, tup);
+ }
+
+ heap_close(rel, NoLock);
+ heap_freetuple(tup);
+}
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 8fbebecd874..b9e8c836274 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.136 2004/06/18 06:13:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.137 2004/06/25 21:55:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -666,7 +666,7 @@ RenameDatabase(const char *oldname, const char *newname)
/* rename */
newtup = heap_copytuple(tup);
namestrcpy(&(((Form_pg_database) GETSTRUCT(newtup))->datname), newname);
- simple_heap_update(rel, &tup->t_self, newtup);
+ simple_heap_update(rel, &newtup->t_self, newtup);
CatalogUpdateIndexes(rel, newtup);
systable_endscan(scan);
@@ -758,7 +758,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
CatalogUpdateIndexes(rel, newtuple);
systable_endscan(scan);
- heap_close(rel, RowExclusiveLock);
+ heap_close(rel, NoLock);
}
@@ -766,14 +766,14 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
* ALTER DATABASE name OWNER TO newowner
*/
void
-AlterDatabaseOwner(const char *dbname, const char *newowner)
+AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
{
- AclId newdatdba;
HeapTuple tuple,
newtuple;
Relation rel;
ScanKeyData scankey;
SysScanDesc scan;
+ Form_pg_database datForm;
rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
ScanKeyInit(&scankey,
@@ -788,21 +788,27 @@ AlterDatabaseOwner(const char *dbname, const char *newowner)
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database \"%s\" does not exist", dbname)));
- /* obtain sysid of proposed owner */
- newdatdba = get_usesysid(newowner); /* will ereport if no such user */
+ newtuple = heap_copytuple(tuple);
+ datForm = (Form_pg_database) GETSTRUCT(newtuple);
- /* changing owner's database for someone else: must be superuser */
- /* note that the someone else need not have any permissions */
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to change owner's database for another user")));
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is to be consistent with other objects.
+ */
+ if (datForm->datdba != newOwnerSysId)
+ {
+ /* changing owner's database for someone else: must be superuser */
+ /* note that the someone else need not have any permissions */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change owner")));
- /* change owner */
- newtuple = heap_copytuple(tuple);
- ((Form_pg_database) GETSTRUCT(newtuple))->datdba = newdatdba;
- simple_heap_update(rel, &tuple->t_self, newtuple);
- CatalogUpdateIndexes(rel, newtuple);
+ /* change owner */
+ datForm->datdba = newOwnerSysId;
+ simple_heap_update(rel, &newtuple->t_self, newtuple);
+ CatalogUpdateIndexes(rel, newtuple);
+ }
systable_endscan(scan);
heap_close(rel, NoLock);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 7747eb1d776..20ee9fa3445 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.48 2004/06/16 01:26:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.49 2004/06/25 21:55:53 tgl Exp $
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@@ -723,6 +723,60 @@ RenameFunction(List *name, List *argtypes, const char *newname)
heap_freetuple(tup);
}
+/*
+ * Change function owner
+ */
+void
+AlterFunctionOwner(List *name, List *argtypes, AclId newOwnerSysId)
+{
+ Oid procOid;
+ HeapTuple tup;
+ Form_pg_proc procForm;
+ Relation rel;
+
+ rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
+
+ procOid = LookupFuncNameTypeNames(name, argtypes, false);
+
+ tup = SearchSysCacheCopy(PROCOID,
+ ObjectIdGetDatum(procOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for function %u", procOid);
+ procForm = (Form_pg_proc) GETSTRUCT(tup);
+
+ if (procForm->proisagg)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is an aggregate function",
+ NameListToString(name)),
+ errhint("Use ALTER AGGREGATE to change owner of aggregate functions.")));
+
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
+ */
+ if (procForm->proowner != newOwnerSysId)
+ {
+ /* Otherwise, must be superuser to change object ownership */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change owner")));
+
+ /* Modify the owner --- okay to scribble on tup because it's a copy */
+ procForm->proowner = newOwnerSysId;
+
+ simple_heap_update(rel, &tup->t_self, tup);
+
+ CatalogUpdateIndexes(rel, tup);
+ }
+
+ heap_close(rel, NoLock);
+ heap_freetuple(tup);
+}
+
+
/*
* SetFunctionReturnType - change declared return type of a function
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index db5c2ccabc9..d9c0c1deade 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.25 2004/05/26 04:41:11 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.26 2004/06/25 21:55:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -871,3 +871,92 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
heap_close(rel, NoLock);
heap_freetuple(tup);
}
+
+/*
+ * Change opclass owner
+ */
+void
+AlterOpClassOwner(List *name, const char *access_method, AclId newOwnerSysId)
+{
+ Oid opcOid;
+ Oid amOid;
+ Oid namespaceOid;
+ char *schemaname;
+ char *opcname;
+ HeapTuple tup;
+ Relation rel;
+ Form_pg_opclass opcForm;
+
+ amOid = GetSysCacheOid(AMNAME,
+ CStringGetDatum(access_method),
+ 0, 0, 0);
+ if (!OidIsValid(amOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("access method \"%s\" does not exist",
+ access_method)));
+
+ rel = heap_openr(OperatorClassRelationName, RowExclusiveLock);
+
+ /*
+ * Look up the opclass
+ */
+ DeconstructQualifiedName(name, &schemaname, &opcname);
+
+ if (schemaname)
+ {
+ namespaceOid = LookupExplicitNamespace(schemaname);
+
+ tup = SearchSysCacheCopy(CLAAMNAMENSP,
+ ObjectIdGetDatum(amOid),
+ PointerGetDatum(opcname),
+ ObjectIdGetDatum(namespaceOid),
+ 0);
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("operator class \"%s\" does not exist for access method \"%s\"",
+ opcname, access_method)));
+
+ }
+ else
+ {
+ opcOid = OpclassnameGetOpcid(amOid, opcname);
+ if (!OidIsValid(opcOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("operator class \"%s\" does not exist for access method \"%s\"",
+ opcname, access_method)));
+
+ tup = SearchSysCacheCopy(CLAOID,
+ ObjectIdGetDatum(opcOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for opclass %u", opcOid);
+ namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace;
+ }
+ opcForm = (Form_pg_opclass) GETSTRUCT(tup);
+
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
+ */
+ if (opcForm->opcowner != newOwnerSysId)
+ {
+ /* Otherwise, must be superuser to change object ownership */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change owner")));
+
+ /* Modify the owner --- okay to scribble on tup because it's a copy */
+ opcForm->opcowner = newOwnerSysId;
+
+ simple_heap_update(rel, &tup->t_self, tup);
+
+ CatalogUpdateIndexes(rel, tup);
+ }
+
+ heap_close(rel, NoLock);
+ heap_freetuple(tup);
+}
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index d2ffae2ce56..8fbe0d1128b 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.16 2004/05/26 04:41:11 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.17 2004/06/25 21:55:53 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -37,6 +37,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/dependency.h"
+#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_operator.h"
#include "commands/defrem.h"
@@ -263,3 +264,55 @@ RemoveOperatorById(Oid operOid)
heap_close(relation, RowExclusiveLock);
}
+
+/*
+ * change operator owner
+ */
+void
+AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
+ AclId newOwnerSysId)
+{
+ Oid operOid;
+ HeapTuple tup;
+ Relation rel;
+ Form_pg_operator oprForm;
+
+ rel = heap_openr(OperatorRelationName, RowExclusiveLock);
+
+ operOid = LookupOperNameTypeNames(name, typeName1, typeName2,
+ false);
+
+ tup = SearchSysCacheCopy(OPEROID,
+ ObjectIdGetDatum(operOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for operator %u", operOid);
+
+ oprForm = (Form_pg_operator) GETSTRUCT(tup);
+
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
+ */
+ if (oprForm->oprowner != newOwnerSysId)
+ {
+ /* Otherwise, must be superuser to change object ownership */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change owner")));
+
+ /* Modify the owner --- okay to scribble on tup because it's a copy */
+ oprForm->oprowner = newOwnerSysId;
+
+ simple_heap_update(rel, &tup->t_self, tup);
+
+ CatalogUpdateIndexes(rel, tup);
+ }
+
+ heap_close(rel, NoLock);
+ heap_freetuple(tup);
+
+}
+
+
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 8366ea634a0..35e18c9bfbd 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.19 2004/06/18 06:13:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.20 2004/06/25 21:55:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -307,3 +307,48 @@ RenameSchema(const char *oldname, const char *newname)
heap_close(rel, NoLock);
heap_freetuple(tup);
}
+
+/*
+ * Change schema owner
+ */
+void
+AlterSchemaOwner(const char *name, AclId newOwnerSysId)
+{
+ HeapTuple tup;
+ Relation rel;
+ Form_pg_namespace nspForm;
+
+ rel = heap_openr(NamespaceRelationName, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy(NAMESPACENAME,
+ CStringGetDatum(name),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_SCHEMA),
+ errmsg("schema \"%s\" does not exist", name)));
+ nspForm = (Form_pg_namespace) GETSTRUCT(tup);
+
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
+ */
+ if (nspForm->nspowner != newOwnerSysId)
+ {
+ /* Otherwise, must be superuser to change object ownership */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change owner")));
+
+ /* Modify the owner --- okay to scribble on tup because it's a copy */
+ nspForm->nspowner = newOwnerSysId;
+
+ simple_heap_update(rel, &tup->t_self, tup);
+
+ CatalogUpdateIndexes(rel, tup);
+ }
+
+ heap_close(rel, NoLock);
+ heap_freetuple(tup);
+}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 8fd07e396ae..cfd8bd80cc0 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.116 2004/06/18 06:13:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.117 2004/06/25 21:55:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1921,11 +1921,6 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
pass = AT_PASS_MISC;
break;
case AT_ChangeOwner: /* ALTER OWNER */
- /* check that we are the superuser */
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to alter owner")));
/* This command never recurses */
/* No command-specific prep needed */
pass = AT_PASS_MISC;
@@ -5097,42 +5092,55 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
NameStr(tuple_class->relname))));
}
- /*
- * Okay, this is a valid tuple: change its ownership and write to the
- * heap.
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
*/
- tuple_class->relowner = newOwnerSysId;
- simple_heap_update(class_rel, &tuple->t_self, tuple);
+ if (tuple_class->relowner != newOwnerSysId)
+ {
+ /* Otherwise, check that we are the superuser */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change owner")));
- /* Keep the catalog indexes up to date */
- CatalogUpdateIndexes(class_rel, tuple);
+ /*
+ * Okay, this is a valid tuple: change its ownership and write to the
+ * heap.
+ */
+ tuple_class->relowner = newOwnerSysId;
+ simple_heap_update(class_rel, &tuple->t_self, tuple);
- /*
- * If we are operating on a table, also change the ownership of any
- * indexes that belong to the table, as well as the table's toast
- * table (if it has one)
- */
- if (tuple_class->relkind == RELKIND_RELATION ||
- tuple_class->relkind == RELKIND_TOASTVALUE)
- {
- List *index_oid_list;
- ListCell *i;
+ /* Keep the catalog indexes up to date */
+ CatalogUpdateIndexes(class_rel, tuple);
- /* Find all the indexes belonging to this relation */
- index_oid_list = RelationGetIndexList(target_rel);
+ /*
+ * If we are operating on a table, also change the ownership of any
+ * indexes that belong to the table, as well as the table's toast
+ * table (if it has one)
+ */
+ if (tuple_class->relkind == RELKIND_RELATION ||
+ tuple_class->relkind == RELKIND_TOASTVALUE)
+ {
+ List *index_oid_list;
+ ListCell *i;
- /* For each index, recursively change its ownership */
- foreach(i, index_oid_list)
- ATExecChangeOwner(lfirst_oid(i), newOwnerSysId);
+ /* Find all the indexes belonging to this relation */
+ index_oid_list = RelationGetIndexList(target_rel);
- list_free(index_oid_list);
- }
+ /* For each index, recursively change its ownership */
+ foreach(i, index_oid_list)
+ ATExecChangeOwner(lfirst_oid(i), newOwnerSysId);
- if (tuple_class->relkind == RELKIND_RELATION)
- {
- /* If it has a toast table, recurse to change its ownership */
- if (tuple_class->reltoastrelid != InvalidOid)
- ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerSysId);
+ list_free(index_oid_list);
+ }
+
+ if (tuple_class->relkind == RELKIND_RELATION)
+ {
+ /* If it has a toast table, recurse to change its ownership */
+ if (tuple_class->reltoastrelid != InvalidOid)
+ ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerSysId);
+ }
}
heap_freetuple(tuple);
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index 61e36d5b5c2..847985456f7 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -45,7 +45,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.3 2004/06/21 04:06:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.4 2004/06/25 21:55:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -669,3 +669,123 @@ get_tablespace_name(Oid spc_oid)
return result;
}
+
+/*
+ * Rename a tablespace
+ */
+void
+RenameTableSpace(const char *oldname, const char *newname)
+{
+ Relation rel;
+ ScanKeyData entry[1];
+ HeapScanDesc scan;
+ HeapTuple tup;
+ HeapTuple newtuple;
+ Form_pg_tablespace newform;
+
+ /* Search pg_tablespace */
+ rel = heap_openr(TableSpaceRelationName, RowExclusiveLock);
+
+ ScanKeyInit(&entry[0],
+ Anum_pg_tablespace_spcname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(oldname));
+ scan = heap_beginscan(rel, SnapshotNow, 1, entry);
+ tup = heap_getnext(scan, ForwardScanDirection);
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("tablespace \"%s\" does not exist",
+ oldname)));
+
+ newtuple = heap_copytuple(tup);
+ newform = (Form_pg_tablespace) GETSTRUCT(newtuple);
+
+ heap_endscan(scan);
+
+ /* Must be owner or superuser */
+ if (newform->spcowner != GetUserId() && !superuser())
+ aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE, oldname);
+
+ /* Validate new name */
+ if (!allowSystemTableMods && IsReservedName(newname))
+ ereport(ERROR,
+ (errcode(ERRCODE_RESERVED_NAME),
+ errmsg("unacceptable tablespace name \"%s\"", newname),
+ errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
+
+ /* Make sure the new name doesn't exist */
+ ScanKeyInit(&entry[0],
+ Anum_pg_tablespace_spcname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(newname));
+ scan = heap_beginscan(rel, SnapshotNow, 1, entry);
+ tup = heap_getnext(scan, ForwardScanDirection);
+ if (HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("tablespace \"%s\" already exists",
+ newname)));
+
+ heap_endscan(scan);
+
+ /* OK, update the entry */
+ namestrcpy(&(newform->spcname), newname);
+
+ simple_heap_update(rel, &newtuple->t_self, newtuple);
+ CatalogUpdateIndexes(rel, newtuple);
+
+ heap_close(rel, NoLock);
+}
+
+/*
+ * Change tablespace owner
+ */
+void
+AlterTableSpaceOwner(const char *name, AclId newOwnerSysId)
+{
+ Relation rel;
+ ScanKeyData entry[1];
+ HeapScanDesc scandesc;
+ Form_pg_tablespace spcForm;
+ HeapTuple tup;
+ HeapTuple newtuple;
+
+ /* Search pg_tablespace */
+ rel = heap_openr(TableSpaceRelationName, RowExclusiveLock);
+
+ ScanKeyInit(&entry[0],
+ Anum_pg_tablespace_spcname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(name));
+ scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);
+ tup = heap_getnext(scandesc, ForwardScanDirection);
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("tablespace \"%s\" does not exist", name)));
+
+ newtuple = heap_copytuple(tup);
+ spcForm = (Form_pg_tablespace) GETSTRUCT(newtuple);
+
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
+ */
+ if (spcForm->spcowner != newOwnerSysId)
+ {
+ /* Otherwise, must be superuser to change object ownership */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change owner")));
+
+ /* Modify the owner */
+ spcForm->spcowner = newOwnerSysId;
+ simple_heap_update(rel, &newtuple->t_self, newtuple);
+ CatalogUpdateIndexes(rel, newtuple);
+ }
+
+ heap_endscan(scandesc);
+ heap_close(rel, NoLock);
+}
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index d087ad8895c..f9f1caa8630 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.60 2004/06/18 06:13:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.61 2004/06/25 21:55:53 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -2042,14 +2042,7 @@ GetDomainConstraints(Oid typeOid)
}
/*
- * 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.
+ * Change the owner of a type.
*/
void
AlterTypeOwner(List *names, AclId newOwnerSysId)
@@ -2084,19 +2077,36 @@ AlterTypeOwner(List *names, AclId newOwnerSysId)
elog(ERROR, "cache lookup failed for type %u", typeOid);
typTup = (Form_pg_type) GETSTRUCT(tup);
- /* Check that this is actually a domain */
- if (typTup->typtype != 'd')
+ /*
+ * If it's a composite type, we need to check that it really is a
+ * free-standing composite type, and not a table's underlying type.
+ * We want people to use ALTER TABLE not ALTER TYPE for that case.
+ */
+ if (typTup->typtype == 'c' && get_rel_relkind(typTup->typrelid) != 'c')
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a domain",
+ errmsg("\"%s\" is a table's row type",
TypeNameToString(typename))));
- /* Modify the owner --- okay to scribble on typTup because it's a copy */
- typTup->typowner = newOwnerSysId;
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
+ */
+ if (typTup->typowner != newOwnerSysId)
+ {
+ /* Otherwise, must be superuser to change object ownership */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change owner")));
+
+ /* Modify the owner --- okay to scribble on typTup because it's a copy */
+ typTup->typowner = newOwnerSysId;
- simple_heap_update(rel, &tup->t_self, tup);
+ simple_heap_update(rel, &tup->t_self, tup);
- CatalogUpdateIndexes(rel, tup);
+ CatalogUpdateIndexes(rel, tup);
+ }
/* Clean up */
heap_close(rel, RowExclusiveLock);