|
1 | 1 | /********************************************************************** |
2 | 2 | * plpython.c - python as a procedural language for PostgreSQL |
3 | 3 | * |
4 | | - * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.128 2009/09/09 19:00:09 petere Exp $ |
| 4 | + * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.129 2009/09/12 22:13:12 petere Exp $ |
5 | 5 | * |
6 | 6 | ********************************************************************* |
7 | 7 | */ |
@@ -54,6 +54,7 @@ typedef int Py_ssize_t; |
54 | 54 | #include "executor/spi.h" |
55 | 55 | #include "funcapi.h" |
56 | 56 | #include "fmgr.h" |
| 57 | +#include "mb/pg_wchar.h" |
57 | 58 | #include "miscadmin.h" |
58 | 59 | #include "nodes/makefuncs.h" |
59 | 60 | #include "parser/parse_type.h" |
@@ -238,6 +239,9 @@ static void *PLy_malloc0(size_t); |
238 | 239 | static char *PLy_strdup(const char *); |
239 | 240 | static void PLy_free(void *); |
240 | 241 |
|
| 242 | +static PyObject*PLyUnicode_Str(PyObject *unicode); |
| 243 | +static char *PLyUnicode_AsString(PyObject *unicode); |
| 244 | + |
241 | 245 | /* sub handlers for functions and triggers */ |
242 | 246 | static Datum PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *); |
243 | 247 | static HeapTuple PLy_trigger_handler(FunctionCallInfo fcinfo, PLyProcedure *); |
@@ -474,13 +478,19 @@ PLy_trigger_handler(FunctionCallInfo fcinfo, PLyProcedure *proc) |
474 | 478 | { |
475 | 479 | char *srv; |
476 | 480 |
|
477 | | - if (!PyString_Check(plrv)) |
| 481 | + if (PyString_Check(plrv)) |
| 482 | + srv = PyString_AsString(plrv); |
| 483 | + else if (PyUnicode_Check(plrv)) |
| 484 | + srv = PLyUnicode_AsString(plrv); |
| 485 | + else |
| 486 | + { |
478 | 487 | ereport(ERROR, |
479 | 488 | (errcode(ERRCODE_DATA_EXCEPTION), |
480 | 489 | errmsg("unexpected return value from trigger procedure"), |
481 | 490 | errdetail("Expected None or a string."))); |
| 491 | + srv = NULL; /* keep compiler quiet */ |
| 492 | + } |
482 | 493 |
|
483 | | - srv = PyString_AsString(plrv); |
484 | 494 | if (pg_strcasecmp(srv, "SKIP") == 0) |
485 | 495 | rv = NULL; |
486 | 496 | else if (pg_strcasecmp(srv, "MODIFY") == 0) |
@@ -572,15 +582,24 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, |
572 | 582 |
|
573 | 583 | for (i = 0; i < natts; i++) |
574 | 584 | { |
| 585 | + char *plattstr; |
| 586 | + |
575 | 587 | platt = PyList_GetItem(plkeys, i); |
576 | | - if (!PyString_Check(platt)) |
| 588 | + if (PyString_Check(platt)) |
| 589 | + plattstr = PyString_AsString(platt); |
| 590 | + else if (PyUnicode_Check(platt)) |
| 591 | + plattstr = PLyUnicode_AsString(platt); |
| 592 | + else |
| 593 | + { |
577 | 594 | ereport(ERROR, |
578 | 595 | (errmsg("TD[\"new\"] dictionary key at ordinal position %d is not a string", i))); |
579 | | - attn = SPI_fnumber(tupdesc, PyString_AsString(platt)); |
| 596 | + plattstr = NULL; /* keep compiler quiet */ |
| 597 | + } |
| 598 | + attn = SPI_fnumber(tupdesc, plattstr); |
580 | 599 | if (attn == SPI_ERROR_NOATTRIBUTE) |
581 | 600 | ereport(ERROR, |
582 | 601 | (errmsg("key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row", |
583 | | - PyString_AsString(platt)))); |
| 602 | + plattstr))); |
584 | 603 | atti = attn - 1; |
585 | 604 |
|
586 | 605 | plval = PyDict_GetItem(plntup, platt); |
@@ -1942,7 +1961,10 @@ PLyObject_ToDatum(PLyTypeInfo *info, |
1942 | 1961 |
|
1943 | 1962 | Assert(plrv != Py_None); |
1944 | 1963 |
|
1945 | | - plrv_so = PyObject_Str(plrv); |
| 1964 | + if (PyUnicode_Check(plrv)) |
| 1965 | + plrv_so = PLyUnicode_Str(plrv); |
| 1966 | + else |
| 1967 | + plrv_so = PyObject_Str(plrv); |
1946 | 1968 | if (!plrv_so) |
1947 | 1969 | PLy_elog(ERROR, "could not create string representation of Python object"); |
1948 | 1970 |
|
@@ -2562,10 +2584,16 @@ PLy_spi_prepare(PyObject *self, PyObject *args) |
2562 | 2584 | Form_pg_type typeStruct; |
2563 | 2585 |
|
2564 | 2586 | optr = PySequence_GetItem(list, i); |
2565 | | - if (!PyString_Check(optr)) |
| 2587 | + if (PyString_Check(optr)) |
| 2588 | + sptr = PyString_AsString(optr); |
| 2589 | + else if (PyUnicode_Check(optr)) |
| 2590 | + sptr = PLyUnicode_AsString(optr); |
| 2591 | + else |
| 2592 | + { |
2566 | 2593 | ereport(ERROR, |
2567 | 2594 | (errmsg("plpy.prepare: type name at ordinal position %d is not a string", i))); |
2568 | | - sptr = PyString_AsString(optr); |
| 2595 | + sptr = NULL; /* keep compiler quiet */ |
| 2596 | + } |
2569 | 2597 |
|
2570 | 2598 | /******************************************************** |
2571 | 2599 | * Resolve argument type names and then look them up by |
@@ -2670,7 +2698,7 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit) |
2670 | 2698 |
|
2671 | 2699 | if (list != NULL) |
2672 | 2700 | { |
2673 | | - if (!PySequence_Check(list) || PyString_Check(list)) |
| 2701 | + if (!PySequence_Check(list) || PyString_Check(list) || PyUnicode_Check(list)) |
2674 | 2702 | { |
2675 | 2703 | PLy_exception_set(PLy_exc_spi_error, "plpy.execute takes a sequence as its second argument"); |
2676 | 2704 | return NULL; |
@@ -2714,7 +2742,10 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit) |
2714 | 2742 | elem = PySequence_GetItem(list, j); |
2715 | 2743 | if (elem != Py_None) |
2716 | 2744 | { |
2717 | | - so = PyObject_Str(elem); |
| 2745 | + if (PyUnicode_Check(elem)) |
| 2746 | + so = PLyUnicode_Str(elem); |
| 2747 | + else |
| 2748 | + so = PyObject_Str(elem); |
2718 | 2749 | if (!so) |
2719 | 2750 | PLy_elog(ERROR, "could not execute plan"); |
2720 | 2751 | Py_DECREF(elem); |
@@ -3303,3 +3334,32 @@ PLy_free(void *ptr) |
3303 | 3334 | { |
3304 | 3335 | free(ptr); |
3305 | 3336 | } |
| 3337 | + |
| 3338 | +/* |
| 3339 | + * Convert a Python unicode object to a Python string object in |
| 3340 | + * PostgreSQL server encoding. Reference ownership is passed to the |
| 3341 | + * caller. |
| 3342 | + */ |
| 3343 | +static PyObject* |
| 3344 | +PLyUnicode_Str(PyObject *unicode) |
| 3345 | +{ |
| 3346 | + /* |
| 3347 | + * This assumes that the PostgreSQL encoding names are acceptable |
| 3348 | + * to Python, but that appears to be the case. |
| 3349 | + */ |
| 3350 | + return PyUnicode_AsEncodedString(unicode, GetDatabaseEncodingName(), "strict"); |
| 3351 | +} |
| 3352 | + |
| 3353 | +/* |
| 3354 | + * Convert a Python unicode object to a C string in PostgreSQL server |
| 3355 | + * encoding. No Python object reference is passed out of this |
| 3356 | + * function. |
| 3357 | + */ |
| 3358 | +static char * |
| 3359 | +PLyUnicode_AsString(PyObject *unicode) |
| 3360 | +{ |
| 3361 | + PyObject *o = PLyUnicode_Str(unicode); |
| 3362 | + char *rv = PyString_AsString(o); |
| 3363 | + Py_XDECREF(o); |
| 3364 | + return rv; |
| 3365 | +} |
0 commit comments