summaryrefslogtreecommitdiff
path: root/src/pl/plpython
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-10-11 22:16:46 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2010-10-11 22:16:46 -0400
commit67120d35e28b85bbb4d10f4568f6e3b85c8e0460 (patch)
treec3885cc25dff02d03ea7d7b02d7d767d63c38284 /src/pl/plpython
parent3b6eb752d99360e4e21ddff2c3edf750ab9b026a (diff)
Fix plpython so that it again honors typmod while assigning to tuple fields.
This was broken in 9.0 while improving plpython's conversion behavior for bytea and boolean. Per bug report from maizi.
Diffstat (limited to 'src/pl/plpython')
-rw-r--r--src/pl/plpython/expected/plpython_trigger.out26
-rw-r--r--src/pl/plpython/plpython.c62
-rw-r--r--src/pl/plpython/sql/plpython_trigger.sql23
3 files changed, 76 insertions, 35 deletions
diff --git a/src/pl/plpython/expected/plpython_trigger.out b/src/pl/plpython/expected/plpython_trigger.out
index 3192ff1d48e..bdcf3e8eb4e 100644
--- a/src/pl/plpython/expected/plpython_trigger.out
+++ b/src/pl/plpython/expected/plpython_trigger.out
@@ -453,3 +453,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)
+
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index e7e5ded1200..1446f0d4558 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -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
@@ -1131,9 +1128,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();
@@ -2098,9 +2093,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;
@@ -2119,9 +2112,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;
@@ -2163,9 +2154,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;
@@ -2201,7 +2190,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();
{
@@ -2216,9 +2208,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;
@@ -2250,7 +2240,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);
}
@@ -2299,7 +2289,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
@@ -2376,7 +2366,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;
}
@@ -2436,7 +2426,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
@@ -3018,7 +3008,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();
{
diff --git a/src/pl/plpython/sql/plpython_trigger.sql b/src/pl/plpython/sql/plpython_trigger.sql
index c60a6737801..e9a215d02eb 100644
--- a/src/pl/plpython/sql/plpython_trigger.sql
+++ b/src/pl/plpython/sql/plpython_trigger.sql
@@ -286,3 +286,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;