diff options
| author | Peter Eisentraut | 2003-06-27 14:45:32 +0000 |
|---|---|---|
| committer | Peter Eisentraut | 2003-06-27 14:45:32 +0000 |
| commit | b256f2426433c56b4bea3a8102757749885b81ba (patch) | |
| tree | bd2b9b75720dd850bffbf40bf3d2440b1639a904 /src/backend/commands | |
| parent | 5bac7d11ddbf19688fd5da87ffbd991a1b06aa4a (diff) | |
First batch of object rename commands.
Diffstat (limited to 'src/backend/commands')
| -rw-r--r-- | src/backend/commands/Makefile | 4 | ||||
| -rw-r--r-- | src/backend/commands/aggregatecmds.c | 75 | ||||
| -rw-r--r-- | src/backend/commands/alter.c | 159 | ||||
| -rw-r--r-- | src/backend/commands/analyze.c | 4 | ||||
| -rw-r--r-- | src/backend/commands/comment.c | 40 | ||||
| -rw-r--r-- | src/backend/commands/conversioncmds.c | 62 | ||||
| -rw-r--r-- | src/backend/commands/dbcommands.c | 157 | ||||
| -rw-r--r-- | src/backend/commands/functioncmds.c | 68 | ||||
| -rw-r--r-- | src/backend/commands/indexcmds.c | 7 | ||||
| -rw-r--r-- | src/backend/commands/opclasscmds.c | 95 | ||||
| -rw-r--r-- | src/backend/commands/proclang.c | 46 | ||||
| -rw-r--r-- | src/backend/commands/schemacmds.c | 60 | ||||
| -rw-r--r-- | src/backend/commands/user.c | 108 | ||||
| -rw-r--r-- | src/backend/commands/vacuum.c | 4 |
14 files changed, 818 insertions, 71 deletions
diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile index db91bf1d0e0..2a0bf0ec83f 100644 --- a/src/backend/commands/Makefile +++ b/src/backend/commands/Makefile @@ -4,7 +4,7 @@ # Makefile for backend/commands # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.31 2002/08/27 04:55:07 tgl Exp $ +# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.32 2003/06/27 14:45:27 petere Exp $ # #------------------------------------------------------------------------- @@ -12,7 +12,7 @@ subdir = src/backend/commands top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -OBJS = aggregatecmds.o analyze.o async.o cluster.o comment.o \ +OBJS = aggregatecmds.o alter.o analyze.o async.o cluster.o comment.o \ conversioncmds.o copy.o \ dbcommands.o define.o explain.o functioncmds.o \ indexcmds.o lockcmds.o operatorcmds.o opclasscmds.o \ diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index bee50e686f0..1ea31a6a5a0 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.7 2003/06/25 21:30:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.8 2003/06/27 14:45:27 petere Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -25,6 +25,7 @@ #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/dependency.h" +#include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_proc.h" @@ -193,3 +194,75 @@ RemoveAggregate(RemoveAggrStmt *stmt) performDeletion(&object, stmt->behavior); } + + +void +RenameAggregate(List *name, TypeName *basetype, const char *newname) +{ + Oid basetypeOid; + Oid procOid; + Oid namespaceOid; + Oid oid_array[FUNC_MAX_ARGS]; + HeapTuple tup; + Relation rel; + AclResult aclresult; + + /* + * 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). + */ + if (basetype) + basetypeOid = typenameTypeId(basetype); + else + basetypeOid = ANYOID; + + rel = heap_openr(ProcedureRelationName, RowExclusiveLock); + + procOid = find_aggregate_func("RenameAggregate", name, basetypeOid); + + tup = SearchSysCacheCopy(PROCOID, + ObjectIdGetDatum(procOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "RenameAggregate: couldn't find pg_proc tuple for %s", + NameListToString(name)); + + namespaceOid = ((Form_pg_proc) GETSTRUCT(tup))->pronamespace; + + /* make sure the new name doesn't exist */ + MemSet(oid_array, 0, sizeof(oid_array)); + oid_array[0] = basetypeOid; + if (SearchSysCacheExists(PROCNAMENSP, + CStringGetDatum(newname), + Int16GetDatum(1), + PointerGetDatum(oid_array), + ObjectIdGetDatum(namespaceOid))) + { + if (basetypeOid == ANYOID) + elog(ERROR, "function %s(*) already exists in schema %s", + newname, get_namespace_name(namespaceOid)); + else + elog(ERROR, "function %s(%s) already exists in schema %s", + newname, format_type_be(basetypeOid), get_namespace_name(namespaceOid)); + } + + /* must be owner */ + if (!pg_proc_ownercheck(procOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name)); + + /* must have CREATE privilege on namespace */ + aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceOid)); + + /* rename */ + namestrcpy(&(((Form_pg_proc) GETSTRUCT(tup))->proname), newname); + 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 new file mode 100644 index 00000000000..65b27f5def3 --- /dev/null +++ b/src/backend/commands/alter.c @@ -0,0 +1,159 @@ +/*------------------------------------------------------------------------- + * + * alter.c + * Drivers for generic alter commands + * + * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/commands/alter.c,v 1.1 2003/06/27 14:45:27 petere Exp $ + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/htup.h" +#include "catalog/catalog.h" +#include "catalog/namespace.h" +#include "catalog/pg_class.h" +#include "commands/alter.h" +#include "commands/conversioncmds.h" +#include "commands/dbcommands.h" +#include "commands/defrem.h" +#include "commands/proclang.h" +#include "commands/schemacmds.h" +#include "commands/tablecmds.h" +#include "commands/trigger.h" +#include "commands/user.h" +#include "miscadmin.h" +#include "parser/parse_clause.h" +#include "utils/acl.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" + + +static void +CheckOwnership(RangeVar *rel, bool noCatalogs) +{ + Oid relOid; + HeapTuple tuple; + + relOid = RangeVarGetRelid(rel, false); + tuple = SearchSysCache(RELOID, + ObjectIdGetDatum(relOid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "Relation \"%s\" does not exist", rel->relname); + + if (!pg_class_ownercheck(relOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname); + + if (noCatalogs) + { + if (!allowSystemTableMods && + IsSystemClass((Form_pg_class) GETSTRUCT(tuple))) + elog(ERROR, "relation \"%s\" is a system catalog", + rel->relname); + } + + ReleaseSysCache(tuple); +} + + +void +ExecRenameStmt(RenameStmt *stmt) +{ + switch (stmt->renameType) + { + case OBJECT_AGGREGATE: + RenameAggregate(stmt->object, (TypeName *) lfirst(stmt->objarg), stmt->newname); + break; + + case OBJECT_CONVERSION: + RenameConversion(stmt->object, stmt->newname); + break; + + case OBJECT_DATABASE: + RenameDatabase(stmt->subname, stmt->newname); + break; + + case OBJECT_FUNCTION: + RenameFunction(stmt->object, stmt->objarg, stmt->newname); + break; + + case OBJECT_GROUP: + RenameGroup(stmt->subname, stmt->newname); + break; + + case OBJECT_LANGUAGE: + RenameLanguage(stmt->subname, stmt->newname); + break; + + case OBJECT_OPCLASS: + RenameOpClass(stmt->object, stmt->subname, stmt->newname); + break; + + case OBJECT_SCHEMA: + RenameSchema(stmt->subname, stmt->newname); + break; + + case OBJECT_USER: + RenameUser(stmt->subname, stmt->newname); + break; + + case OBJECT_TABLE: + case OBJECT_COLUMN: + case OBJECT_TRIGGER: + { + Oid relid; + + CheckOwnership(stmt->relation, true); + + relid = RangeVarGetRelid(stmt->relation, false); + + switch (stmt->renameType) + { + case OBJECT_TABLE: + { + /* + * RENAME TABLE requires that we (still) hold + * CREATE rights on the containing namespace, as + * well as ownership of the table. + */ + Oid namespaceId = get_rel_namespace(relid); + AclResult aclresult; + + aclresult = pg_namespace_aclcheck(namespaceId, + GetUserId(), + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, + get_namespace_name(namespaceId)); + + renamerel(relid, stmt->newname); + break; + } + case OBJECT_COLUMN: + renameatt(relid, + stmt->subname, /* old att name */ + stmt->newname, /* new att name */ + interpretInhOption(stmt->relation->inhOpt), /* recursive? */ + false); /* recursing already? */ + break; + case OBJECT_TRIGGER: + renametrig(relid, + stmt->subname, /* old att name */ + stmt->newname); /* new att name */ + break; + default: + /*can't happen*/; + } + break; + } + + default: + elog(ERROR, "invalid object type for RenameStmt: %d", stmt->renameType); + } +} diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index ad70a47753b..70d147f1207 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.54 2003/05/27 17:49:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.55 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -192,7 +192,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) onerel = relation_open(relid, AccessShareLock); if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) || - (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared))) + (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared))) { /* No need for a WARNING if we already complained during VACUUM */ if (!vacstmt->vacuum) diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 4176cf3cfd3..53974f396b2 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1996-2001, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.62 2003/03/10 22:28:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.63 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -71,40 +71,40 @@ CommentObject(CommentStmt *stmt) { switch (stmt->objtype) { - case COMMENT_ON_INDEX: - case COMMENT_ON_SEQUENCE: - case COMMENT_ON_TABLE: - case COMMENT_ON_VIEW: + case OBJECT_INDEX: + case OBJECT_SEQUENCE: + case OBJECT_TABLE: + case OBJECT_VIEW: CommentRelation(stmt->objtype, stmt->objname, stmt->comment); break; - case COMMENT_ON_COLUMN: + case OBJECT_COLUMN: CommentAttribute(stmt->objname, stmt->comment); break; - case COMMENT_ON_DATABASE: + case OBJECT_DATABASE: CommentDatabase(stmt->objname, stmt->comment); break; - case COMMENT_ON_RULE: + case OBJECT_RULE: CommentRule(stmt->objname, stmt->comment); break; - case COMMENT_ON_TYPE: + case OBJECT_TYPE: CommentType(stmt->objname, stmt->comment); break; - case COMMENT_ON_AGGREGATE: + case OBJECT_AGGREGATE: CommentAggregate(stmt->objname, stmt->objargs, stmt->comment); break; - case COMMENT_ON_FUNCTION: + case OBJECT_FUNCTION: CommentProc(stmt->objname, stmt->objargs, stmt->comment); break; - case COMMENT_ON_OPERATOR: + case OBJECT_OPERATOR: CommentOperator(stmt->objname, stmt->objargs, stmt->comment); break; - case COMMENT_ON_TRIGGER: + case OBJECT_TRIGGER: CommentTrigger(stmt->objname, stmt->comment); break; - case COMMENT_ON_SCHEMA: + case OBJECT_SCHEMA: CommentNamespace(stmt->objname, stmt->comment); break; - case COMMENT_ON_CONSTRAINT: + case OBJECT_CONSTRAINT: CommentConstraint(stmt->objname, stmt->comment); break; default: @@ -301,22 +301,22 @@ CommentRelation(int objtype, List *relname, char *comment) switch (objtype) { - case COMMENT_ON_INDEX: + case OBJECT_INDEX: if (relation->rd_rel->relkind != RELKIND_INDEX) elog(ERROR, "relation \"%s\" is not an index", RelationGetRelationName(relation)); break; - case COMMENT_ON_SEQUENCE: + case OBJECT_SEQUENCE: if (relation->rd_rel->relkind != RELKIND_SEQUENCE) elog(ERROR, "relation \"%s\" is not a sequence", RelationGetRelationName(relation)); break; - case COMMENT_ON_TABLE: + case OBJECT_TABLE: if (relation->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "relation \"%s\" is not a table", RelationGetRelationName(relation)); break; - case COMMENT_ON_VIEW: + case OBJECT_VIEW: if (relation->rd_rel->relkind != RELKIND_VIEW) elog(ERROR, "relation \"%s\" is not a view", RelationGetRelationName(relation)); @@ -410,7 +410,7 @@ CommentDatabase(List *qualname, char *comment) /* Allow if the user matches the database dba or is a superuser */ - if (!(superuser() || is_dbadmin(oid))) + if (!pg_database_ownercheck(oid, GetUserId())) elog(ERROR, "you are not permitted to comment on database \"%s\"", database); diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c index 6115b0e12e5..2d2fd66c4b3 100644 --- a/src/backend/commands/conversioncmds.c +++ b/src/backend/commands/conversioncmds.c @@ -8,14 +8,17 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.5 2002/11/02 02:33:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.6 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "catalog/pg_conversion.h" +#include "access/heapam.h" #include "catalog/catalog.h" +#include "catalog/catname.h" +#include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_type.h" #include "mb/pg_wchar.h" @@ -23,7 +26,9 @@ #include "miscadmin.h" #include "parser/parse_func.h" #include "utils/acl.h" +#include "utils/builtins.h" #include "utils/lsyscache.h" +#include "utils/syscache.h" /* @@ -98,3 +103,58 @@ DropConversionCommand(List *name, DropBehavior behavior) ConversionDrop(conversionOid, behavior); } + +/* + * Rename conversion + */ +void +RenameConversion(List *name, const char *newname) +{ + Oid conversionOid; + Oid namespaceOid; + HeapTuple tup; + Relation rel; + AclResult aclresult; + + rel = heap_openr(ConversionRelationName, RowExclusiveLock); + + conversionOid = FindConversionByName(name); + if (!OidIsValid(conversionOid)) + elog(ERROR, "conversion %s not found", NameListToString(name)); + + tup = SearchSysCacheCopy(CONOID, + ObjectIdGetDatum(conversionOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "couldn't find pg_conversion tuple for %s", + NameListToString(name)); + + namespaceOid = ((Form_pg_conversion) GETSTRUCT(tup))->connamespace; + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists(CONNAMENSP, + CStringGetDatum(newname), + ObjectIdGetDatum(namespaceOid), + 0, 0)) + { + elog(ERROR, "conversion %s already exists in schema %s", + newname, get_namespace_name(namespaceOid)); + } + + /* must be owner */ + if (!superuser() && ((Form_pg_conversion) GETSTRUCT(tup))->conowner != GetUserId()) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name)); + + /* must have CREATE privilege on namespace */ + aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceOid)); + + /* rename */ + namestrcpy(&(((Form_pg_conversion) GETSTRUCT(tup))->conname), newname); + 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 bd436878189..55f44f9d8cb 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.115 2003/05/15 17:59:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.116 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ #include <unistd.h> #include <sys/stat.h> +#include "access/genam.h" #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/catalog.h" @@ -31,6 +32,7 @@ #include "miscadmin.h" #include "storage/freespace.h" #include "storage/sinval.h" +#include "utils/acl.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -402,13 +404,13 @@ dropdb(const char *dbname) char *nominal_loc; char dbpath[MAXPGPATH]; Relation pgdbrel; - HeapScanDesc pgdbscan; + SysScanDesc pgdbscan; ScanKeyData key; HeapTuple tup; AssertArg(dbname); - if (strcmp(dbname, DatabaseName) == 0) + if (strcmp(dbname, get_database_name(MyDatabaseId)) == 0) elog(ERROR, "DROP DATABASE: cannot be executed on the currently open database"); PreventTransactionChain((void *) dbname, "DROP DATABASE"); @@ -454,9 +456,9 @@ dropdb(const char *dbname) ScanKeyEntryInitialize(&key, 0, ObjectIdAttributeNumber, F_OIDEQ, ObjectIdGetDatum(db_id)); - pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key); + pgdbscan = systable_beginscan(pgdbrel, DatabaseOidIndex, true, SnapshotNow, 1, &key); - tup = heap_getnext(pgdbscan, ForwardScanDirection); + tup = systable_getnext(pgdbscan); if (!HeapTupleIsValid(tup)) { /* @@ -470,7 +472,7 @@ dropdb(const char *dbname) /* Remove the database's tuple from pg_database */ simple_heap_delete(pgdbrel, &tup->t_self); - heap_endscan(pgdbscan); + systable_endscan(pgdbscan); /* * Delete any comments associated with the database @@ -513,6 +515,94 @@ dropdb(const char *dbname) } +/* + * Rename database + */ +void +RenameDatabase(const char *oldname, const char *newname) +{ + HeapTuple tup, newtup; + Relation rel; + SysScanDesc scan, scan2; + ScanKeyData key, key2; + + /* + * Obtain AccessExclusiveLock so that no new session gets started + * while the rename is in progress. + */ + rel = heap_openr(DatabaseRelationName, AccessExclusiveLock); + + ScanKeyEntryInitialize(&key, 0, Anum_pg_database_datname, + F_NAMEEQ, NameGetDatum(oldname)); + scan = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &key); + + tup = systable_getnext(scan); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("database \"%s\" does not exist", oldname))); + + /* + * XXX Client applications probably store the current database + * somewhere, so renaming it could cause confusion. On the other + * hand, there may not be an actual problem besides a little + * confusion, so think about this and decide. + */ + if (HeapTupleGetOid(tup) == MyDatabaseId) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("current database may not be renamed"))); + + /* + * Make sure the database does not have active sessions. Might + * not be necessary, but it's consistent with other database + * operations. + */ + if (DatabaseHasActiveBackends(HeapTupleGetOid(tup), false)) + elog(ERROR, "database \"%s\" is being accessed by other users", oldname); + + /* make sure the new name doesn't exist */ + ScanKeyEntryInitialize(&key2, 0, Anum_pg_database_datname, + F_NAMEEQ, NameGetDatum(newname)); + scan2 = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &key2); + if (HeapTupleIsValid(systable_getnext(scan2))) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("database \"%s\" already exists", newname))); + } + systable_endscan(scan2); + + /* must be owner */ + if (!pg_database_ownercheck(HeapTupleGetOid(tup), GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, oldname); + + /* must have createdb */ + if (!have_createdb_privilege()) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("permission denied"))); + } + + /* rename */ + newtup = heap_copytuple(tup); + namestrcpy(&(((Form_pg_database) GETSTRUCT(newtup))->datname), newname); + simple_heap_update(rel, &tup->t_self, newtup); + CatalogUpdateIndexes(rel, newtup); + + systable_endscan(scan); + heap_close(rel, NoLock); + + /* + * Force dirty buffers out to disk, so that newly-connecting + * backends will see the renamed database in pg_database right + * away. (They'll see an uncommitted tuple, but they don't care; + * see GetRawDatabaseInfo.) + */ + BufferSync(); +} + /* * ALTER DATABASE name SET ... @@ -525,7 +615,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) newtuple; Relation rel; ScanKeyData scankey; - HeapScanDesc scan; + SysScanDesc scan; Datum repl_val[Natts_pg_database]; char repl_null[Natts_pg_database]; char repl_repl[Natts_pg_database]; @@ -535,8 +625,8 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) rel = heap_openr(DatabaseRelationName, RowExclusiveLock); ScanKeyEntryInitialize(&scankey, 0, Anum_pg_database_datname, F_NAMEEQ, NameGetDatum(stmt->dbname)); - scan = heap_beginscan(rel, SnapshotNow, 1, &scankey); - tuple = heap_getnext(scan, ForwardScanDirection); + scan = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &scankey); + tuple = systable_getnext(scan); if (!HeapTupleIsValid(tuple)) elog(ERROR, "database \"%s\" does not exist", stmt->dbname); @@ -583,7 +673,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) /* Update indexes */ CatalogUpdateIndexes(rel, newtuple); - heap_endscan(scan); + systable_endscan(scan); heap_close(rel, RowExclusiveLock); } @@ -601,7 +691,7 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, { Relation relation; ScanKeyData scanKey; - HeapScanDesc scan; + SysScanDesc scan; HeapTuple tuple; bool gottuple; @@ -613,9 +703,9 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname, F_NAMEEQ, NameGetDatum(name)); - scan = heap_beginscan(relation, SnapshotNow, 1, &scanKey); + scan = systable_beginscan(relation, DatabaseNameIndex, true, SnapshotNow, 1, &scanKey); - tuple = heap_getnext(scan, ForwardScanDirection); + tuple = systable_getnext(scan); gottuple = HeapTupleIsValid(tuple); if (gottuple) @@ -667,7 +757,7 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, } } - heap_endscan(scan); + systable_endscan(scan); heap_close(relation, AccessShareLock); return gottuple; @@ -790,7 +880,7 @@ get_database_oid(const char *dbname) { Relation pg_database; ScanKeyData entry[1]; - HeapScanDesc scan; + SysScanDesc scan; HeapTuple dbtuple; Oid oid; @@ -799,9 +889,9 @@ get_database_oid(const char *dbname) ScanKeyEntryInitialize(&entry[0], 0x0, Anum_pg_database_datname, F_NAMEEQ, CStringGetDatum(dbname)); - scan = heap_beginscan(pg_database, SnapshotNow, 1, entry); + scan = systable_beginscan(pg_database, DatabaseNameIndex, true, SnapshotNow, 1, entry); - dbtuple = heap_getnext(scan, ForwardScanDirection); + dbtuple = systable_getnext(scan); /* We assume that there can be at most one matching tuple */ if (HeapTupleIsValid(dbtuple)) @@ -809,45 +899,46 @@ get_database_oid(const char *dbname) else oid = InvalidOid; - heap_endscan(scan); + systable_endscan(scan); heap_close(pg_database, AccessShareLock); return oid; } + /* - * get_database_owner - given a database OID, fetch the owner's usesysid. + * get_database_name - given a database OID, look up the name * - * Errors out if database not found. + * Returns InvalidOid if database name not found. * * This is not actually used in this file, but is exported for use elsewhere. */ -Oid -get_database_owner(Oid dbid) +char * +get_database_name(Oid dbid) { Relation pg_database; ScanKeyData entry[1]; - HeapScanDesc scan; + SysScanDesc scan; HeapTuple dbtuple; - int32 dba; + char *result; /* There's no syscache for pg_database, so must look the hard way */ pg_database = heap_openr(DatabaseRelationName, AccessShareLock); ScanKeyEntryInitialize(&entry[0], 0x0, ObjectIdAttributeNumber, F_OIDEQ, ObjectIdGetDatum(dbid)); - scan = heap_beginscan(pg_database, SnapshotNow, 1, entry); + scan = systable_beginscan(pg_database, DatabaseOidIndex, true, SnapshotNow, 1, entry); - dbtuple = heap_getnext(scan, ForwardScanDirection); + dbtuple = systable_getnext(scan); - if (!HeapTupleIsValid(dbtuple)) - elog(ERROR, "database %u does not exist", dbid); - - dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba; + /* We assume that there can be at most one matching tuple */ + if (HeapTupleIsValid(dbtuple)) + result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname)); + else + result = NULL; - heap_endscan(scan); + systable_endscan(scan); heap_close(pg_database, AccessShareLock); - /* XXX some confusion about whether userids are OID or int4 ... */ - return (Oid) dba; + return result; } diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index a0943993c16..47ac67b9dcd 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.25 2003/02/01 22:09:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.26 2003/06/27 14:45:27 petere Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -592,6 +592,72 @@ RemoveFunctionById(Oid funcOid) /* + * Rename function + */ +void +RenameFunction(List *name, List *argtypes, const char *newname) +{ + Oid procOid; + Oid namespaceOid; + Oid oid_array[FUNC_MAX_ARGS]; + HeapTuple tup; + Relation rel; + AclResult aclresult; + int16 nargs; + + rel = heap_openr(ProcedureRelationName, RowExclusiveLock); + + procOid = LookupFuncNameTypeNames(name, argtypes, "RenameFunction"); + + tup = SearchSysCacheCopy(PROCOID, + ObjectIdGetDatum(procOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "RenameFunction: couldn't find pg_proc tuple for %s", + NameListToString(name)); + + if (((Form_pg_proc) GETSTRUCT(tup))->proisagg) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("%s is an aggregate function", NameListToString(name)), + errhint("Use ALTER AGGREGATE to rename aggregate functions."))); + + namespaceOid = ((Form_pg_proc) GETSTRUCT(tup))->pronamespace; + + /* make sure the new name doesn't exist */ + nargs = compute_parameter_types(argtypes, ((Form_pg_proc) GETSTRUCT(tup))->prolang, oid_array); + if (SearchSysCacheExists(PROCNAMENSP, + CStringGetDatum(newname), + Int16GetDatum(nargs), + PointerGetDatum(oid_array), + ObjectIdGetDatum(namespaceOid))) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("function %s with the same argument types already exists in schema %s", + newname, get_namespace_name(namespaceOid)))); + } + + /* must be owner */ + if (!pg_proc_ownercheck(procOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name)); + + /* must have CREATE privilege on namespace */ + aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceOid)); + + /* rename */ + namestrcpy(&(((Form_pg_proc) GETSTRUCT(tup))->proname), newname); + 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 * * This is presently only used for adjusting legacy functions that return diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 4186a145795..151183c6455 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.100 2003/05/28 16:03:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.101 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -24,6 +24,7 @@ #include "catalog/namespace.h" #include "catalog/pg_opclass.h" #include "catalog/pg_proc.h" +#include "commands/dbcommands.h" #include "commands/defrem.h" #include "commands/tablecmds.h" #include "executor/executor.h" @@ -644,10 +645,10 @@ ReindexDatabase(const char *dbname, bool force, bool all) AssertArg(dbname); - if (strcmp(dbname, DatabaseName) != 0) + if (strcmp(dbname, get_database_name(MyDatabaseId)) != 0) elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database."); - if (!(superuser() || is_dbadmin(MyDatabaseId))) + if (!pg_database_ownercheck(MyDatabaseId, GetUserId())) elog(ERROR, "REINDEX DATABASE: Permission denied."); if (!allowSystemTableMods) diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index f67a1a6e81d..9b90698a26a 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.9 2002/11/13 00:39:46 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.10 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -550,7 +550,7 @@ RemoveOpClassById(Oid opclassOid) ObjectIdGetDatum(opclassOid), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "RemoveOpClassById: couldn't find pg_class entry %u", + elog(ERROR, "RemoveOpClassById: couldn't find pg_opclass entry %u", opclassOid); simple_heap_delete(rel, &tup->t_self); @@ -595,3 +595,94 @@ RemoveOpClassById(Oid opclassOid) systable_endscan(scan); heap_close(rel, RowExclusiveLock); } + + +/* + * Rename opclass + */ +void +RenameOpClass(List *name, const char *access_method, const char *newname) +{ + Oid opcOid; + Oid amOid; + Oid namespaceOid; + char *schemaname; + char *opcname; + HeapTuple tup; + Relation rel; + AclResult aclresult; + + amOid = GetSysCacheOid(AMNAME, + CStringGetDatum(access_method), + 0, 0, 0); + if (!OidIsValid(amOid)) + elog(ERROR, "access method \"%s\" not found", 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)) + elog(ERROR, "operator class \"%s\" for access method \"%s\" does not exist", + opcname, access_method); + + opcOid = HeapTupleGetOid(tup); + } + else + { + opcOid = OpclassnameGetOpcid(amOid, opcname); + if (!OidIsValid(opcOid)) + elog(ERROR, "operator class \"%s\" for access method \"%s\" does not exist", + opcname, access_method); + + tup = SearchSysCacheCopy(CLAOID, + ObjectIdGetDatum(opcOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "couldn't find pg_opclass tuple for %u", opcOid); + + namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace; + } + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists(CLAAMNAMENSP, + ObjectIdGetDatum(amOid), + CStringGetDatum(newname), + ObjectIdGetDatum(namespaceOid), + 0)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"", + newname, access_method, get_namespace_name(namespaceOid)))); + } + + /* must be owner */ + if (!pg_opclass_ownercheck(opcOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name)); + + /* must have CREATE privilege on namespace */ + aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceOid)); + + /* rename */ + namestrcpy(&(((Form_pg_opclass) GETSTRUCT(tup))->opcname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 03d022f1f4f..1e93c07fec5 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.43 2002/09/21 18:39:25 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.44 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -231,3 +231,47 @@ DropProceduralLanguageById(Oid langOid) heap_close(rel, RowExclusiveLock); } + +/* + * Rename language + */ +void +RenameLanguage(const char *oldname, const char *newname) +{ + HeapTuple tup; + Relation rel; + + rel = heap_openr(ShadowRelationName, RowExclusiveLock); + + tup = SearchSysCacheCopy(LANGNAME, + CStringGetDatum(oldname), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("language \"%s\" does not exist", oldname))); + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists(LANGNAME, + CStringGetDatum(newname), + 0, 0, 0)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("language \"%s\" already exists", newname))); + } + + /* must be superuser */ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("permission denied"))); + + /* rename */ + namestrcpy(&(((Form_pg_language) GETSTRUCT(tup))->lanname), newname); + 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 282fb19a85b..1d71f658459 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.9 2003/05/06 20:26:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.10 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -18,8 +18,10 @@ #include "catalog/catalog.h" #include "catalog/catname.h" #include "catalog/dependency.h" +#include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_namespace.h" +#include "commands/dbcommands.h" #include "commands/schemacmds.h" #include "miscadmin.h" #include "parser/analyze.h" @@ -86,7 +88,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) */ aclresult = pg_database_aclcheck(MyDatabaseId, saved_userid, ACL_CREATE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, DatabaseName); + aclcheck_error(aclresult, get_database_name(MyDatabaseId)); if (!allowSystemTableMods && IsReservedName(schemaName)) elog(ERROR, "CREATE SCHEMA: Illegal schema name: \"%s\" -- pg_ is reserved for system schemas", @@ -212,3 +214,57 @@ RemoveSchemaById(Oid schemaOid) heap_close(relation, RowExclusiveLock); } + + +/* + * Rename schema + */ +void +RenameSchema(const char *oldname, const char *newname) +{ + HeapTuple tup; + Relation rel; + AclResult aclresult; + + rel = heap_openr(NamespaceRelationName, RowExclusiveLock); + + tup = SearchSysCacheCopy(NAMESPACENAME, + CStringGetDatum(oldname), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("schema \"%s\" does not exist", oldname))); + + /* make sure the new name doesn't exist */ + if (HeapTupleIsValid( + SearchSysCache(NAMESPACENAME, + CStringGetDatum(newname), + 0, 0, 0))) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("schema \"%s\" already exists", newname))); + } + + /* must be owner */ + if (!pg_namespace_ownercheck(HeapTupleGetOid(tup), GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, oldname); + + /* must have CREATE privilege on database */ + aclresult = pg_database_aclcheck(MyDatabaseId, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_database_name(MyDatabaseId)); + + if (!allowSystemTableMods && IsReservedName(newname)) + elog(ERROR, "illegal schema name: \"%s\" -- pg_ is reserved for system schemas", + newname); + + /* rename */ + namestrcpy(&(((Form_pg_namespace) GETSTRUCT(tup))->nspname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index d31690aa246..be588b08632 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.117 2003/05/12 23:08:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.118 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -1091,6 +1091,64 @@ DropUser(DropUserStmt *stmt) } +/* + * Rename user + */ +void +RenameUser(const char *oldname, const char *newname) +{ + HeapTuple tup; + Relation rel; + + /* ExclusiveLock because we need to update the password file */ + rel = heap_openr(ShadowRelationName, ExclusiveLock); + + tup = SearchSysCacheCopy(SHADOWNAME, + CStringGetDatum(oldname), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("user \"%s\" does not exist", oldname))); + + /* + * XXX Client applications probably store the session user + * somewhere, so renaming it could cause confusion. On the other + * hand, there may not be an actual problem besides a little + * confusion, so think about this and decide. + */ + if (((Form_pg_shadow) GETSTRUCT(tup))->usesysid == GetSessionUserId()) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("session user may not be renamed"))); + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists(SHADOWNAME, + CStringGetDatum(newname), + 0, 0, 0)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("user \"%s\" already exists", newname))); + } + + /* must be superuser */ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("permission denied"))); + + /* rename */ + namestrcpy(&(((Form_pg_shadow) GETSTRUCT(tup))->usename), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); + + user_file_update_needed = true; +} + /* * CheckPgUserAclNotNull @@ -1566,3 +1624,51 @@ DropGroup(DropGroupStmt *stmt) */ group_file_update_needed = true; } + + +/* + * Rename group + */ +void +RenameGroup(const char *oldname, const char *newname) +{ + HeapTuple tup; + Relation rel; + + /* ExclusiveLock because we need to update the flat group file */ + rel = heap_openr(GroupRelationName, ExclusiveLock); + + tup = SearchSysCacheCopy(GRONAME, + CStringGetDatum(oldname), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("group \"%s\" does not exist", oldname))); + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists(GRONAME, + CStringGetDatum(newname), + 0, 0, 0)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("a group \"%s\" already exists", newname))); + } + + /* must be superuser */ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + errmsg("permission denied"))); + + /* rename */ + namestrcpy(&(((Form_pg_group) GETSTRUCT(tup))->groname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); + + group_file_update_needed = true; +} diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 93701b611ed..5c4faa5da24 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.255 2003/05/28 16:03:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.256 2003/06/27 14:45:27 petere Exp $ * *------------------------------------------------------------------------- */ @@ -771,7 +771,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) onerel = relation_open(relid, lmode); if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) || - (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared))) + (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared))) { elog(WARNING, "Skipping \"%s\" --- only table or database owner can VACUUM it", RelationGetRelationName(onerel)); |
