Commit 23e10843 authored by Tom Lane's avatar Tom Lane

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.
parent 14149035
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * 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. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -100,16 +100,16 @@ typedef struct plpgsql_hashent ...@@ -100,16 +100,16 @@ typedef struct plpgsql_hashent
*/ */
static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo, static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
HeapTuple procTup, HeapTuple procTup,
PLpgSQL_func_hashkey * hashkey); PLpgSQL_func_hashkey *hashkey);
static void plpgsql_compile_error_callback(void *arg); static void plpgsql_compile_error_callback(void *arg);
static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod); 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, Form_pg_proc procStruct,
PLpgSQL_func_hashkey * hashkey); PLpgSQL_func_hashkey *hashkey);
static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key); static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key);
static void plpgsql_HashTableInsert(PLpgSQL_function * function, static void plpgsql_HashTableInsert(PLpgSQL_function *function,
PLpgSQL_func_hashkey * func_key); PLpgSQL_func_hashkey *func_key);
static void plpgsql_HashTableDelete(PLpgSQL_function * function); static void plpgsql_HashTableDelete(PLpgSQL_function *function);
/* /*
* This routine is a crock, and so is everyplace that calls it. The problem * This routine is a crock, and so is everyplace that calls it. The problem
...@@ -169,7 +169,7 @@ plpgsql_compile(FunctionCallInfo fcinfo) ...@@ -169,7 +169,7 @@ plpgsql_compile(FunctionCallInfo fcinfo)
plpgsql_HashTableInit(); plpgsql_HashTableInit();
/* Compute hashkey using function signature and actual arg types */ /* 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; hashkey_valid = true;
/* And do the lookup */ /* And do the lookup */
...@@ -203,7 +203,7 @@ plpgsql_compile(FunctionCallInfo fcinfo) ...@@ -203,7 +203,7 @@ plpgsql_compile(FunctionCallInfo fcinfo)
* the completed function. * the completed function.
*/ */
if (!hashkey_valid) if (!hashkey_valid)
compute_function_hashkey(fcinfo->flinfo, procStruct, &hashkey); compute_function_hashkey(fcinfo, procStruct, &hashkey);
/* /*
* Do the hard part. * Do the hard part.
...@@ -230,7 +230,7 @@ plpgsql_compile(FunctionCallInfo fcinfo) ...@@ -230,7 +230,7 @@ plpgsql_compile(FunctionCallInfo fcinfo)
static PLpgSQL_function * static PLpgSQL_function *
do_compile(FunctionCallInfo fcinfo, do_compile(FunctionCallInfo fcinfo,
HeapTuple procTup, HeapTuple procTup,
PLpgSQL_func_hashkey * hashkey) PLpgSQL_func_hashkey *hashkey)
{ {
Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup); Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
int functype = CALLED_AS_TRIGGER(fcinfo) ? T_TRIGGER : T_FUNCTION; int functype = CALLED_AS_TRIGGER(fcinfo) ? T_TRIGGER : T_FUNCTION;
...@@ -1711,16 +1711,25 @@ plpgsql_yyerror(const char *s) ...@@ -1711,16 +1711,25 @@ plpgsql_yyerror(const char *s)
* The hashkey is returned into the caller-provided storage at *hashkey. * The hashkey is returned into the caller-provided storage at *hashkey.
*/ */
static void static void
compute_function_hashkey(FmgrInfo *flinfo, compute_function_hashkey(FunctionCallInfo fcinfo,
Form_pg_proc procStruct, Form_pg_proc procStruct,
PLpgSQL_func_hashkey * hashkey) PLpgSQL_func_hashkey *hashkey)
{ {
int i; int i;
/* Make sure any unused bytes of the struct are zero */ /* Make sure any unused bytes of the struct are zero */
MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey)); 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 */ /* get the argument types */
for (i = 0; i < procStruct->pronargs; i++) for (i = 0; i < procStruct->pronargs; i++)
...@@ -1737,7 +1746,7 @@ compute_function_hashkey(FmgrInfo *flinfo, ...@@ -1737,7 +1746,7 @@ compute_function_hashkey(FmgrInfo *flinfo,
if (argtypeid == ANYARRAYOID || argtypeid == ANYELEMENTOID || if (argtypeid == ANYARRAYOID || argtypeid == ANYELEMENTOID ||
argtypeid == ANYOID) argtypeid == ANYOID)
{ {
argtypeid = get_fn_expr_argtype(flinfo, i); argtypeid = get_fn_expr_argtype(fcinfo->flinfo, i);
if (!OidIsValid(argtypeid)) if (!OidIsValid(argtypeid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
...@@ -1767,7 +1776,7 @@ plpgsql_HashTableInit(void) ...@@ -1767,7 +1776,7 @@ plpgsql_HashTableInit(void)
} }
static PLpgSQL_function * static PLpgSQL_function *
plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key) plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
{ {
plpgsql_HashEnt *hentry; plpgsql_HashEnt *hentry;
...@@ -1782,8 +1791,8 @@ plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key) ...@@ -1782,8 +1791,8 @@ plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key)
} }
static void static void
plpgsql_HashTableInsert(PLpgSQL_function * function, plpgsql_HashTableInsert(PLpgSQL_function *function,
PLpgSQL_func_hashkey * func_key) PLpgSQL_func_hashkey *func_key)
{ {
plpgsql_HashEnt *hentry; plpgsql_HashEnt *hentry;
bool found; bool found;
...@@ -1805,7 +1814,7 @@ plpgsql_HashTableInsert(PLpgSQL_function * function, ...@@ -1805,7 +1814,7 @@ plpgsql_HashTableInsert(PLpgSQL_function * function,
} }
static void static void
plpgsql_HashTableDelete(PLpgSQL_function * function) plpgsql_HashTableDelete(PLpgSQL_function *function)
{ {
plpgsql_HashEnt *hentry; plpgsql_HashEnt *hentry;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * 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. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -491,6 +491,14 @@ typedef struct PLpgSQL_func_hashkey ...@@ -491,6 +491,14 @@ typedef struct PLpgSQL_func_hashkey
{ /* Hash lookup key for functions */ { /* Hash lookup key for functions */
Oid funcOid; 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 * We include actual argument types in the hash key to support
* polymorphic PLpgSQL functions. Be careful that extra positions are * polymorphic PLpgSQL functions. Be careful that extra positions are
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment