]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix plpython so that it again honors typmod while assigning to tuple fields.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 12 Oct 2010 02:16:40 +0000 (22:16 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 12 Oct 2010 02:16:40 +0000 (22:16 -0400)
This was broken in 9.0 while improving plpython's conversion behavior for
bytea and boolean.  Per bug report from maizi.

src/pl/plpython/expected/plpython_trigger.out
src/pl/plpython/plpython.c
src/pl/plpython/sql/plpython_trigger.sql

index 275d0f7439998552cfe5bbb87d68d86c4dbdb982..a78e96e4a16ba9d0a416f282ba1d870a5ca6f82d 100644 (file)
@@ -523,3 +523,29 @@ SELECT * FROM trigger_test;
  0 | 
 (1 row)
 
+--
+-- Test that triggers honor typmod when assigning to tuple fields,
+-- as per an early 9.0 bug report
+--
+SET DateStyle = 'ISO';
+CREATE FUNCTION set_modif_time() RETURNS trigger AS $$
+    TD['new']['modif_time'] = '2010-10-13 21:57:28.930486'
+    return 'MODIFY'
+$$ LANGUAGE plpythonu;
+CREATE TABLE pb (a TEXT, modif_time TIMESTAMP(0) WITHOUT TIME ZONE);
+CREATE TRIGGER set_modif_time BEFORE UPDATE ON pb
+  FOR EACH ROW EXECUTE PROCEDURE set_modif_time();
+INSERT INTO pb VALUES ('a', '2010-10-09 21:57:33.930486');
+SELECT * FROM pb;
+ a |     modif_time      
+---+---------------------
+ a | 2010-10-09 21:57:34
+(1 row)
+
+UPDATE pb SET a = 'b';
+SELECT * FROM pb;
+ a |     modif_time      
+---+---------------------
+ b | 2010-10-13 21:57:29
+(1 row)
+
index c468cf00d07fdf4a10b0e3177a77226d8066db5f..f3352b3bc6fe21d1c0ebfbb4c9fa6ea26ec9ff90 100644 (file)
@@ -153,10 +153,8 @@ typedef union PLyTypeInput
  */
 
 struct PLyObToDatum;
-struct PLyTypeInfo;
-typedef Datum (*PLyObToDatumFunc) (struct PLyTypeInfo *,
-                                                                                          struct PLyObToDatum *,
-                                                                                          PyObject *);
+typedef Datum (*PLyObToDatumFunc) (struct PLyObToDatum *, int32 typmod,
+                                                                  PyObject *);
 
 typedef struct PLyObToDatum
 {
@@ -346,14 +344,10 @@ static PyObject *PLyList_FromArray(PLyDatumToOb *arg, Datum d);
 
 static PyObject *PLyDict_FromTuple(PLyTypeInfo *, HeapTuple, TupleDesc);
 
-static Datum PLyObject_ToBool(PLyTypeInfo *, PLyObToDatum *,
-                                PyObject *);
-static Datum PLyObject_ToBytea(PLyTypeInfo *, PLyObToDatum *,
-                                 PyObject *);
-static Datum PLyObject_ToDatum(PLyTypeInfo *, PLyObToDatum *,
-                                 PyObject *);
-static Datum PLySequence_ToArray(PLyTypeInfo *, PLyObToDatum *,
-                                       PyObject *);
+static Datum PLyObject_ToBool(PLyObToDatum *, int32, PyObject *);
+static Datum PLyObject_ToBytea(PLyObToDatum *, int32, PyObject *);
+static Datum PLyObject_ToDatum(PLyObToDatum *, int32, PyObject *);
+static Datum PLySequence_ToArray(PLyObToDatum *, int32, PyObject *);
 
 static HeapTuple PLyMapping_ToTuple(PLyTypeInfo *, PyObject *);
 static HeapTuple PLySequence_ToTuple(PLyTypeInfo *, PyObject *);
@@ -421,7 +415,8 @@ static void
 plpython_error_callback(void *arg)
 {
        if (PLy_curr_procedure)
-               errcontext("PL/Python function \"%s\"", PLy_procedure_name(PLy_curr_procedure));
+               errcontext("PL/Python function \"%s\"",
+                                  PLy_procedure_name(PLy_curr_procedure));
 }
 
 static void
@@ -743,7 +738,9 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
                        {
                                PLyObToDatum *att = &proc->result.out.r.atts[atti];
 
-                               modvalues[i] = (att->func) (&proc->result, att, plval);
+                               modvalues[i] = (att->func) (att,
+                                                                                       tupdesc->attrs[atti]->atttypmod,
+                                                                                       plval);
                                modnulls[i] = ' ';
                        }
                        else
@@ -1132,9 +1129,7 @@ PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *proc)
                else
                {
                        fcinfo->isnull = false;
-                       rv = (proc->result.out.d.func) (&proc->result,
-                                                                                       &proc->result.out.d,
-                                                                                       plrv);
+                       rv = (proc->result.out.d.func) (&proc->result.out.d, -1, plrv);
                }
        }
        PG_CATCH();
@@ -2099,9 +2094,7 @@ PLyDict_FromTuple(PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc)
  * type can parse.
  */
 static Datum
-PLyObject_ToBool(PLyTypeInfo *info,
-                                PLyObToDatum *arg,
-                                PyObject *plrv)
+PLyObject_ToBool(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
 {
        Datum           rv;
 
@@ -2120,9 +2113,7 @@ PLyObject_ToBool(PLyTypeInfo *info,
  * with embedded nulls.  And it's faster this way.
  */
 static Datum
-PLyObject_ToBytea(PLyTypeInfo *info,
-                                 PLyObToDatum *arg,
-                                 PyObject *plrv)
+PLyObject_ToBytea(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
 {
        PyObject   *volatile plrv_so = NULL;
        Datum           rv;
@@ -2164,9 +2155,7 @@ PLyObject_ToBytea(PLyTypeInfo *info,
  * cstring into PostgreSQL type.
  */
 static Datum
-PLyObject_ToDatum(PLyTypeInfo *info,
-                                 PLyObToDatum *arg,
-                                 PyObject *plrv)
+PLyObject_ToDatum(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
 {
        PyObject   *volatile plrv_bo = NULL;
        Datum           rv;
@@ -2202,7 +2191,10 @@ PLyObject_ToDatum(PLyTypeInfo *info,
                else if (slen > plen)
                        elog(ERROR, "could not convert Python object into cstring: Python string longer than reported length");
                pg_verifymbstr(plrv_sc, slen, false);
-               rv = InputFunctionCall(&arg->typfunc, plrv_sc, arg->typioparam, -1);
+               rv = InputFunctionCall(&arg->typfunc,
+                                                          plrv_sc,
+                                                          arg->typioparam,
+                                                          typmod);
        }
        PG_CATCH();
        {
@@ -2217,9 +2209,7 @@ PLyObject_ToDatum(PLyTypeInfo *info,
 }
 
 static Datum
-PLySequence_ToArray(PLyTypeInfo *info,
-                                       PLyObToDatum *arg,
-                                       PyObject *plrv)
+PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
 {
        ArrayType  *array;
        int                     i;
@@ -2251,7 +2241,7 @@ PLySequence_ToArray(PLyTypeInfo *info,
                         * We don't support arrays of row types yet, so the first argument
                         * can be NULL.
                         */
-                       elems[i] = arg->elm->func(NULL, arg->elm, obj);
+                       elems[i] = arg->elm->func(arg->elm, -1, obj);
                }
                Py_XDECREF(obj);
        }
@@ -2300,7 +2290,7 @@ PLyMapping_ToTuple(PLyTypeInfo *info, PyObject *mapping)
                        }
                        else if (value)
                        {
-                               values[i] = (att->func) (info, att, value);
+                               values[i] = (att->func) (att, -1, value);
                                nulls[i] = false;
                        }
                        else
@@ -2377,7 +2367,7 @@ PLySequence_ToTuple(PLyTypeInfo *info, PyObject *sequence)
                        }
                        else if (value)
                        {
-                               values[i] = (att->func) (info, att, value);
+                               values[i] = (att->func) (att, -1, value);
                                nulls[i] = false;
                        }
 
@@ -2437,7 +2427,7 @@ PLyObject_ToTuple(PLyTypeInfo *info, PyObject *object)
                        }
                        else if (value)
                        {
-                               values[i] = (att->func) (info, att, value);
+                               values[i] = (att->func) (att, -1, value);
                                nulls[i] = false;
                        }
                        else
@@ -3019,7 +3009,9 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
                                PG_TRY();
                                {
                                        plan->values[j] =
-                                               plan->args[j].out.d.func(NULL, &(plan->args[j].out.d), elem);
+                                               plan->args[j].out.d.func(&(plan->args[j].out.d),
+                                                                                                -1,
+                                                                                                elem);
                                }
                                PG_CATCH();
                                {
index c3af5c211e6954f73be8abf002c8d63de1045f04..7520c79db58cca5dea8f18bfacca2d6962da91e8 100644 (file)
@@ -303,3 +303,26 @@ UPDATE trigger_test SET v = 'null' WHERE i = 0;
 DROP TRIGGER test_null_trigger ON trigger_test;
 
 SELECT * FROM trigger_test;
+
+
+--
+-- Test that triggers honor typmod when assigning to tuple fields,
+-- as per an early 9.0 bug report
+--
+
+SET DateStyle = 'ISO';
+
+CREATE FUNCTION set_modif_time() RETURNS trigger AS $$
+    TD['new']['modif_time'] = '2010-10-13 21:57:28.930486'
+    return 'MODIFY'
+$$ LANGUAGE plpythonu;
+
+CREATE TABLE pb (a TEXT, modif_time TIMESTAMP(0) WITHOUT TIME ZONE);
+
+CREATE TRIGGER set_modif_time BEFORE UPDATE ON pb
+  FOR EACH ROW EXECUTE PROCEDURE set_modif_time();
+
+INSERT INTO pb VALUES ('a', '2010-10-09 21:57:33.930486');
+SELECT * FROM pb;
+UPDATE pb SET a = 'b';
+SELECT * FROM pb;