@ -82,6 +82,9 @@ static void ExecutePlan(EState *estate, PlanState *planstate,
ScanDirection direction ,
DestReceiver * dest ) ;
static bool ExecCheckRTEPerms ( RangeTblEntry * rte ) ;
static bool ExecCheckRTEPermsModified ( Oid relOid , Oid userid ,
Bitmapset * modifiedCols ,
AclMode requiredPerms ) ;
static void ExecCheckXactReadOnly ( PlannedStmt * plannedstmt ) ;
static char * ExecBuildSlotValueDescription ( Oid reloid ,
TupleTableSlot * slot ,
@ -92,13 +95,15 @@ static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
Plan * planTree ) ;
/*
* Note that this macro also exists in commands / trigger . c . There does not
* appear to be any good header to put it into , given the structures that
* Note that GetUpdatedColumns ( ) also exists in commands / trigger . c . There does
* not appear to be any good header to put it into , given the structures that
* it uses , so we let them be duplicated . Be sure to update both if one needs
* to be changed , however .
*/
# define GetModifiedColumns(relinfo, estate) \
( rt_fetch ( ( relinfo ) - > ri_RangeTableIndex , ( estate ) - > es_range_table ) - > modifiedCols )
# define GetInsertedColumns(relinfo, estate) \
( rt_fetch ( ( relinfo ) - > ri_RangeTableIndex , ( estate ) - > es_range_table ) - > insertedCols )
# define GetUpdatedColumns(relinfo, estate) \
( rt_fetch ( ( relinfo ) - > ri_RangeTableIndex , ( estate ) - > es_range_table ) - > updatedCols )
/* end of local decls */
@ -571,7 +576,6 @@ ExecCheckRTEPerms(RangeTblEntry *rte)
AclMode remainingPerms ;
Oid relOid ;
Oid userid ;
int col ;
/*
* Only plain - relation RTEs need to be checked here . Function RTEs are
@ -609,6 +613,8 @@ ExecCheckRTEPerms(RangeTblEntry *rte)
remainingPerms = requiredPerms & ~ relPerms ;
if ( remainingPerms ! = 0 )
{
int col = - 1 ;
/*
* If we lack any permissions that exist only as relation permissions ,
* we can fail straight away .
@ -637,7 +643,6 @@ ExecCheckRTEPerms(RangeTblEntry *rte)
return false ;
}
col = - 1 ;
while ( ( col = bms_next_member ( rte - > selectedCols , col ) ) > = 0 )
{
/* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
@ -660,43 +665,63 @@ ExecCheckRTEPerms(RangeTblEntry *rte)
}
/*
* Basically the same for the mod columns , with either INSERT or
* UPDATE privilege as specified by remainingPerms .
* Basically the same for the mod columns , for both INSERT and UPDATE
* privilege as specified by remainingPerms .
*/
remainingPerms & = ~ ACL_SELECT ;
if ( remainingPerms ! = 0 )
{
/*
* When the query doesn ' t explicitly change any columns , allow the
* query if we have permission on any column of the rel . This is
* to handle SELECT FOR UPDATE as well as possible corner cases in
* INSERT and UPDATE .
*/
if ( bms_is_empty ( rte - > modifiedCols ) )
{
if ( pg_attribute_aclcheck_all ( relOid , userid , remainingPerms ,
ACLMASK_ANY ) ! = ACLCHECK_OK )
return false ;
}
if ( remainingPerms & ACL_INSERT & & ! ExecCheckRTEPermsModified ( relOid ,
userid ,
rte - > insertedCols ,
ACL_INSERT ) )
return false ;
col = - 1 ;
while ( ( col = bms_next_member ( rte - > modifiedCols , col ) ) > = 0 )
{
/* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
AttrNumber attno = col + FirstLowInvalidHeapAttributeNumber ;
if ( remainingPerms & ACL_UPDATE & & ! ExecCheckRTEPermsModified ( relOid ,
userid ,
rte - > updatedCols ,
ACL_UPDATE ) )
return false ;
}
return true ;
}
if ( attno = = InvalidAttrNumber )
{
/* whole-row reference can't happen here */
elog ( ERROR , " whole-row update is not implemented " ) ;
}
else
{
if ( pg_attribute_aclcheck ( relOid , attno , userid ,
remainingPerms ) ! = ACLCHECK_OK )
return false ;
}
}
/*
* ExecCheckRTEPermsModified
* Check INSERT or UPDATE access permissions for a single RTE ( these
* are processed uniformly ) .
*/
static bool
ExecCheckRTEPermsModified ( Oid relOid , Oid userid , Bitmapset * modifiedCols ,
AclMode requiredPerms )
{
int col = - 1 ;
/*
* When the query doesn ' t explicitly update any columns , allow the
* query if we have permission on any column of the rel . This is
* to handle SELECT FOR UPDATE as well as possible corner cases in
* UPDATE .
*/
if ( bms_is_empty ( modifiedCols ) )
{
if ( pg_attribute_aclcheck_all ( relOid , userid , requiredPerms ,
ACLMASK_ANY ) ! = ACLCHECK_OK )
return false ;
}
while ( ( col = bms_next_member ( modifiedCols , col ) ) > = 0 )
{
/* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
AttrNumber attno = col + FirstLowInvalidHeapAttributeNumber ;
if ( attno = = InvalidAttrNumber )
{
/* whole-row reference can't happen here */
elog ( ERROR , " whole-row update is not implemented " ) ;
}
else
{
if ( pg_attribute_aclcheck ( relOid , attno , userid ,
requiredPerms ) ! = ACLCHECK_OK )
return false ;
}
}
return true ;
@ -1633,6 +1658,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
Relation rel = resultRelInfo - > ri_RelationDesc ;
TupleDesc tupdesc = RelationGetDescr ( rel ) ;
TupleConstr * constr = tupdesc - > constr ;
Bitmapset * modifiedCols ;
Bitmapset * insertedCols ;
Bitmapset * updatedCols ;
Assert ( constr ) ;
@ -1647,9 +1675,10 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
slot_attisnull ( slot , attrChk ) )
{
char * val_desc ;
Bitmapset * modifiedCols ;
modifiedCols = GetModifiedColumns ( resultRelInfo , estate ) ;
insertedCols = GetInsertedColumns ( resultRelInfo , estate ) ;
updatedCols = GetUpdatedColumns ( resultRelInfo , estate ) ;
modifiedCols = bms_union ( insertedCols , updatedCols ) ;
val_desc = ExecBuildSlotValueDescription ( RelationGetRelid ( rel ) ,
slot ,
tupdesc ,
@ -1673,9 +1702,10 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
if ( ( failed = ExecRelCheck ( resultRelInfo , slot , estate ) ) ! = NULL )
{
char * val_desc ;
Bitmapset * modifiedCols ;
modifiedCols = GetModifiedColumns ( resultRelInfo , estate ) ;
insertedCols = GetInsertedColumns ( resultRelInfo , estate ) ;
updatedCols = GetUpdatedColumns ( resultRelInfo , estate ) ;
modifiedCols = bms_union ( insertedCols , updatedCols ) ;
val_desc = ExecBuildSlotValueDescription ( RelationGetRelid ( rel ) ,
slot ,
tupdesc ,
@ -1746,6 +1776,8 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
{
char * val_desc ;
Bitmapset * modifiedCols ;
Bitmapset * insertedCols ;
Bitmapset * updatedCols ;
switch ( wco - > kind )
{
@ -1758,7 +1790,9 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
* as that depends on the USING policy .
*/
case WCO_VIEW_CHECK :
modifiedCols = GetModifiedColumns ( resultRelInfo , estate ) ;
insertedCols = GetInsertedColumns ( resultRelInfo , estate ) ;
updatedCols = GetUpdatedColumns ( resultRelInfo , estate ) ;
modifiedCols = bms_union ( insertedCols , updatedCols ) ;
val_desc = ExecBuildSlotValueDescription ( RelationGetRelid ( rel ) ,
slot ,
tupdesc ,