v2-0001-Make-SPI_prepare-argtypes-argument-const.patch

text/plain

Filename: v2-0001-Make-SPI_prepare-argtypes-argument-const.patch
Type: text/plain
Part: 0
Message: Re: Make SPI_prepare argtypes argument const

Patch

Format: format-patch
Series: patch v2-0001
Subject: Make SPI_prepare argtypes argument const
File+
contrib/postgres_fdw/postgres_fdw.c 3 3
doc/src/sgml/spi.sgml 4 4
src/backend/executor/spi.c 16 10
src/backend/utils/adt/ri_triggers.c 2 2
src/backend/utils/cache/plancache.c 1 1
src/include/executor/spi.h 4 4
src/include/executor/spi_priv.h 1 1
src/include/utils/plancache.h 1 1
From ad0857ce3c257ddc022ca48d93300d4f9957a489 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Sat, 25 Apr 2026 23:44:36 +0200
Subject: [PATCH v2 1/2] Make SPI_prepare argtypes argument const

This changes the argtypes argument of SPI_prepare(),
SPI_prepare_cursor(), SPI_cursor_open_with_args(), and
SPI_execute_with_args() from Oid *argtypes to const Oid *argtypes.
The underlying functions were already receptive to that, so this
doesn't require any significant changes beyond the function signatures
and some internal variables.

Commit 28972b6fc3dc recently introduced a case where a const had to be
cast away before calling these functions.  This is fixed here.
---
 contrib/postgres_fdw/postgres_fdw.c |  6 +++---
 doc/src/sgml/spi.sgml               |  8 ++++----
 src/backend/executor/spi.c          | 26 ++++++++++++++++----------
 src/backend/utils/adt/ri_triggers.c |  4 ++--
 src/backend/utils/cache/plancache.c |  2 +-
 src/include/executor/spi.h          |  8 ++++----
 src/include/executor/spi_priv.h     |  2 +-
 src/include/utils/plancache.h       |  2 +-
 8 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 0a589f8db74..322212552ee 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -6164,12 +6164,12 @@ import_fetched_statistics(const char *schemaname,
 		Assert(PQntuples(remstats->att) >= 1);
 
 		attimport_plan = SPI_prepare(attimport_sql, ATTIMPORT_SQL_NUM_FIELDS,
-									 (Oid *) attimport_argtypes);
+									 attimport_argtypes);
 		if (attimport_plan == NULL)
 			elog(ERROR, "failed to prepare attimport_sql query");
 
 		attclear_plan = SPI_prepare(attclear_sql, ATTCLEAR_SQL_NUM_FIELDS,
-									(Oid *) attclear_argtypes);
+									attclear_argtypes);
 		if (attclear_plan == NULL)
 			elog(ERROR, "failed to prepare attclear_sql query");
 
@@ -6247,7 +6247,7 @@ import_fetched_statistics(const char *schemaname,
 
 	spirc = SPI_execute_with_args(relimport_sql,
 								  RELIMPORT_SQL_NUM_FIELDS,
-								  (Oid *) relimport_argtypes,
+								  relimport_argtypes,
 								  values, nulls, false, 1);
 	if (spirc != SPI_OK_SELECT)
 		elog(ERROR, "failed to execute relimport_sql query for foreign table \"%s.%s\"",
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index e30d0962ae7..043c6f00039 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -845,7 +845,7 @@ <title>Return Value</title>
  <refsynopsisdiv>
 <synopsis>
 int SPI_execute_with_args(const char *<parameter>command</parameter>,
-                          int <parameter>nargs</parameter>, Oid *<parameter>argtypes</parameter>,
+                          int <parameter>nargs</parameter>, const Oid *<parameter>argtypes</parameter>,
                           const Datum *<parameter>values</parameter>, const char *<parameter>nulls</parameter>,
                           bool <parameter>read_only</parameter>, long <parameter>count</parameter>)
 </synopsis>
@@ -997,7 +997,7 @@ <title>Return Value</title>
 
  <refsynopsisdiv>
 <synopsis>
-SPIPlanPtr SPI_prepare(const char * <parameter>command</parameter>, int <parameter>nargs</parameter>, Oid * <parameter>argtypes</parameter>)
+SPIPlanPtr SPI_prepare(const char * <parameter>command</parameter>, int <parameter>nargs</parameter>, const Oid * <parameter>argtypes</parameter>)
 </synopsis>
  </refsynopsisdiv>
 
@@ -1160,7 +1160,7 @@ <title>Notes</title>
  <refsynopsisdiv>
 <synopsis>
 SPIPlanPtr SPI_prepare_cursor(const char * <parameter>command</parameter>, int <parameter>nargs</parameter>,
-                              Oid * <parameter>argtypes</parameter>, int <parameter>cursorOptions</parameter>)
+                              const Oid * <parameter>argtypes</parameter>, int <parameter>cursorOptions</parameter>)
 </synopsis>
  </refsynopsisdiv>
 
@@ -2316,7 +2316,7 @@ <title>Return Value</title>
 <synopsis>
 Portal SPI_cursor_open_with_args(const char *<parameter>name</parameter>,
                                  const char *<parameter>command</parameter>,
-                                 int <parameter>nargs</parameter>, Oid *<parameter>argtypes</parameter>,
+                                 int <parameter>nargs</parameter>, const Oid *<parameter>argtypes</parameter>,
                                  const Datum *<parameter>values</parameter>, const char *<parameter>nulls</parameter>,
                                  bool <parameter>read_only</parameter>, int <parameter>cursorOptions</parameter>)
 </synopsis>
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 52f3b11301c..d884c962f14 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -68,7 +68,7 @@ static int	_SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options,
 							  Snapshot snapshot, Snapshot crosscheck_snapshot,
 							  bool fire_triggers);
 
-static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes,
+static ParamListInfo _SPI_convert_params(int nargs, const Oid *argtypes,
 										 const Datum *Values, const char *Nulls);
 
 static int	_SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount);
@@ -811,7 +811,7 @@ SPI_execute_snapshot(SPIPlanPtr plan,
  */
 int
 SPI_execute_with_args(const char *src,
-					  int nargs, Oid *argtypes,
+					  int nargs, const Oid *argtypes,
 					  const Datum *Values, const char *Nulls,
 					  bool read_only, long tcount)
 {
@@ -858,13 +858,13 @@ SPI_execute_with_args(const char *src,
 }
 
 SPIPlanPtr
-SPI_prepare(const char *src, int nargs, Oid *argtypes)
+SPI_prepare(const char *src, int nargs, const Oid *argtypes)
 {
 	return SPI_prepare_cursor(src, nargs, argtypes, 0);
 }
 
 SPIPlanPtr
-SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
+SPI_prepare_cursor(const char *src, int nargs, const Oid *argtypes,
 				   int cursorOptions)
 {
 	_SPI_plan	plan;
@@ -1472,7 +1472,7 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
 Portal
 SPI_cursor_open_with_args(const char *name,
 						  const char *src,
-						  int nargs, Oid *argtypes,
+						  int nargs, const Oid *argtypes,
 						  Datum *Values, const char *Nulls,
 						  bool read_only, int cursorOptions)
 {
@@ -2846,7 +2846,7 @@ _SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options,
  * Convert arrays of query parameters to form wanted by planner and executor
  */
 static ParamListInfo
-_SPI_convert_params(int nargs, Oid *argtypes,
+_SPI_convert_params(int nargs, const Oid *argtypes,
 					const Datum *Values, const char *Nulls)
 {
 	ParamListInfo paramLI;
@@ -3170,8 +3170,11 @@ _SPI_make_plan_non_temp(SPIPlanPtr plan)
 	newplan->nargs = plan->nargs;
 	if (plan->nargs > 0)
 	{
-		newplan->argtypes = palloc_array(Oid, plan->nargs);
-		memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
+		Oid		   *newplan_argtypes;
+
+		newplan_argtypes = palloc_array(Oid, plan->nargs);
+		memcpy(newplan_argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
+		newplan->argtypes = newplan_argtypes;
 	}
 	else
 		newplan->argtypes = NULL;
@@ -3235,8 +3238,11 @@ _SPI_save_plan(SPIPlanPtr plan)
 	newplan->nargs = plan->nargs;
 	if (plan->nargs > 0)
 	{
-		newplan->argtypes = palloc_array(Oid, plan->nargs);
-		memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
+		Oid		   *newplan_argtypes;
+
+		newplan_argtypes = palloc_array(Oid, plan->nargs);
+		memcpy(newplan_argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
+		newplan->argtypes = newplan_argtypes;
 	}
 	else
 		newplan->argtypes = NULL;
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index dc89c686394..4741b559c61 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -301,7 +301,7 @@ static RI_ConstraintInfo *ri_FetchConstraintInfo(Trigger *trigger,
 												 Relation trig_rel, bool rel_is_pk);
 static RI_ConstraintInfo *ri_LoadConstraintInfo(Oid constraintOid);
 static Oid	get_ri_constraint_root(Oid constrOid);
-static SPIPlanPtr ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes,
+static SPIPlanPtr ri_PlanCheck(const char *querystr, int nargs, const Oid *argtypes,
 							   RI_QueryKey *qkey, Relation fk_rel, Relation pk_rel);
 static bool ri_PerformCheck(const RI_ConstraintInfo *riinfo,
 							RI_QueryKey *qkey, SPIPlanPtr qplan,
@@ -2582,7 +2582,7 @@ InvalidateConstraintCacheCallBack(Datum arg, SysCacheIdentifier cacheid,
  * Prepare execution plan for a query to enforce an RI restriction
  */
 static SPIPlanPtr
-ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes,
+ri_PlanCheck(const char *querystr, int nargs, const Oid *argtypes,
 			 RI_QueryKey *qkey, Relation fk_rel, Relation pk_rel)
 {
 	SPIPlanPtr	qplan;
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 698e7c1aa22..26f1bd64515 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -393,7 +393,7 @@ void
 CompleteCachedPlan(CachedPlanSource *plansource,
 				   List *querytree_list,
 				   MemoryContext querytree_context,
-				   Oid *param_types,
+				   const Oid *param_types,
 				   int num_params,
 				   ParserSetupHook parserSetup,
 				   void *parserSetupArg,
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
index f4985cb715d..e809ba18098 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -127,11 +127,11 @@ extern int	SPI_execute_snapshot(SPIPlanPtr plan,
 								 Snapshot crosscheck_snapshot,
 								 bool read_only, bool fire_triggers, long tcount);
 extern int	SPI_execute_with_args(const char *src,
-								  int nargs, Oid *argtypes,
+								  int nargs, const Oid *argtypes,
 								  const Datum *Values, const char *Nulls,
 								  bool read_only, long tcount);
-extern SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes);
-extern SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
+extern SPIPlanPtr SPI_prepare(const char *src, int nargs, const Oid *argtypes);
+extern SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, const Oid *argtypes,
 									 int cursorOptions);
 extern SPIPlanPtr SPI_prepare_extended(const char *src,
 									   const SPIPrepareOptions *options);
@@ -175,7 +175,7 @@ extern Portal SPI_cursor_open(const char *name, SPIPlanPtr plan,
 							  const Datum *Values, const char *Nulls, bool read_only);
 extern Portal SPI_cursor_open_with_args(const char *name,
 										const char *src,
-										int nargs, Oid *argtypes,
+										int nargs, const Oid *argtypes,
 										Datum *Values, const char *Nulls,
 										bool read_only, int cursorOptions);
 extern Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan,
diff --git a/src/include/executor/spi_priv.h b/src/include/executor/spi_priv.h
index 240383b97b9..9fb82ad0984 100644
--- a/src/include/executor/spi_priv.h
+++ b/src/include/executor/spi_priv.h
@@ -97,7 +97,7 @@ typedef struct _SPI_plan
 	RawParseMode parse_mode;	/* raw_parser() mode */
 	int			cursor_options; /* Cursor options used for planning */
 	int			nargs;			/* number of plan arguments */
-	Oid		   *argtypes;		/* Argument types (NULL if nargs is 0) */
+	const Oid  *argtypes;		/* Argument types (NULL if nargs is 0) */
 	ParserSetupHook parserSetup;	/* alternative parameter spec method */
 	void	   *parserSetupArg;
 } _SPI_plan;
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
index 7a4a85c8038..a0355e79c28 100644
--- a/src/include/utils/plancache.h
+++ b/src/include/utils/plancache.h
@@ -214,7 +214,7 @@ extern CachedPlanSource *CreateOneShotCachedPlan(RawStmt *raw_parse_tree,
 extern void CompleteCachedPlan(CachedPlanSource *plansource,
 							   List *querytree_list,
 							   MemoryContext querytree_context,
-							   Oid *param_types,
+							   const Oid *param_types,
 							   int num_params,
 							   ParserSetupHook parserSetup,
 							   void *parserSetupArg,
-- 
2.54.0