diff --git a/src/pl/plpython/expected/README b/src/pl/plpython/expected/README index 574062dd77..24f5e80a29 100644 --- a/src/pl/plpython/expected/README +++ b/src/pl/plpython/expected/README @@ -2,3 +2,8 @@ Guide to alternative expected files: plpython_error_2.out Python 2.2, 2.3, 2.4 plpython_error.out Python 2.5, 2.6 + +plpython_unicode.out any version, when server encoding != SQL_ASCII; else ... +plpython_unicode_2.out Python 2.2 +plpython_unicode_3.out Python 2.3, 2.4 +plpython_unicode_5.out Python 2.5, 2.6 diff --git a/src/pl/plpython/expected/plpython_unicode_2.out b/src/pl/plpython/expected/plpython_unicode_2.out new file mode 100644 index 0000000000..5e44e4a799 --- /dev/null +++ b/src/pl/plpython/expected/plpython_unicode_2.out @@ -0,0 +1,52 @@ +-- +-- Unicode handling +-- +CREATE TABLE unicode_test ( + testvalue text NOT NULL +); +CREATE FUNCTION unicode_return() RETURNS text AS E' +return u"\\x80" +' LANGUAGE plpythonu; +CREATE FUNCTION unicode_trigger() RETURNS trigger AS E' +TD["new"]["testvalue"] = u"\\x80" +return "MODIFY" +' LANGUAGE plpythonu; +CREATE TRIGGER unicode_test_bi BEFORE INSERT ON unicode_test + FOR EACH ROW EXECUTE PROCEDURE unicode_trigger(); +CREATE FUNCTION unicode_plan1() RETURNS text AS E' +plan = plpy.prepare("SELECT $1 AS testvalue", ["text"]) +rv = plpy.execute(plan, [u"\\x80"], 1) +return rv[0]["testvalue"] +' LANGUAGE plpythonu; +CREATE FUNCTION unicode_plan2() RETURNS text AS E' +plan = plpy.prepare("SELECT $1 || $2 AS testvalue", ["text", u"text"]) +rv = plpy.execute(plan, ["foo", "bar"], 1) +return rv[0]["testvalue"] +' LANGUAGE plpythonu; +SELECT unicode_return(); +ERROR: PL/Python: could not convert Python Unicode object to PostgreSQL server encoding +DETAIL: exceptions.UnicodeError: ASCII encoding error: ordinal not in range(128) +CONTEXT: while creating return value +PL/Python function "unicode_return" +INSERT INTO unicode_test (testvalue) VALUES ('test'); +ERROR: PL/Python: could not convert Python Unicode object to PostgreSQL server encoding +DETAIL: exceptions.UnicodeError: ASCII encoding error: ordinal not in range(128) +CONTEXT: while modifying trigger row +PL/Python function "unicode_trigger" +SELECT * FROM unicode_test; + testvalue +----------- +(0 rows) + +SELECT unicode_plan1(); +WARNING: PL/Python: plpy.Error: unrecognized error in PLy_spi_execute_plan +CONTEXT: PL/Python function "unicode_plan1" +ERROR: PL/Python: could not convert Python Unicode object to PostgreSQL server encoding +DETAIL: exceptions.UnicodeError: ASCII encoding error: ordinal not in range(128) +CONTEXT: PL/Python function "unicode_plan1" +SELECT unicode_plan2(); + unicode_plan2 +--------------- + foobar +(1 row) + diff --git a/src/pl/plpython/expected/plpython_unicode_3.out b/src/pl/plpython/expected/plpython_unicode_3.out new file mode 100644 index 0000000000..8e48c20a62 --- /dev/null +++ b/src/pl/plpython/expected/plpython_unicode_3.out @@ -0,0 +1,52 @@ +-- +-- Unicode handling +-- +CREATE TABLE unicode_test ( + testvalue text NOT NULL +); +CREATE FUNCTION unicode_return() RETURNS text AS E' +return u"\\x80" +' LANGUAGE plpythonu; +CREATE FUNCTION unicode_trigger() RETURNS trigger AS E' +TD["new"]["testvalue"] = u"\\x80" +return "MODIFY" +' LANGUAGE plpythonu; +CREATE TRIGGER unicode_test_bi BEFORE INSERT ON unicode_test + FOR EACH ROW EXECUTE PROCEDURE unicode_trigger(); +CREATE FUNCTION unicode_plan1() RETURNS text AS E' +plan = plpy.prepare("SELECT $1 AS testvalue", ["text"]) +rv = plpy.execute(plan, [u"\\x80"], 1) +return rv[0]["testvalue"] +' LANGUAGE plpythonu; +CREATE FUNCTION unicode_plan2() RETURNS text AS E' +plan = plpy.prepare("SELECT $1 || $2 AS testvalue", ["text", u"text"]) +rv = plpy.execute(plan, ["foo", "bar"], 1) +return rv[0]["testvalue"] +' LANGUAGE plpythonu; +SELECT unicode_return(); +ERROR: PL/Python: could not convert Python Unicode object to PostgreSQL server encoding +DETAIL: exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128) +CONTEXT: while creating return value +PL/Python function "unicode_return" +INSERT INTO unicode_test (testvalue) VALUES ('test'); +ERROR: PL/Python: could not convert Python Unicode object to PostgreSQL server encoding +DETAIL: exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128) +CONTEXT: while modifying trigger row +PL/Python function "unicode_trigger" +SELECT * FROM unicode_test; + testvalue +----------- +(0 rows) + +SELECT unicode_plan1(); +WARNING: PL/Python: plpy.Error: unrecognized error in PLy_spi_execute_plan +CONTEXT: PL/Python function "unicode_plan1" +ERROR: PL/Python: could not convert Python Unicode object to PostgreSQL server encoding +DETAIL: exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128) +CONTEXT: PL/Python function "unicode_plan1" +SELECT unicode_plan2(); + unicode_plan2 +--------------- + foobar +(1 row) + diff --git a/src/pl/plpython/expected/plpython_unicode_5.out b/src/pl/plpython/expected/plpython_unicode_5.out new file mode 100644 index 0000000000..76ff8f23cd --- /dev/null +++ b/src/pl/plpython/expected/plpython_unicode_5.out @@ -0,0 +1,52 @@ +-- +-- Unicode handling +-- +CREATE TABLE unicode_test ( + testvalue text NOT NULL +); +CREATE FUNCTION unicode_return() RETURNS text AS E' +return u"\\x80" +' LANGUAGE plpythonu; +CREATE FUNCTION unicode_trigger() RETURNS trigger AS E' +TD["new"]["testvalue"] = u"\\x80" +return "MODIFY" +' LANGUAGE plpythonu; +CREATE TRIGGER unicode_test_bi BEFORE INSERT ON unicode_test + FOR EACH ROW EXECUTE PROCEDURE unicode_trigger(); +CREATE FUNCTION unicode_plan1() RETURNS text AS E' +plan = plpy.prepare("SELECT $1 AS testvalue", ["text"]) +rv = plpy.execute(plan, [u"\\x80"], 1) +return rv[0]["testvalue"] +' LANGUAGE plpythonu; +CREATE FUNCTION unicode_plan2() RETURNS text AS E' +plan = plpy.prepare("SELECT $1 || $2 AS testvalue", ["text", u"text"]) +rv = plpy.execute(plan, ["foo", "bar"], 1) +return rv[0]["testvalue"] +' LANGUAGE plpythonu; +SELECT unicode_return(); +ERROR: PL/Python: could not convert Python Unicode object to PostgreSQL server encoding +DETAIL: : 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128) +CONTEXT: while creating return value +PL/Python function "unicode_return" +INSERT INTO unicode_test (testvalue) VALUES ('test'); +ERROR: PL/Python: could not convert Python Unicode object to PostgreSQL server encoding +DETAIL: : 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128) +CONTEXT: while modifying trigger row +PL/Python function "unicode_trigger" +SELECT * FROM unicode_test; + testvalue +----------- +(0 rows) + +SELECT unicode_plan1(); +WARNING: PL/Python: : unrecognized error in PLy_spi_execute_plan +CONTEXT: PL/Python function "unicode_plan1" +ERROR: PL/Python: could not convert Python Unicode object to PostgreSQL server encoding +DETAIL: : 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128) +CONTEXT: PL/Python function "unicode_plan1" +SELECT unicode_plan2(); + unicode_plan2 +--------------- + foobar +(1 row) + diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index ae898385b5..c37993829f 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -1,7 +1,7 @@ /********************************************************************** * plpython.c - python as a procedural language for PostgreSQL * - * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.129 2009/09/12 22:13:12 petere Exp $ + * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.130 2009/09/13 22:07:06 petere Exp $ * ********************************************************************* */ @@ -3343,11 +3343,21 @@ PLy_free(void *ptr) static PyObject* PLyUnicode_Str(PyObject *unicode) { + PyObject *rv; + const char *serverenc; + /* - * This assumes that the PostgreSQL encoding names are acceptable - * to Python, but that appears to be the case. + * Python understands almost all PostgreSQL encoding names, but it + * doesn't know SQL_ASCII. */ - return PyUnicode_AsEncodedString(unicode, GetDatabaseEncodingName(), "strict"); + if (GetDatabaseEncoding() == PG_SQL_ASCII) + serverenc = "ascii"; + else + serverenc = GetDatabaseEncodingName(); + rv = PyUnicode_AsEncodedString(unicode, serverenc, "strict"); + if (rv == NULL) + PLy_elog(ERROR, "could not convert Python Unicode object to PostgreSQL server encoding"); + return rv; } /*