From 4902acc0740fb795dc282d73bb2ef9775fb26e1f Mon Sep 17 00:00:00 2001
From: Euler Taveira <euler@eulerto.com>
Date: Tue, 1 Jul 2025 19:43:41 -0300
Subject: [PATCH v1 1/2] PL/Python: refactor for trigger support

Change is_trigger type from boolean to enum. That's a preparation to add
event trigger support.
---
 src/pl/plpython/plpy_exec.c      |  2 +-
 src/pl/plpython/plpy_main.c      | 25 +++++++++++++++++++------
 src/pl/plpython/plpy_procedure.c | 13 ++++++++-----
 src/pl/plpython/plpy_procedure.h | 13 +++++++++++--
 src/tools/pgindent/typedefs.list |  1 +
 5 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c
index 28fbd443b98..22835174b69 100644
--- a/src/pl/plpython/plpy_exec.c
+++ b/src/pl/plpython/plpy_exec.c
@@ -509,7 +509,7 @@ PLy_function_save_args(PLyProcedure *proc)
 	Py_XINCREF(result->args);
 
 	/* If it's a trigger, also save "TD" */
-	if (proc->is_trigger)
+	if (proc->is_trigger == PLPY_TRIGGER)
 	{
 		result->td = PyDict_GetItemString(proc->globals, "TD");
 		Py_XINCREF(result->td);
diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c
index f36eadbadc6..66e11aba754 100644
--- a/src/pl/plpython/plpy_main.c
+++ b/src/pl/plpython/plpy_main.c
@@ -19,6 +19,7 @@
 #include "plpy_procedure.h"
 #include "plpy_subxactobject.h"
 #include "plpy_util.h"
+#include "utils/builtins.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
@@ -38,7 +39,7 @@ PG_FUNCTION_INFO_V1(plpython3_call_handler);
 PG_FUNCTION_INFO_V1(plpython3_inline_handler);
 
 
-static bool PLy_procedure_is_trigger(Form_pg_proc procStruct);
+static PLyTrigType PLy_procedure_is_trigger(Form_pg_proc procStruct);
 static void plpython_error_callback(void *arg);
 static void plpython_inline_error_callback(void *arg);
 static void PLy_init_interp(void);
@@ -163,7 +164,7 @@ plpython3_validator(PG_FUNCTION_ARGS)
 	Oid			funcoid = PG_GETARG_OID(0);
 	HeapTuple	tuple;
 	Form_pg_proc procStruct;
-	bool		is_trigger;
+	PLyTrigType is_trigger;
 
 	if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
 		PG_RETURN_VOID();
@@ -235,14 +236,14 @@ plpython3_call_handler(PG_FUNCTION_ARGS)
 			Relation	tgrel = ((TriggerData *) fcinfo->context)->tg_relation;
 			HeapTuple	trv;
 
-			proc = PLy_procedure_get(funcoid, RelationGetRelid(tgrel), true);
+			proc = PLy_procedure_get(funcoid, RelationGetRelid(tgrel), PLPY_TRIGGER);
 			exec_ctx->curr_proc = proc;
 			trv = PLy_exec_trigger(fcinfo, proc);
 			retval = PointerGetDatum(trv);
 		}
 		else
 		{
-			proc = PLy_procedure_get(funcoid, InvalidOid, false);
+			proc = PLy_procedure_get(funcoid, InvalidOid, PLPY_NOT_TRIGGER);
 			exec_ctx->curr_proc = proc;
 			retval = PLy_exec_function(fcinfo, proc);
 		}
@@ -336,10 +337,22 @@ plpython3_inline_handler(PG_FUNCTION_ARGS)
 	PG_RETURN_VOID();
 }
 
-static bool
+static PLyTrigType
 PLy_procedure_is_trigger(Form_pg_proc procStruct)
 {
-	return (procStruct->prorettype == TRIGGEROID);
+	PLyTrigType ret;
+
+	switch (procStruct->prorettype)
+	{
+		case TRIGGEROID:
+			ret = PLPY_TRIGGER;
+			break;
+		default:
+			ret = PLPY_NOT_TRIGGER;
+			break;
+	}
+
+	return ret;
 }
 
 static void
diff --git a/src/pl/plpython/plpy_procedure.c b/src/pl/plpython/plpy_procedure.c
index c176d24e801..15b7c100144 100644
--- a/src/pl/plpython/plpy_procedure.c
+++ b/src/pl/plpython/plpy_procedure.c
@@ -21,7 +21,7 @@
 
 static HTAB *PLy_procedure_cache = NULL;
 
-static PLyProcedure *PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger);
+static PLyProcedure *PLy_procedure_create(HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger);
 static bool PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup);
 static char *PLy_procedure_munge_source(const char *name, const char *src);
 
@@ -63,15 +63,18 @@ PLy_procedure_name(PLyProcedure *proc)
  * be used with, so no sensible fn_rel can be passed.
  */
 PLyProcedure *
-PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger)
+PLy_procedure_get(Oid fn_oid, Oid fn_rel, PLyTrigType is_trigger)
 {
-	bool		use_cache = !(is_trigger && fn_rel == InvalidOid);
+	bool		use_cache = true;
 	HeapTuple	procTup;
 	PLyProcedureKey key;
 	PLyProcedureEntry *volatile entry = NULL;
 	PLyProcedure *volatile proc = NULL;
 	bool		found = false;
 
+	if (is_trigger == PLPY_TRIGGER && fn_rel == InvalidOid)
+		use_cache = false;
+
 	procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fn_oid));
 	if (!HeapTupleIsValid(procTup))
 		elog(ERROR, "cache lookup failed for function %u", fn_oid);
@@ -127,7 +130,7 @@ PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger)
  * Create a new PLyProcedure structure
  */
 static PLyProcedure *
-PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
+PLy_procedure_create(HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger)
 {
 	char		procName[NAMEDATALEN + 256];
 	Form_pg_proc procStruct;
@@ -200,7 +203,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
 		 * get information required for output conversion of the return value,
 		 * but only if this isn't a trigger.
 		 */
-		if (!is_trigger)
+		if (is_trigger == PLPY_NOT_TRIGGER)
 		{
 			Oid			rettype = procStruct->prorettype;
 			HeapTuple	rvTypeTup;
diff --git a/src/pl/plpython/plpy_procedure.h b/src/pl/plpython/plpy_procedure.h
index 5db854fc8bd..601b91d5d94 100644
--- a/src/pl/plpython/plpy_procedure.h
+++ b/src/pl/plpython/plpy_procedure.h
@@ -11,6 +11,15 @@
 extern void init_procedure_caches(void);
 
 
+/*
+ * Trigger type
+ */
+typedef enum PLyTrigType
+{
+	PLPY_TRIGGER,
+	PLPY_NOT_TRIGGER,
+} PLyTrigType;
+
 /* saved arguments for outer recursion level or set-returning function */
 typedef struct PLySavedArgs
 {
@@ -33,7 +42,7 @@ typedef struct PLyProcedure
 	bool		fn_readonly;
 	bool		is_setof;		/* true, if function returns result set */
 	bool		is_procedure;
-	bool		is_trigger;		/* called as trigger? */
+	PLyTrigType is_trigger;		/* called as trigger? */
 	PLyObToDatum result;		/* Function result output conversion info */
 	PLyDatumToOb result_in;		/* For converting input tuples in a trigger */
 	char	   *src;			/* textual procedure code, after mangling */
@@ -65,7 +74,7 @@ typedef struct PLyProcedureEntry
 
 /* PLyProcedure manipulation */
 extern char *PLy_procedure_name(PLyProcedure *proc);
-extern PLyProcedure *PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger);
+extern PLyProcedure *PLy_procedure_get(Oid fn_oid, Oid fn_rel, PLyTrigType is_trigger);
 extern void PLy_procedure_compile(PLyProcedure *proc, const char *src);
 extern void PLy_procedure_delete(PLyProcedure *proc);
 
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index ff050e93a50..5da48dd4ac7 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1989,6 +1989,7 @@ PLyScalarToOb
 PLySubtransactionData
 PLySubtransactionObject
 PLyTransformToOb
+PLyTrigType
 PLyTupleToOb
 PLyUnicode_FromStringAndSize_t
 PLy_elog_impl_t
-- 
2.39.5

