On Fri, Jul 25, 2025 at 02:34:07PM -0500, Sami Imseih wrote:
> Sami Imseih <samims...@gmail.com> writes:
>> I think Michael's got a point.  As of HEAD there are seven different
>> places that are setting this to PLAN_CACHE_NONE; who's to say that
>> pg_stat_statements or some other extension might not wish to
>> distinguish some of those sources?  At the very least, user-submitted
>> versus internally-generated queries might be an interesting
>> distinction.  I don't have a concrete proposal for a different
>> categorization than what we've got, but it seems worth considering
>> while we still have the flexibility to change it easily.
> 
> Sure, I get it now, I think. An example is the cached plan from a sql
> in a utility statement of a prepared statement, as an example. right?

Attached is my counter-proposal, where I have settled down to four
categories of PlannedStmt:
- "standard" PlannedStmt, when going through the planner.
- internally-generated "fake" PlannedStmt.
- custom cache
- generic cache

We could decide if a few more of the internal "fake" ones are worth
subdividing, but I am feeling that this is kind of OK to start with.
If we want more granularity, I was wondering about some bits to be
able to mix one or more of these categories, but they are all
exclusive as far as I know.
--
Michael
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 46e2e09ea35b..0d125e7d47c1 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -29,18 +29,18 @@
  */
 
 /* ----------------
- *		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_INTERNAL = 0,		/* 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 +72,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/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index fcd5fcd8915e..77f8461f42ee 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 c00f1a11384f..0f03d9743d20 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 fc76f22fb823..f098a5557cf0 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 a77b2147e959..d59d6e4c6a02 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 a297606cdd7f..0cecd4649020 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 babc34d0cbe1..4f4191b0ea6b 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 f4d2b9458a5e..0c506d320b13 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/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 3daba26b2372..e6f2e93b2d6f 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

Attachment: signature.asc
Description: PGP signature

Reply via email to