Clean up loose ends remaining from schema privileges discussion.

I concluded that RENAME should require CREATE privilege on the namespace
as well as ownership of the table.
This commit is contained in:
Tom Lane 2002-04-30 01:26:26 +00:00
parent 4c25a0655b
commit e4f06dc12e
5 changed files with 86 additions and 26 deletions

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.24 2002/04/29 22:28:19 tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.25 2002/04/30 01:26:25 tgl Exp $
PostgreSQL documentation
-->
@ -161,6 +161,8 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
</para>
<para>
For schemas, allows new objects to be created within the schema.
To rename an existing object, you must own the object <emphasis>and</>
have this privilege for the containing schema.
</para>
</listitem>
</varlistentry>

View File

@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.15 2002/04/29 22:15:07 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.16 2002/04/30 01:26:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1161,7 +1161,12 @@ GetTempTableNamespace(void)
{
/*
* First use of this temp namespace in this database; create it.
* The temp namespaces are always owned by the superuser.
* The temp namespaces are always owned by the superuser. We
* leave their permissions at default --- i.e., no access except to
* superuser --- to ensure that unprivileged users can't peek
* at other backends' temp tables. This works because the places
* that access the temp namespace for my own backend skip permissions
* checks on it.
*/
namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID);
/* Advance command counter to make namespace visible */

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.152 2002/04/27 03:45:03 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.153 2002/04/30 01:26:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -374,25 +374,49 @@ ProcessUtility(Node *parsetree,
case T_RenameStmt:
{
RenameStmt *stmt = (RenameStmt *) parsetree;
Oid relid;
CheckOwnership(stmt->relation, true);
relid = RangeVarGetRelid(stmt->relation, false);
switch (stmt->renameType)
{
case RENAME_TABLE:
renamerel(RangeVarGetRelid(stmt->relation, false),
stmt->newname);
{
/*
* RENAME TABLE requires that we (still) hold CREATE
* rights on the containing namespace, as well as
* ownership of the table. But skip check for
* temp tables.
*/
Oid namespaceId = get_rel_namespace(relid);
if (!isTempNamespace(namespaceId))
{
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 RENAME_COLUMN:
renameatt(RangeVarGetRelid(stmt->relation, false),
stmt->oldname, /* old att name */
stmt->newname, /* new att name */
interpretInhOption(stmt->relation->inhOpt)); /* recursive? */
renameatt(relid,
stmt->oldname, /* old att name */
stmt->newname, /* new att name */
interpretInhOption(stmt->relation->inhOpt)); /* recursive? */
break;
case RENAME_TRIGGER:
renametrig(RangeVarGetRelid(stmt->relation, false),
stmt->oldname, /* old att name */
stmt->newname); /* new att name */
renametrig(relid,
stmt->oldname, /* old att name */
stmt->newname); /* new att name */
break;
case RENAME_RULE:
elog(ERROR, "ProcessUtility: Invalid target for RENAME: %d",
@ -410,6 +434,9 @@ ProcessUtility(Node *parsetree,
case T_AlterTableStmt:
{
AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
Oid relid;
relid = RangeVarGetRelid(stmt->relation, false);
/*
* Some or all of these functions are recursive to cover
@ -422,7 +449,7 @@ ProcessUtility(Node *parsetree,
* Recursively add column to table and,
* if requested, to descendants
*/
AlterTableAddColumn(RangeVarGetRelid(stmt->relation, false),
AlterTableAddColumn(relid,
interpretInhOption(stmt->relation->inhOpt),
(ColumnDef *) stmt->def);
break;
@ -431,18 +458,18 @@ ProcessUtility(Node *parsetree,
* Recursively alter column default for table and,
* if requested, for descendants
*/
AlterTableAlterColumnDefault(RangeVarGetRelid(stmt->relation, false),
AlterTableAlterColumnDefault(relid,
interpretInhOption(stmt->relation->inhOpt),
stmt->name,
stmt->def);
break;
case 'N': /* ALTER COLUMN DROP NOT NULL */
AlterTableAlterColumnDropNotNull(RangeVarGetRelid(stmt->relation, false),
AlterTableAlterColumnDropNotNull(relid,
interpretInhOption(stmt->relation->inhOpt),
stmt->name);
break;
case 'O': /* ALTER COLUMN SET NOT NULL */
AlterTableAlterColumnSetNotNull(RangeVarGetRelid(stmt->relation, false),
AlterTableAlterColumnSetNotNull(relid,
interpretInhOption(stmt->relation->inhOpt),
stmt->name);
break;
@ -452,7 +479,7 @@ ProcessUtility(Node *parsetree,
* Recursively alter column statistics for table and,
* if requested, for descendants
*/
AlterTableAlterColumnFlags(RangeVarGetRelid(stmt->relation, false),
AlterTableAlterColumnFlags(relid,
interpretInhOption(stmt->relation->inhOpt),
stmt->name,
stmt->def,
@ -464,7 +491,7 @@ ProcessUtility(Node *parsetree,
* Recursively drop column from table and,
* if requested, from descendants
*/
AlterTableDropColumn(RangeVarGetRelid(stmt->relation, false),
AlterTableDropColumn(relid,
interpretInhOption(stmt->relation->inhOpt),
stmt->name,
stmt->behavior);
@ -474,7 +501,7 @@ ProcessUtility(Node *parsetree,
* Recursively add constraint to table and,
* if requested, to descendants
*/
AlterTableAddConstraint(RangeVarGetRelid(stmt->relation, false),
AlterTableAddConstraint(relid,
interpretInhOption(stmt->relation->inhOpt),
(List *) stmt->def);
break;
@ -483,21 +510,20 @@ ProcessUtility(Node *parsetree,
* Recursively drop constraint from table and,
* if requested, from descendants
*/
AlterTableDropConstraint(RangeVarGetRelid(stmt->relation, false),
AlterTableDropConstraint(relid,
interpretInhOption(stmt->relation->inhOpt),
stmt->name,
stmt->behavior);
break;
case 'E': /* CREATE TOAST TABLE */
AlterTableCreateToastTable(RangeVarGetRelid(stmt->relation, false),
false);
AlterTableCreateToastTable(relid, false);
break;
case 'U': /* ALTER OWNER */
/* check that we are the superuser */
if (!superuser())
elog(ERROR, "ALTER TABLE: permission denied");
/* get_usesysid raises an error if no such user */
AlterTableOwner(RangeVarGetRelid(stmt->relation, false),
AlterTableOwner(relid,
get_usesysid(stmt->name));
break;
default: /* oops */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.71 2002/04/27 03:45:03 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.72 2002/04/30 01:26:26 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@ -708,6 +708,32 @@ get_rel_name(Oid relid)
return NULL;
}
/*
* get_rel_namespace
*
* Returns the pg_namespace OID associated with a given relation.
*/
Oid
get_rel_namespace(Oid relid)
{
HeapTuple tp;
tp = SearchSysCache(RELOID,
ObjectIdGetDatum(relid),
0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
Oid result;
result = reltup->relnamespace;
ReleaseSysCache(tp);
return result;
}
else
return InvalidOid;
}
/*
* get_rel_type_id
*

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: lsyscache.h,v 1.50 2002/04/27 03:45:03 tgl Exp $
* $Id: lsyscache.h,v 1.51 2002/04/30 01:26:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -42,6 +42,7 @@ extern Oid get_func_rettype(Oid funcid);
extern char func_volatile(Oid funcid);
extern Oid get_relname_relid(const char *relname, Oid relnamespace);
extern char *get_rel_name(Oid relid);
extern Oid get_rel_namespace(Oid relid);
extern Oid get_rel_type_id(Oid relid);
extern bool get_typisdefined(Oid typid);
extern int16 get_typlen(Oid typid);