v1-0002-refactoring-LET-statement-self-assign-privileg.no-cfbot

application/octet-stream

Filename: v1-0002-refactoring-LET-statement-self-assign-privileg.no-cfbot
Type: application/octet-stream
Part: 1
Message: Re: Re: proposal: schema variables
From 52b238edc235d3f207be6840da513a79682d8f11 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Mon, 6 Jan 2025 15:45:09 +0800
Subject: [PATCH v1 2/2] refactoring LET statement self assign privilege check

---
 src/backend/optimizer/plan/planner.c |  9 ++++---
 src/backend/optimizer/plan/setrefs.c | 37 ++++++++++++++++++++--------
 src/include/nodes/parsenodes.h       |  9 +++++++
 src/include/nodes/pathnodes.h        |  6 -----
 4 files changed, 41 insertions(+), 20 deletions(-)

diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 11f736b437..a21d8e48c6 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -334,8 +334,6 @@ 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;
 
 	/*
 	 * Assess whether it's feasible to use parallel mode for this query. We
@@ -578,8 +576,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 (OidIsValid(root->parse->resultVariable) &&
+		!root->parse->is_Variable_assigned)
+		result->exclSelectPermCheckVarid = root->parse->resultVariable;
+	else
+		result->exclSelectPermCheckVarid = InvalidOid;
 
 	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 95e8538117..e627185388 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -2171,18 +2171,35 @@ fix_param_node(PlannerInfo *root, Param *p)
 		 * indirection. In this case we must not do SELECT permission check.
 		 * In other cases we have do SELECT permission check.
 		 */
-		if (p->parambasenode)
+		if (!p->parambasenode)
 		{
-			/* the variable can be used only once as base node */
-			Assert(!(OidIsValid(root->glob->basenodeSessionVarid)));
+			bool		exists = false;
+			PlannerInfo *temp_root	= NULL;
+			temp_root = root;
+			do
+			{
+				if (temp_root->parse &&
+					OidIsValid(temp_root->parse->resultVariable) &&
+					(p->paramvarid == temp_root->parse->resultVariable))
+				{
+					exists = true;
+					break;
+				}
+				temp_root = temp_root->parent_root;
+			}
+			while (temp_root != NULL);
 
-			root->glob->basenodeSessionVarid = p->paramvarid;
-		}
-		else
-		{
-			root->glob->checkSelectPermVarids =
-							  bms_add_member(root->glob->checkSelectPermVarids,
-											 p->paramvarid);
+			if (exists)
+			{
+				temp_root = root;
+				do
+				{
+					if (temp_root->parse)
+						temp_root->parse->is_Variable_assigned = true;
+					temp_root = temp_root->parent_root;
+				}
+				while (temp_root != NULL);
+			}
 		}
 
 		return (Node *) p;
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index b417b56c2a..653fa52113 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -145,6 +145,15 @@ typedef struct Query
 	/* target variable of LET statement */
 	Oid			resultVariable;
 
+	/* true if session variables is in both sides of LET statement, this flag is
+	 * set recursively for parent_root. for LET statement, when we assigned
+	 * value to a variable, we don't need check users SELECT priviledge for that
+	 * variable, but if variable is in both side of LET statement, then we do
+	 * need check the session variable SELECT priviledge again current user.
+	 * for example LET v1.a = v1.a.
+	*/
+	bool		is_Variable_assigned;
+
 	/* has aggregates in tlist or havingQual */
 	bool		hasAggs pg_node_attr(query_jumble_ignore);
 	/* has window functions in tlist */
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index f1a93d5b34..880bb2a26f 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -166,12 +166,6 @@ typedef struct PlannerGlobal
 
 	/* list of used session variables */
 	List	   *sessionVariables;
-
-	/* oid of session variable used like base node for assignment indirection */
-	Oid			basenodeSessionVarid;
-
-	/* set of session variables where execute permission check is required */
-	Bitmapset *checkSelectPermVarids;
 } PlannerGlobal;
 
 /* macro for fetching the Plan associated with a SubPlan node */
-- 
2.34.1