aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execMain.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r--src/backend/executor/execMain.c117
1 files changed, 55 insertions, 62 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 12ff4f3de58..872b879387b 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -54,6 +54,7 @@
#include "jit/jit.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
+#include "parser/parse_relation.h"
#include "parser/parsetree.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
@@ -74,7 +75,7 @@ ExecutorRun_hook_type ExecutorRun_hook = NULL;
ExecutorFinish_hook_type ExecutorFinish_hook = NULL;
ExecutorEnd_hook_type ExecutorEnd_hook = NULL;
-/* Hook for plugin to get control in ExecCheckRTPerms() */
+/* Hook for plugin to get control in ExecCheckPermissions() */
ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook = NULL;
/* decls for local routines only used within this module */
@@ -90,10 +91,10 @@ static void ExecutePlan(EState *estate, PlanState *planstate,
ScanDirection direction,
DestReceiver *dest,
bool execute_once);
-static bool ExecCheckRTEPerms(RangeTblEntry *rte);
-static bool ExecCheckRTEPermsModified(Oid relOid, Oid userid,
- Bitmapset *modifiedCols,
- AclMode requiredPerms);
+static bool ExecCheckOneRelPerms(RTEPermissionInfo *perminfo);
+static bool ExecCheckPermissionsModified(Oid relOid, Oid userid,
+ Bitmapset *modifiedCols,
+ AclMode requiredPerms);
static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt);
static char *ExecBuildSlotValueDescription(Oid reloid,
TupleTableSlot *slot,
@@ -554,8 +555,8 @@ ExecutorRewind(QueryDesc *queryDesc)
/*
- * ExecCheckRTPerms
- * Check access permissions for all relations listed in a range table.
+ * ExecCheckPermissions
+ * Check access permissions of relations mentioned in a query
*
* Returns true if permissions are adequate. Otherwise, throws an appropriate
* error if ereport_on_violation is true, or simply returns false otherwise.
@@ -565,73 +566,65 @@ ExecutorRewind(QueryDesc *queryDesc)
* passing, then RLS also needs to be consulted (and check_enable_rls()).
*
* See rewrite/rowsecurity.c.
+ *
+ * NB: rangeTable is no longer used by us, but kept around for the hooks that
+ * might still want to look at the RTEs.
*/
bool
-ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation)
+ExecCheckPermissions(List *rangeTable, List *rteperminfos,
+ bool ereport_on_violation)
{
ListCell *l;
bool result = true;
- foreach(l, rangeTable)
+ foreach(l, rteperminfos)
{
- RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
+ RTEPermissionInfo *perminfo = lfirst_node(RTEPermissionInfo, l);
- result = ExecCheckRTEPerms(rte);
+ Assert(OidIsValid(perminfo->relid));
+ result = ExecCheckOneRelPerms(perminfo);
if (!result)
{
- Assert(rte->rtekind == RTE_RELATION);
if (ereport_on_violation)
- aclcheck_error(ACLCHECK_NO_PRIV, get_relkind_objtype(get_rel_relkind(rte->relid)),
- get_rel_name(rte->relid));
+ aclcheck_error(ACLCHECK_NO_PRIV,
+ get_relkind_objtype(get_rel_relkind(perminfo->relid)),
+ get_rel_name(perminfo->relid));
return false;
}
}
if (ExecutorCheckPerms_hook)
- result = (*ExecutorCheckPerms_hook) (rangeTable,
+ result = (*ExecutorCheckPerms_hook) (rangeTable, rteperminfos,
ereport_on_violation);
return result;
}
/*
- * ExecCheckRTEPerms
- * Check access permissions for a single RTE.
+ * ExecCheckOneRelPerms
+ * Check access permissions for a single relation.
*/
static bool
-ExecCheckRTEPerms(RangeTblEntry *rte)
+ExecCheckOneRelPerms(RTEPermissionInfo *perminfo)
{
AclMode requiredPerms;
AclMode relPerms;
AclMode remainingPerms;
- Oid relOid;
Oid userid;
+ Oid relOid = perminfo->relid;
- /*
- * Only plain-relation RTEs need to be checked here. Function RTEs are
- * checked when the function is prepared for execution. Join, subquery,
- * and special RTEs need no checks.
- */
- if (rte->rtekind != RTE_RELATION)
- return true;
-
- /*
- * No work if requiredPerms is empty.
- */
- requiredPerms = rte->requiredPerms;
- if (requiredPerms == 0)
- return true;
-
- relOid = rte->relid;
+ requiredPerms = perminfo->requiredPerms;
+ Assert(requiredPerms != 0);
/*
* userid to check as: current user unless we have a setuid indication.
*
* Note: GetUserId() is presently fast enough that there's no harm in
- * calling it separately for each RTE. If that stops being true, we could
- * call it once in ExecCheckRTPerms and pass the userid down from there.
- * But for now, no need for the extra clutter.
+ * calling it separately for each relation. If that stops being true, we
+ * could call it once in ExecCheckPermissions and pass the userid down
+ * from there. But for now, no need for the extra clutter.
*/
- userid = OidIsValid(rte->checkAsUser) ? rte->checkAsUser : GetUserId();
+ userid = OidIsValid(perminfo->checkAsUser) ?
+ perminfo->checkAsUser : GetUserId();
/*
* We must have *all* the requiredPerms bits, but some of the bits can be
@@ -665,14 +658,14 @@ ExecCheckRTEPerms(RangeTblEntry *rte)
* example, SELECT COUNT(*) FROM table), allow the query if we
* have SELECT on any column of the rel, as per SQL spec.
*/
- if (bms_is_empty(rte->selectedCols))
+ if (bms_is_empty(perminfo->selectedCols))
{
if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
ACLMASK_ANY) != ACLCHECK_OK)
return false;
}
- while ((col = bms_next_member(rte->selectedCols, col)) >= 0)
+ while ((col = bms_next_member(perminfo->selectedCols, col)) >= 0)
{
/* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
AttrNumber attno = col + FirstLowInvalidHeapAttributeNumber;
@@ -697,29 +690,31 @@ ExecCheckRTEPerms(RangeTblEntry *rte)
* Basically the same for the mod columns, for both INSERT and UPDATE
* privilege as specified by remainingPerms.
*/
- if (remainingPerms & ACL_INSERT && !ExecCheckRTEPermsModified(relOid,
- userid,
- rte->insertedCols,
- ACL_INSERT))
+ if (remainingPerms & ACL_INSERT &&
+ !ExecCheckPermissionsModified(relOid,
+ userid,
+ perminfo->insertedCols,
+ ACL_INSERT))
return false;
- if (remainingPerms & ACL_UPDATE && !ExecCheckRTEPermsModified(relOid,
- userid,
- rte->updatedCols,
- ACL_UPDATE))
+ if (remainingPerms & ACL_UPDATE &&
+ !ExecCheckPermissionsModified(relOid,
+ userid,
+ perminfo->updatedCols,
+ ACL_UPDATE))
return false;
}
return true;
}
/*
- * ExecCheckRTEPermsModified
- * Check INSERT or UPDATE access permissions for a single RTE (these
+ * ExecCheckPermissionsModified
+ * Check INSERT or UPDATE access permissions for a single relation (these
* are processed uniformly).
*/
static bool
-ExecCheckRTEPermsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols,
- AclMode requiredPerms)
+ExecCheckPermissionsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols,
+ AclMode requiredPerms)
{
int col = -1;
@@ -773,17 +768,14 @@ ExecCheckXactReadOnly(PlannedStmt *plannedstmt)
* Fail if write permissions are requested in parallel mode for table
* (temp or non-temp), otherwise fail for any non-temp table.
*/
- foreach(l, plannedstmt->rtable)
+ foreach(l, plannedstmt->permInfos)
{
- RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
-
- if (rte->rtekind != RTE_RELATION)
- continue;
+ RTEPermissionInfo *perminfo = lfirst_node(RTEPermissionInfo, l);
- if ((rte->requiredPerms & (~ACL_SELECT)) == 0)
+ if ((perminfo->requiredPerms & (~ACL_SELECT)) == 0)
continue;
- if (isTempNamespace(get_rel_namespace(rte->relid)))
+ if (isTempNamespace(get_rel_namespace(perminfo->relid)))
continue;
PreventCommandIfReadOnly(CreateCommandName((Node *) plannedstmt));
@@ -815,9 +807,10 @@ InitPlan(QueryDesc *queryDesc, int eflags)
int i;
/*
- * Do permissions checks
+ * Do permissions checks and save the list for later use.
*/
- ExecCheckRTPerms(rangeTable, true);
+ ExecCheckPermissions(rangeTable, plannedstmt->permInfos, true);
+ estate->es_rteperminfos = plannedstmt->permInfos;
/*
* initialize the node's execution state