1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

Support renaming of tablespaces, and changing the owners of

aggregates, conversions, functions, operators, operator classes,
schemas, types, and tablespaces.  Fold the existing implementations
of alter domain owner and alter database owner in with these.

Christopher Kings-Lynne
This commit is contained in:
Tom Lane
2004-06-25 21:55:59 +00:00
parent 1621192b11
commit 0adfa2c39d
40 changed files with 1380 additions and 234 deletions

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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 */
/* 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")));
/* change owner */
newtuple = heap_copytuple(tuple);
((Form_pg_database) GETSTRUCT(newtuple))->datdba = newdatdba;
simple_heap_update(rel, &tuple->t_self, newtuple);
CatalogUpdateIndexes(rel, newtuple);
datForm = (Form_pg_database) GETSTRUCT(newtuple);
/*
* 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 */
datForm->datdba = newOwnerSysId;
simple_heap_update(rel, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(rel, newtuple);
}
systable_endscan(scan);
heap_close(rel, NoLock);

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
/* Keep the catalog indexes up to date */
CatalogUpdateIndexes(class_rel, 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)
if (tuple_class->relowner != newOwnerSysId)
{
List *index_oid_list;
ListCell *i;
/* Otherwise, check that we are the superuser */
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to change owner")));
/* Find all the indexes belonging to this relation */
index_oid_list = RelationGetIndexList(target_rel);
/*
* 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);
/* For each index, recursively change its ownership */
foreach(i, index_oid_list)
ATExecChangeOwner(lfirst_oid(i), newOwnerSysId);
/* Keep the catalog indexes up to date */
CatalogUpdateIndexes(class_rel, tuple);
list_free(index_oid_list);
}
/*
* 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;
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);
/* Find all the indexes belonging to this relation */
index_oid_list = RelationGetIndexList(target_rel);
/* For each index, recursively change its ownership */
foreach(i, index_oid_list)
ATExecChangeOwner(lfirst_oid(i), 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);

View File

@@ -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);
}

View File

@@ -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")));
simple_heap_update(rel, &tup->t_self, tup);
/* Modify the owner --- okay to scribble on typTup because it's a copy */
typTup->typowner = newOwnerSysId;
CatalogUpdateIndexes(rel, tup);
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
}
/* Clean up */
heap_close(rel, RowExclusiveLock);