aboutsummaryrefslogtreecommitdiff
path: root/src/pl/plpython/plpython.c
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2011-02-19 16:52:24 +0200
committerPeter Eisentraut <peter_e@gmx.net>2011-02-19 16:56:02 +0200
commitb05186f8a403c7dcd1bd974948273f8c00edb127 (patch)
treed1c3c0fd1aa8f09fc55225d2f3508aec8bfc3b35 /src/pl/plpython/plpython.c
parent964b46d00ec2222c1273bec3ead369f3e167d482 (diff)
downloadpostgresql-b05186f8a403c7dcd1bd974948273f8c00edb127.tar.gz
postgresql-b05186f8a403c7dcd1bd974948273f8c00edb127.zip
Invalidate PL/Python functions with composite type argument when the
type changes. The invalidation will cause the type information to be refetched, and everything will work. Jan UrbaƄski, reviewed by Alex Hunsaker
Diffstat (limited to 'src/pl/plpython/plpython.c')
-rw-r--r--src/pl/plpython/plpython.c78
1 files changed, 76 insertions, 2 deletions
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 82baf940e31..4e54d3e8b0e 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -101,6 +101,7 @@ typedef int Py_ssize_t;
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
#include "tcop/tcopprot.h"
+#include "access/transam.h"
#include "access/xact.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
@@ -195,6 +196,10 @@ typedef struct PLyTypeInfo
* datatype; 1 = rowtype; 2 = rowtype, but I/O functions not set up yet
*/
int is_rowtype;
+ /* used to check if the type has been modified */
+ Oid typ_relid;
+ TransactionId typrel_xmin;
+ ItemPointerData typrel_tid;
} PLyTypeInfo;
@@ -1335,11 +1340,50 @@ PLy_function_delete_args(PLyProcedure *proc)
static bool
PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup)
{
+ int i;
+ bool valid;
+
Assert(proc != NULL);
/* If the pg_proc tuple has changed, it's not valid */
- return (proc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
- ItemPointerEquals(&proc->fn_tid, &procTup->t_self));
+ if (!(proc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
+ ItemPointerEquals(&proc->fn_tid, &procTup->t_self)))
+ return false;
+
+ valid = true;
+ /* If there are composite input arguments, they might have changed */
+ for (i = 0; i < proc->nargs; i++)
+ {
+ Oid relid;
+ HeapTuple relTup;
+
+ /* Short-circuit on first changed argument */
+ if (!valid)
+ break;
+
+ /* Only check input arguments that are composite */
+ if (proc->args[i].is_rowtype != 1)
+ continue;
+
+ Assert(OidIsValid(proc->args[i].typ_relid));
+ Assert(TransactionIdIsValid(proc->args[i].typrel_xmin));
+ Assert(ItemPointerIsValid(&proc->args[i].typrel_tid));
+
+ /* Get the pg_class tuple for the argument type */
+ relid = proc->args[i].typ_relid;
+ relTup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(relTup))
+ elog(ERROR, "cache lookup failed for relation %u", relid);
+
+ /* If it has changed, the function is not valid */
+ if (!(proc->args[i].typrel_xmin == HeapTupleHeaderGetXmin(relTup->t_data) &&
+ ItemPointerEquals(&proc->args[i].typrel_tid, &relTup->t_self)))
+ valid = false;
+
+ ReleaseSysCache(relTup);
+ }
+
+ return valid;
}
@@ -1747,6 +1791,33 @@ PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
arg->in.r.atts = PLy_malloc0(desc->natts * sizeof(PLyDatumToOb));
}
+ /* Can this be an unnamed tuple? If not, then an Assert would be enough */
+ if (desc->tdtypmod != -1)
+ elog(ERROR, "received unnamed record type as input");
+
+ Assert(OidIsValid(desc->tdtypeid));
+
+ /*
+ * RECORDOID means we got called to create input functions for a tuple
+ * fetched by plpy.execute or for an anonymous record type
+ */
+ if (desc->tdtypeid != RECORDOID && !TransactionIdIsValid(arg->typrel_xmin))
+ {
+ HeapTuple relTup;
+
+ /* Get the pg_class tuple corresponding to the type of the input */
+ arg->typ_relid = typeidTypeRelid(desc->tdtypeid);
+ relTup = SearchSysCache1(RELOID, ObjectIdGetDatum(arg->typ_relid));
+ if (!HeapTupleIsValid(relTup))
+ elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);
+
+ /* Extract the XMIN value to later use it in PLy_procedure_valid */
+ arg->typrel_xmin = HeapTupleHeaderGetXmin(relTup->t_data);
+ arg->typrel_tid = relTup->t_self;
+
+ ReleaseSysCache(relTup);
+ }
+
for (i = 0; i < desc->natts; i++)
{
HeapTuple typeTup;
@@ -1951,6 +2022,9 @@ PLy_typeinfo_init(PLyTypeInfo *arg)
arg->in.r.natts = arg->out.r.natts = 0;
arg->in.r.atts = NULL;
arg->out.r.atts = NULL;
+ arg->typ_relid = InvalidOid;
+ arg->typrel_xmin = InvalidTransactionId;
+ ItemPointerSetInvalid(&arg->typrel_tid);
}
static void