1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-31 17:02:12 +03:00

Support column-level privileges, as required by SQL standard.

Stephen Frost, with help from KaiGai Kohei and others
This commit is contained in:
Tom Lane
2009-01-22 20:16:10 +00:00
parent bf136cf6e3
commit 3cb5d6580a
59 changed files with 2314 additions and 722 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.132 2009/01/06 23:46:06 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.133 2009/01/22 20:16:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -705,11 +705,12 @@ examine_attribute(Relation onerel, int attnum)
return NULL;
/*
* Create the VacAttrStats struct.
* Create the VacAttrStats struct. Note that we only have a copy of
* the fixed fields of the pg_attribute tuple.
*/
stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
stats->attr = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
memcpy(stats->attr, attr, ATTRIBUTE_TUPLE_SIZE);
stats->attr = (Form_pg_attribute) palloc(ATTRIBUTE_FIXED_PART_SIZE);
memcpy(stats->attr, attr, ATTRIBUTE_FIXED_PART_SIZE);
typtuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(attr->atttypid),
0, 0, 0);

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.277 2009/01/12 08:54:26 petere Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.278 2009/01/22 20:16:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -246,6 +246,7 @@ static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
static Oid transformFkeyCheckAttrs(Relation pkrel,
int numattrs, int16 *attnums,
Oid *opclasses);
static void checkFkeyPermissions(Relation rel, int16 *attnums, int natts);
static void validateForeignKeyConstraint(FkConstraint *fkconstraint,
Relation rel, Relation pkrel, Oid constraintOid);
static void createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
@@ -3589,6 +3590,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
attribute.attisdropped = false;
attribute.attislocal = colDef->is_local;
attribute.attinhcount = colDef->inhcount;
/* attribute.attacl is handled by InsertPgAttributeTuple */
ReleaseSysCache(typeTuple);
@@ -4473,15 +4475,14 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
* Add a foreign-key constraint to a single table
*
* Subroutine for ATExecAddConstraint. Must already hold exclusive
* lock on the rel, and have done appropriate validity/permissions checks
* for it.
* lock on the rel, and have done appropriate validity checks for it.
* We do permissions checks here, however.
*/
static void
ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
FkConstraint *fkconstraint)
{
Relation pkrel;
AclResult aclresult;
int16 pkattnum[INDEX_MAX_KEYS];
int16 fkattnum[INDEX_MAX_KEYS];
Oid pktypoid[INDEX_MAX_KEYS];
@@ -4506,10 +4507,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
pkrel = heap_openrv(fkconstraint->pktable, AccessExclusiveLock);
/*
* Validity and permissions checks
*
* Note: REFERENCES permissions checks are redundant with CREATE TRIGGER,
* but we may as well error out sooner instead of later.
* Validity checks (permission checks wait till we have the column numbers)
*/
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
ereport(ERROR,
@@ -4517,24 +4515,12 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
errmsg("referenced relation \"%s\" is not a table",
RelationGetRelationName(pkrel))));
aclresult = pg_class_aclcheck(RelationGetRelid(pkrel), GetUserId(),
ACL_REFERENCES);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(pkrel));
if (!allowSystemTableMods && IsSystemRelation(pkrel))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied: \"%s\" is a system catalog",
RelationGetRelationName(pkrel))));
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
ACL_REFERENCES);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(rel));
/*
* Disallow reference from permanent table to temp table or vice versa.
* (The ban on perm->temp is for fairly obvious reasons. The ban on
@@ -4598,6 +4584,12 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
opclasses);
}
/*
* Now we can check permissions.
*/
checkFkeyPermissions(pkrel, pkattnum, numpks);
checkFkeyPermissions(rel, fkattnum, numfks);
/*
* Look up the equality operators to use in the constraint.
*
@@ -5016,6 +5008,30 @@ transformFkeyCheckAttrs(Relation pkrel,
return indexoid;
}
/* Permissions checks for ADD FOREIGN KEY */
static void
checkFkeyPermissions(Relation rel, int16 *attnums, int natts)
{
Oid roleid = GetUserId();
AclResult aclresult;
int i;
/* Okay if we have relation-level REFERENCES permission */
aclresult = pg_class_aclcheck(RelationGetRelid(rel), roleid,
ACL_REFERENCES);
if (aclresult == ACLCHECK_OK)
return;
/* Else we must have REFERENCES on each column */
for (i = 0; i < natts; i++)
{
aclresult = pg_attribute_aclcheck(RelationGetRelid(rel), attnums[i],
roleid, ACL_REFERENCES);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(rel));
}
}
/*
* Scan the existing rows in a table to verify they meet a proposed FK
* constraint.
@@ -5123,7 +5139,7 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
fk_trigger->constrrel = fkconstraint->pktable;
fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, constraintOid);
(void) CreateTrigger(fk_trigger, constraintOid, false);
/* Make changes-so-far visible */
CommandCounterIncrement();
@@ -5204,7 +5220,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
}
fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, constraintOid);
(void) CreateTrigger(fk_trigger, constraintOid, false);
/* Make changes-so-far visible */
CommandCounterIncrement();
@@ -5256,7 +5272,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
}
fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, constraintOid);
(void) CreateTrigger(fk_trigger, constraintOid, false);
}
/*

View File

@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.60 2009/01/20 18:59:37 heikki Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.61 2009/01/22 20:16:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -455,7 +455,7 @@ DropTableSpace(DropTableSpaceStmt *stmt)
/*
* Remove dependency on owner.
*/
deleteSharedDependencyRecordsFor(TableSpaceRelationId, tablespaceoid);
deleteSharedDependencyRecordsFor(TableSpaceRelationId, tablespaceoid, 0);
/*
* Acquire TablespaceCreateLock to ensure that no TablespaceCreateDbspace

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.245 2009/01/22 19:16:31 heikki Exp $
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.246 2009/01/22 20:16:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -74,11 +74,16 @@ static void AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event,
* be made to link the trigger to that constraint. constraintOid is zero when
* executing a user-entered CREATE TRIGGER command.
*
* If checkPermissions is true we require ACL_TRIGGER permissions on the
* relation. If not, the caller already checked permissions. (This is
* currently redundant with constraintOid being zero, but it's clearer to
* have a separate argument.)
*
* Note: can return InvalidOid if we decided to not create a trigger at all,
* but a foreign-key constraint. This is a kluge for backwards compatibility.
*/
Oid
CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid, bool checkPermissions)
{
int16 tgtype;
int2vector *tgattr;
@@ -117,36 +122,26 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
errmsg("permission denied: \"%s\" is a system catalog",
RelationGetRelationName(rel))));
if (stmt->isconstraint && stmt->constrrel != NULL)
constrrelid = RangeVarGetRelid(stmt->constrrel, false);
/* permission checks */
if (stmt->isconstraint)
if (checkPermissions)
{
/* constraint trigger */
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
ACL_REFERENCES);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(rel));
if (stmt->constrrel != NULL)
{
constrrelid = RangeVarGetRelid(stmt->constrrel, false);
aclresult = pg_class_aclcheck(constrrelid, GetUserId(),
ACL_REFERENCES);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
get_rel_name(constrrelid));
}
}
else
{
/* regular trigger */
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
ACL_TRIGGER);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(rel));
if (OidIsValid(constrrelid))
{
aclresult = pg_class_aclcheck(constrrelid, GetUserId(),
ACL_TRIGGER);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
get_rel_name(constrrelid));
}
}
/* Compute tgtype */

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tsearchcmds.c,v 1.15 2009/01/01 17:23:40 momjian Exp $
* $PostgreSQL: pgsql/src/backend/commands/tsearchcmds.c,v 1.16 2009/01/22 20:16:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1255,7 +1255,7 @@ makeConfigurationDependencies(HeapTuple tuple, bool removeOld,
if (removeOld)
{
deleteDependencyRecordsFor(myself.classId, myself.objectId);
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId);
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
}
/*

View File

@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.184 2009/01/01 17:23:40 momjian Exp $
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.185 2009/01/22 20:16:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1123,9 +1123,17 @@ GrantRole(GrantRoleStmt *stmt)
*/
foreach(item, stmt->granted_roles)
{
char *rolename = strVal(lfirst(item));
Oid roleid = get_roleid_checked(rolename);
AccessPriv *priv = (AccessPriv *) lfirst(item);
char *rolename = priv->priv_name;
Oid roleid;
/* Must reject priv(columns) and ALL PRIVILEGES(columns) */
if (rolename == NULL || priv->cols != NIL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
roleid = get_roleid_checked(rolename);
if (stmt->is_grant)
AddRoleMems(rolename, roleid,
stmt->grantee_roles, grantee_ids,