From aa3ba9d3e8b96db8383219e3942b2d87c0c9ed9c Mon Sep 17 00:00:00 2001
From: "okbob@github.com" <pavel.stehule@gmail.com>
Date: Mon, 6 Jan 2025 17:37:14 +0100
Subject: [PATCH 03/23] use bitmapset of parid instead of varid for calculation
 of variable excluded from ACL_SELECT check

Originaly we stored oid of session variables to bitmapset checkSelectPermVarid.
Storing high oid to bitmapset is not too effective (it can consume lot of memory
(for low custom oid about 2kB). But we can store position in sessionVariable list
instead. These possitions are low numbers starting by zero. It reduces memory
usage for bitmapset to just tens bytes.
---
 src/backend/executor/execMain.c      |  2 +-
 src/backend/optimizer/plan/planner.c | 11 +++++++----
 src/backend/optimizer/plan/setrefs.c | 10 +++++-----
 src/include/nodes/pathnodes.h        |  8 ++++----
 src/include/nodes/plannodes.h        |  9 +++++----
 5 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index a49fe560365..0c6f001ac31 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -238,7 +238,7 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
 			 * only UPDATE variable). In this case the permission check
 			 * is executed in write time.
 			 */
-			if (varid != queryDesc->plannedstmt->exclSelectPermCheckVarid)
+			if (i != queryDesc->plannedstmt->exclSelectPermCheckVarIdx)
 			{
 				AclResult	aclresult;
 
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 11f736b4374..45d6ce07f20 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -334,8 +334,8 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
 	glob->transientPlan = false;
 	glob->dependsOnRole = false;
 	glob->sessionVariables = NIL;
-	glob->basenodeSessionVarid = InvalidOid;
-	glob->checkSelectPermVarids = NULL;
+	glob->basenodeSessionVarIdx = -1;
+	glob->checkSelectPermVarIdxs = NULL;
 
 	/*
 	 * Assess whether it's feasible to use parallel mode for this query. We
@@ -578,8 +578,11 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
 	 * for assignemnt indirection should be excluded from permission
 	 * check.
 	 */
-	if (!bms_is_member(glob->basenodeSessionVarid, glob->checkSelectPermVarids))
-		result->exclSelectPermCheckVarid = glob->basenodeSessionVarid;
+	if ((glob->basenodeSessionVarIdx != -1) &&
+		(!bms_is_member(glob->basenodeSessionVarIdx, glob->checkSelectPermVarIdxs)))
+			result->exclSelectPermCheckVarIdx = glob->basenodeSessionVarIdx;
+	else
+		result->exclSelectPermCheckVarIdx = -1;
 
 	result->stmt_location = parse->stmt_location;
 	result->stmt_len = parse->stmt_len;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 95e85381175..4eb1e799c96 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -2174,15 +2174,15 @@ fix_param_node(PlannerInfo *root, Param *p)
 		if (p->parambasenode)
 		{
 			/* the variable can be used only once as base node */
-			Assert(!(OidIsValid(root->glob->basenodeSessionVarid)));
+			Assert(root->glob->basenodeSessionVarIdx == -1);
 
-			root->glob->basenodeSessionVarid = p->paramvarid;
+			root->glob->basenodeSessionVarIdx = p->paramid;
 		}
 		else
 		{
-			root->glob->checkSelectPermVarids =
-							  bms_add_member(root->glob->checkSelectPermVarids,
-											 p->paramvarid);
+			root->glob->checkSelectPermVarIdxs =
+							  bms_add_member(root->glob->checkSelectPermVarIdxs,
+											 p->paramid);
 		}
 
 		return (Node *) p;
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index f1a93d5b34a..c1dd5a64c41 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -167,11 +167,11 @@ typedef struct PlannerGlobal
 	/* list of used session variables */
 	List	   *sessionVariables;
 
-	/* oid of session variable used like base node for assignment indirection */
-	Oid			basenodeSessionVarid;
+	/* position of session variable used like base node for assignment indirection */
+	int			basenodeSessionVarIdx;
 
-	/* set of session variables where execute permission check is required */
-	Bitmapset *checkSelectPermVarids;
+	/* set of positions from sessionvariables where execute permission check is required */
+	Bitmapset *checkSelectPermVarIdxs;
 } PlannerGlobal;
 
 /* macro for fetching the Plan associated with a SubPlan node */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 7095ddd6f3d..a7b8990831a 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -97,11 +97,12 @@ typedef struct PlannedStmt
 	List	   *sessionVariables;	/* OIDs for PARAM_VARIABLE Params */
 
 	/*
-	 * The oid of session variable execlued from permission check.
-	 * It can be id of session variable used like base node of assignment
-	 * indirection if this variable is used only there.
+	 * The position (in sessionVariables list) of session variable execluded
+	 * from permission check. This can be a position of session variable
+	 * used as base node of assignment indirection (when this session
+	 * variable is used only there).
 	 */
-	Oid			exclSelectPermCheckVarid;
+	int			exclSelectPermCheckVarIdx;
 
 	/* statement location in source string (copied from Query) */
 	ParseLoc	stmt_location;	/* start location, or -1 if unknown */
-- 
2.47.1

