From aa3de3f0770cf7f2b91d70de90922fdfce947cf5 Mon Sep 17 00:00:00 2001
From: amitlan <amitlangote09@gmail.com>
Date: Wed, 7 Jun 2023 21:00:58 +0900
Subject: [PATCH v39 2/4] Add a PlannedStmt field to store RT indexes of
 once-child relations

A future commit will teach the executor to lock only the child tables
appearing in a plan and to identify those tables it will rely on the
fact that plan tree subnodes to scan the child tables normally appear
under an Append/MergeAppend node.  But when there's only one child
subnode, setrefs.c removes the redundant Append/MergeAppend node,
making it impossible for the executor to identify the subnode as
scanning a child table.

This commit makes setrefs.c store the RT indexes of child tables
scanned by such once-child subnodes into a new field of PlannedStmt
called elidedAppendChildRelations.

There are no users of that field as of this commit but the
aforementioned future commit will use it to lock child tables that
don't appears under Append/MergeAppend.
---
 src/backend/optimizer/plan/planner.c |  1 +
 src/backend/optimizer/plan/setrefs.c | 97 ++++++++++++++++++++++++++++
 src/include/nodes/pathnodes.h        |  3 +
 src/include/nodes/plannodes.h        |  2 +
 4 files changed, 103 insertions(+)

diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 8e3d2c1e35..27a4c7585a 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -526,6 +526,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
 	result->permInfos = glob->finalrteperminfos;
 	result->resultRelations = glob->resultRelations;
 	result->appendRelations = glob->appendRelations;
+	result->elidedAppendChildRels = glob->elidedAppendChildRels;
 	result->subplans = glob->subplans;
 	result->rewindPlanIDs = glob->rewindPlanIDs;
 	result->rowMarks = glob->finalrowmarks;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index c4db6812ec..8ccc869bdd 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -16,6 +16,7 @@
 #include "postgres.h"
 
 #include "access/transam.h"
+#include "catalog/pg_class.h"
 #include "catalog/pg_type.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
@@ -134,6 +135,7 @@ static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte);
 static bool flatten_rtes_walker(Node *node, flatten_rtes_walker_context *cxt);
 static void add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos,
 								   RangeTblEntry *rte);
+static List *add_plan_scanrelids(List *scanrelids, Plan *plan);
 static Plan *set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset);
 static Plan *set_indexonlyscan_references(PlannerInfo *root,
 										  IndexOnlyScan *plan,
@@ -601,6 +603,93 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos,
 	}
 }
 
+/*
+ * Recursively adds the RT index(es) of the relation(s) scanned by plan
+ * to 'scanrelids'.
+ */
+static List *
+add_plan_scanrelids(List *scanrelids, Plan *plan)
+{
+	if (plan == NULL)
+		return scanrelids;
+
+	switch (nodeTag(plan))
+	{
+		case T_SeqScan:
+		case T_SampleScan:
+		case T_IndexScan:
+		case T_IndexOnlyScan:
+		case T_BitmapHeapScan:
+		case T_TidScan:
+		case T_TidRangeScan:
+		case T_SubqueryScan:
+		case T_FunctionScan:
+		case T_TableFuncScan:
+		case T_ValuesScan:
+		case T_CteScan:
+		case T_WorkTableScan:
+		case T_NamedTuplestoreScan:
+		case T_ForeignScan:
+		case T_CustomScan:
+			scanrelids = lappend_int(scanrelids, ((Scan *) plan)->scanrelid);
+			break;
+
+		/* Recurse for nodes that have child plans. */
+		case T_Append:
+			{
+				Append *aplan = (Append *) plan;
+				ListCell *l;
+
+				foreach(l, aplan->appendplans)
+					scanrelids = add_plan_scanrelids(scanrelids,
+													 (Plan *) lfirst(l));
+			}
+			break;
+
+		case T_MergeAppend:
+			{
+				MergeAppend *mplan = (MergeAppend *) plan;
+				ListCell *l;
+
+				foreach(l, mplan->mergeplans)
+					scanrelids = add_plan_scanrelids(scanrelids,
+													 (Plan *) lfirst(l));
+			}
+			break;
+
+		case T_BitmapAnd:
+			{
+				BitmapAnd *baplan = (BitmapAnd *) plan;
+				ListCell *l;
+
+				foreach(l, baplan->bitmapplans)
+					scanrelids = add_plan_scanrelids(scanrelids,
+													 (Plan *) lfirst(l));
+			}
+			break;
+
+		case T_BitmapOr:
+			{
+				BitmapOr *boplan = (BitmapOr *) plan;
+				ListCell *l;
+
+				foreach(l, boplan->bitmapplans)
+					scanrelids = add_plan_scanrelids(scanrelids,
+													 (Plan *) lfirst(l));
+			}
+			break;
+
+		default:
+			break;
+	}
+
+	/* Recurse into child plans. */
+	scanrelids = add_plan_scanrelids(scanrelids, plan->lefttree);
+	scanrelids = add_plan_scanrelids(scanrelids, plan->righttree);
+
+	return scanrelids;
+}
+
 /*
  * set_plan_refs: recurse through the Plan nodes of a single subquery level
  */
@@ -1743,7 +1832,11 @@ set_append_references(PlannerInfo *root,
 		Plan	   *p = (Plan *) linitial(aplan->appendplans);
 
 		if (p->parallel_aware == aplan->plan.parallel_aware)
+		{
+			root->glob->elidedAppendChildRels =
+				add_plan_scanrelids(root->glob->elidedAppendChildRels, p);
 			return clean_up_removed_plan_level((Plan *) aplan, p);
+		}
 	}
 
 	/*
@@ -1821,7 +1914,11 @@ set_mergeappend_references(PlannerInfo *root,
 		Plan	   *p = (Plan *) linitial(mplan->mergeplans);
 
 		if (p->parallel_aware == mplan->plan.parallel_aware)
+		{
+			root->glob->elidedAppendChildRels =
+				add_plan_scanrelids(root->glob->elidedAppendChildRels, p);
 			return clean_up_removed_plan_level((Plan *) mplan, p);
+		}
 	}
 
 	/*
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index c17b53f7ad..4303482499 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -125,6 +125,9 @@ typedef struct PlannerGlobal
 	/* "flat" list of AppendRelInfos */
 	List	   *appendRelations;
 
+	/* "flat" list of integer RT indexes */
+	List	   *elidedAppendChildRels;
+
 	/* OIDs of relations the plan depends on */
 	List	   *relationOids;
 
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 7a5f3ba625..203268d1ba 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -80,6 +80,8 @@ typedef struct PlannedStmt
 
 	List	   *appendRelations;	/* list of AppendRelInfo nodes */
 
+	List	   *elidedAppendChildRels; /* "flat" list of integer RT indexes */
+
 	List	   *subplans;		/* Plan trees for SubPlan expressions; note
 								 * that some could be NULL */
 
-- 
2.35.3

