From ba3e4157a7d0c7e963a8b800a30b9789aea6dd96 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 26 Apr 2012 21:03:48 +0300 Subject: PL/Python: Accept strings in functions returning composite types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before 9.1, PL/Python functions returning composite types could return a string and it would be parsed using record_in. The 9.1 changes made PL/Python only expect dictionaries, tuples, or objects supporting getattr as output of composite functions, resulting in a regression and a confusing error message, as the strings were interpreted as sequences and the code for transforming lists to database tuples was used. Fix this by treating strings separately as before, before checking for the other types. The reason why it's important to support string to database tuple conversion is that trigger functions on tables with composite columns get the composite row passed in as a string (from record_out). Without supporting converting this back using record_in, this makes it impossible to implement pass-through behavior for these columns, as PL/Python no longer accepts strings for composite values. A better solution would be to fix the code that transforms composite inputs into Python objects to produce dictionaries that would then be correctly interpreted by the Python->PostgreSQL counterpart code. But that would be too invasive to backpatch to 9.1, and it is too late in the 9.2 cycle to attempt it. It should be revisited in the future, though. Reported as bug #6559 by Kirill Simonov. Jan UrbaƄski --- src/pl/plpython/plpy_exec.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'src/pl/plpython/plpy_exec.c') diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c index 280d3ed1ac..ad30fc0065 100644 --- a/src/pl/plpython/plpy_exec.c +++ b/src/pl/plpython/plpy_exec.c @@ -180,8 +180,7 @@ PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc) } else if (proc->result.is_rowtype >= 1) { - TupleDesc desc; - HeapTuple tuple = NULL; + TupleDesc desc; /* make sure it's not an unnamed record */ Assert((proc->result.out.d.typoid == RECORDOID && @@ -192,18 +191,8 @@ PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc) desc = lookup_rowtype_tupdesc(proc->result.out.d.typoid, proc->result.out.d.typmod); - tuple = PLyObject_ToTuple(&proc->result, desc, plrv); - - if (tuple != NULL) - { - fcinfo->isnull = false; - rv = HeapTupleGetDatum(tuple); - } - else - { - fcinfo->isnull = true; - rv = (Datum) NULL; - } + rv = PLyObject_ToCompositeDatum(&proc->result, desc, plrv); + fcinfo->isnull = (rv == (Datum) NULL); } else { -- cgit v1.2.1