From 23e10843db588928e18bd58018c2e70f4548f177 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 18 Aug 2003 19:16:02 +0000
Subject: [PATCH] When compiling a plpgsql trigger function, include the OID of
 the table the trigger is attached to in the hashkey.  This ensures that we
 will create separate compiled trees for each table the trigger is used with,
 avoiding possible datatype-mismatch problems if the tables have different
 rowtypes.  This is essentially the same bug recently identified in plpython
 --- though plpgsql doesn't seem as prone to crash when the rowtype changes
 underneath it.  But failing robustly is no substitute for just working.

---
 src/pl/plpgsql/src/pl_comp.c | 47 +++++++++++++++++++++---------------
 src/pl/plpgsql/src/plpgsql.h | 10 +++++++-
 2 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index e4d7b3c062c..84685c21034 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.66 2003/08/08 19:19:32 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.67 2003/08/18 19:16:02 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -100,16 +100,16 @@ typedef struct plpgsql_hashent
  */
 static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
 		   HeapTuple procTup,
-		   PLpgSQL_func_hashkey * hashkey);
+		   PLpgSQL_func_hashkey *hashkey);
 static void plpgsql_compile_error_callback(void *arg);
 static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
-static void compute_function_hashkey(FmgrInfo *flinfo,
+static void compute_function_hashkey(FunctionCallInfo fcinfo,
 						 Form_pg_proc procStruct,
-						 PLpgSQL_func_hashkey * hashkey);
-static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key);
-static void plpgsql_HashTableInsert(PLpgSQL_function * function,
-						PLpgSQL_func_hashkey * func_key);
-static void plpgsql_HashTableDelete(PLpgSQL_function * function);
+						 PLpgSQL_func_hashkey *hashkey);
+static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key);
+static void plpgsql_HashTableInsert(PLpgSQL_function *function,
+						PLpgSQL_func_hashkey *func_key);
+static void plpgsql_HashTableDelete(PLpgSQL_function *function);
 
 /*
  * This routine is a crock, and so is everyplace that calls it.  The problem
@@ -169,7 +169,7 @@ plpgsql_compile(FunctionCallInfo fcinfo)
 			plpgsql_HashTableInit();
 
 		/* Compute hashkey using function signature and actual arg types */
-		compute_function_hashkey(fcinfo->flinfo, procStruct, &hashkey);
+		compute_function_hashkey(fcinfo, procStruct, &hashkey);
 		hashkey_valid = true;
 
 		/* And do the lookup */
@@ -203,7 +203,7 @@ plpgsql_compile(FunctionCallInfo fcinfo)
 		 * the completed function.
 		 */
 		if (!hashkey_valid)
-			compute_function_hashkey(fcinfo->flinfo, procStruct, &hashkey);
+			compute_function_hashkey(fcinfo, procStruct, &hashkey);
 
 		/*
 		 * Do the hard part.
@@ -230,7 +230,7 @@ plpgsql_compile(FunctionCallInfo fcinfo)
 static PLpgSQL_function *
 do_compile(FunctionCallInfo fcinfo,
 		   HeapTuple procTup,
-		   PLpgSQL_func_hashkey * hashkey)
+		   PLpgSQL_func_hashkey *hashkey)
 {
 	Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
 	int			functype = CALLED_AS_TRIGGER(fcinfo) ? T_TRIGGER : T_FUNCTION;
@@ -1711,16 +1711,25 @@ plpgsql_yyerror(const char *s)
  * The hashkey is returned into the caller-provided storage at *hashkey.
  */
 static void
-compute_function_hashkey(FmgrInfo *flinfo,
+compute_function_hashkey(FunctionCallInfo fcinfo,
 						 Form_pg_proc procStruct,
-						 PLpgSQL_func_hashkey * hashkey)
+						 PLpgSQL_func_hashkey *hashkey)
 {
 	int			i;
 
 	/* Make sure any unused bytes of the struct are zero */
 	MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
 
-	hashkey->funcOid = flinfo->fn_oid;
+	/* get function OID */
+	hashkey->funcOid = fcinfo->flinfo->fn_oid;
+
+	/* if trigger, get relation OID */
+	if (CALLED_AS_TRIGGER(fcinfo))
+	{
+		TriggerData *trigdata = (TriggerData *) fcinfo->context;
+
+		hashkey->trigrelOid = RelationGetRelid(trigdata->tg_relation);
+	}
 
 	/* get the argument types */
 	for (i = 0; i < procStruct->pronargs; i++)
@@ -1737,7 +1746,7 @@ compute_function_hashkey(FmgrInfo *flinfo,
 		if (argtypeid == ANYARRAYOID || argtypeid == ANYELEMENTOID ||
 			argtypeid == ANYOID)
 		{
-			argtypeid = get_fn_expr_argtype(flinfo, i);
+			argtypeid = get_fn_expr_argtype(fcinfo->flinfo, i);
 			if (!OidIsValid(argtypeid))
 				ereport(ERROR,
 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -1767,7 +1776,7 @@ plpgsql_HashTableInit(void)
 }
 
 static PLpgSQL_function *
-plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key)
+plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
 {
 	plpgsql_HashEnt *hentry;
 
@@ -1782,8 +1791,8 @@ plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key)
 }
 
 static void
-plpgsql_HashTableInsert(PLpgSQL_function * function,
-						PLpgSQL_func_hashkey * func_key)
+plpgsql_HashTableInsert(PLpgSQL_function *function,
+						PLpgSQL_func_hashkey *func_key)
 {
 	plpgsql_HashEnt *hentry;
 	bool		found;
@@ -1805,7 +1814,7 @@ plpgsql_HashTableInsert(PLpgSQL_function * function,
 }
 
 static void
-plpgsql_HashTableDelete(PLpgSQL_function * function)
+plpgsql_HashTableDelete(PLpgSQL_function *function)
 {
 	plpgsql_HashEnt *hentry;
 
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 1cb5ea2de90..3ec33091e35 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.39 2003/08/04 00:43:33 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.40 2003/08/18 19:16:02 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -491,6 +491,14 @@ typedef struct PLpgSQL_func_hashkey
 {								/* Hash lookup key for functions */
 	Oid			funcOid;
 
+	/*
+	 * For a trigger function, the OID of the relation triggered on is part
+	 * of the hashkey --- we want to compile the trigger separately for each
+	 * relation it is used with, in case the rowtype is different.  Zero if
+	 * not called as a trigger.
+	 */
+	Oid			trigrelOid;
+
 	/*
 	 * We include actual argument types in the hash key to support
 	 * polymorphic PLpgSQL functions.  Be careful that extra positions are
-- 
GitLab