From d8dc62eb1c22d0d9a38a3938e501740501756a6a Mon Sep 17 00:00:00 2001
From: Sami Imseih <simseih@amazon.com>
Date: Tue, 29 Jul 2025 15:37:33 -0500
Subject: [PATCH v16 1/2] Introduce planOrigin field in PlannedStmt to replace
 CachedPlanType

Commit 719dcf3c42 introduced a field called CachedPlanType in
PlannedStmt to allow extensions to determine whether a cached plan is
generic or custom.

Since this field is attached to PlannedStmt, it was proposed to
generalize it into a new field called planOrigin. This field captures
where the PlannedStmt originated, such as internal, standard_planner,
custom, or generic. While these are the currently defined origins, it
is conceivable that more granular categories may be added in the
future, for example, internal plans from CTAS.

The planOrigin field also defines a default UNKNOWN value to simplify
handling in code paths where a PlannedStmt may not yet be available.
This makes it easier to distinguish unset states from valid origins.

Discussion: https://www.postgresql.org/message-id/1933906.1753462272%40sss.pgh.pa.us
---
 src/backend/commands/foreigncmds.c   |  2 +-
 src/backend/commands/schemacmds.c    |  2 +-
 src/backend/executor/execParallel.c  |  2 +-
 src/backend/optimizer/plan/planner.c |  2 +-
 src/backend/tcop/postgres.c          |  2 +-
 src/backend/tcop/utility.c           |  4 ++--
 src/backend/utils/cache/plancache.c  |  2 +-
 src/include/nodes/plannodes.h        | 21 +++++++++++----------
 src/tools/pgindent/typedefs.list     |  2 +-
 9 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index fcd5fcd8915..77f8461f42e 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -1588,7 +1588,7 @@ ImportForeignSchema(ImportForeignSchemaStmt *stmt)
 			pstmt->utilityStmt = (Node *) cstmt;
 			pstmt->stmt_location = rs->stmt_location;
 			pstmt->stmt_len = rs->stmt_len;
-			pstmt->cached_plan_type = PLAN_CACHE_NONE;
+			pstmt->planOrigin = PLAN_STMT_INTERNAL;
 
 			/* Execute statement */
 			ProcessUtility(pstmt, cmd, false,
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index c00f1a11384..0f03d9743d2 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -215,7 +215,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
 		wrapper->utilityStmt = stmt;
 		wrapper->stmt_location = stmt_location;
 		wrapper->stmt_len = stmt_len;
-		wrapper->cached_plan_type = PLAN_CACHE_NONE;
+		wrapper->planOrigin = PLAN_STMT_INTERNAL;
 
 		/* do this step */
 		ProcessUtility(wrapper,
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index fc76f22fb82..f098a5557cf 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -189,7 +189,7 @@ ExecSerializePlan(Plan *plan, EState *estate)
 	pstmt->permInfos = estate->es_rteperminfos;
 	pstmt->resultRelations = NIL;
 	pstmt->appendRelations = NIL;
-	pstmt->cached_plan_type = PLAN_CACHE_NONE;
+	pstmt->planOrigin = PLAN_STMT_INTERNAL;
 
 	/*
 	 * Transfer only parallel-safe subplans, leaving a NULL "hole" in the list
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index a77b2147e95..d59d6e4c6a0 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -558,6 +558,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
 
 	result->commandType = parse->commandType;
 	result->queryId = parse->queryId;
+	result->planOrigin = PLAN_STMT_STANDARD;
 	result->hasReturning = (parse->returningList != NIL);
 	result->hasModifyingCTE = parse->hasModifyingCTE;
 	result->canSetTag = parse->canSetTag;
@@ -582,7 +583,6 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
 	result->utilityStmt = parse->utilityStmt;
 	result->stmt_location = parse->stmt_location;
 	result->stmt_len = parse->stmt_len;
-	result->cached_plan_type = PLAN_CACHE_NONE;
 
 	result->jitFlags = PGJIT_NONE;
 	if (jit_enabled && jit_above_cost >= 0 &&
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index a297606cdd7..0cecd464902 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -988,7 +988,7 @@ pg_plan_queries(List *querytrees, const char *query_string, int cursorOptions,
 			stmt->stmt_location = query->stmt_location;
 			stmt->stmt_len = query->stmt_len;
 			stmt->queryId = query->queryId;
-			stmt->cached_plan_type = PLAN_CACHE_NONE;
+			stmt->planOrigin = PLAN_STMT_INTERNAL;
 		}
 		else
 		{
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index babc34d0cbe..4f4191b0ea6 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1234,7 +1234,7 @@ ProcessUtilitySlow(ParseState *pstate,
 							wrapper->utilityStmt = stmt;
 							wrapper->stmt_location = pstmt->stmt_location;
 							wrapper->stmt_len = pstmt->stmt_len;
-							wrapper->cached_plan_type = PLAN_CACHE_NONE;
+							wrapper->planOrigin = PLAN_STMT_INTERNAL;
 
 							ProcessUtility(wrapper,
 										   queryString,
@@ -1965,7 +1965,7 @@ ProcessUtilityForAlterTable(Node *stmt, AlterTableUtilityContext *context)
 	wrapper->utilityStmt = stmt;
 	wrapper->stmt_location = context->pstmt->stmt_location;
 	wrapper->stmt_len = context->pstmt->stmt_len;
-	wrapper->cached_plan_type = PLAN_CACHE_NONE;
+	wrapper->planOrigin = PLAN_STMT_INTERNAL;
 
 	ProcessUtility(wrapper,
 				   context->queryString,
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index f4d2b9458a5..0c506d320b1 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -1390,7 +1390,7 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
 	{
 		PlannedStmt *pstmt = (PlannedStmt *) lfirst(lc);
 
-		pstmt->cached_plan_type = customplan ? PLAN_CACHE_CUSTOM : PLAN_CACHE_GENERIC;
+		pstmt->planOrigin = customplan ? PLAN_STMT_CACHE_CUSTOM : PLAN_STMT_CACHE_GENERIC;
 	}
 
 	return plan;
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 6d8e1e99db3..29d7732d6a0 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -29,18 +29,19 @@
  */
 
 /* ----------------
- *		CachedPlanType
+ *		PlannedStmtOrigin
  *
- * CachedPlanType identifies whether a PlannedStmt is a cached plan, and if
- * so, whether it is generic or custom.
+ * PlannedStmtOrigin identifies from where a PlannedStmt comes from.
  * ----------------
  */
-typedef enum CachedPlanType
+typedef enum PlannedStmtOrigin
 {
-	PLAN_CACHE_NONE = 0,		/* Not a cached plan */
-	PLAN_CACHE_GENERIC,			/* Generic cached plan */
-	PLAN_CACHE_CUSTOM,			/* Custom cached plan */
-} CachedPlanType;
+	PLAN_STMT_UNKNOWN = 0,		/* plan origin is not yet known */
+	PLAN_STMT_INTERNAL,			/* generated internally by a query */
+	PLAN_STMT_STANDARD,			/* standard planned statement */
+	PLAN_STMT_CACHE_GENERIC,	/* Generic cached plan */
+	PLAN_STMT_CACHE_CUSTOM,		/* Custom cached plan */
+} PlannedStmtOrigin;
 
 /* ----------------
  *		PlannedStmt node
@@ -72,8 +73,8 @@ typedef struct PlannedStmt
 	/* plan identifier (can be set by plugins) */
 	int64		planId;
 
-	/* type of cached plan */
-	CachedPlanType cached_plan_type;
+	/* origin of plan */
+	PlannedStmtOrigin planOrigin;
 
 	/* is it insert|update|delete|merge RETURNING? */
 	bool		hasReturning;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 3daba26b237..e6f2e93b2d6 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -391,7 +391,6 @@ CachedFunctionHashEntry
 CachedFunctionHashKey
 CachedPlan
 CachedPlanSource
-CachedPlanType
 CallContext
 CallStmt
 CancelRequestPacket
@@ -2276,6 +2275,7 @@ PlanInvalItem
 PlanRowMark
 PlanState
 PlannedStmt
+PlannedStmtOrigin
 PlannerGlobal
 PlannerInfo
 PlannerParamItem
-- 
2.39.5 (Apple Git-154)

