From 1ce7a57ca6e8c5212fa2ab3bf31d56c74d5b5b8f Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 11 Mar 2015 15:44:17 -0400 Subject: [PATCH] PL/Python: Avoid lossiness in float conversion PL/Python uses str() to convert Python values back to PostgreSQL, but str() is lossy for float values, so use repr() instead in that case. Author: Marko Kreen --- src/pl/plpython/expected/plpython_types.out | 8 ++++++++ src/pl/plpython/plpy_typeio.c | 12 ++++++++++++ src/pl/plpython/sql/plpython_types.sql | 1 + 3 files changed, 21 insertions(+) diff --git a/src/pl/plpython/expected/plpython_types.out b/src/pl/plpython/expected/plpython_types.out index 61d800b57a..17057a543d 100644 --- a/src/pl/plpython/expected/plpython_types.out +++ b/src/pl/plpython/expected/plpython_types.out @@ -354,6 +354,14 @@ CONTEXT: PL/Python function "test_type_conversion_float8" (1 row) +SELECT * FROM test_type_conversion_float8(100100100.654321); +INFO: (100100100.654321, ) +CONTEXT: PL/Python function "test_type_conversion_float8" + test_type_conversion_float8 +----------------------------- + 100100100.654321 +(1 row) + CREATE FUNCTION test_type_conversion_oid(x oid) RETURNS oid AS $$ plpy.info(x, type(x)) return x diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c index 524534e613..8c70c7c978 100644 --- a/src/pl/plpython/plpy_typeio.c +++ b/src/pl/plpython/plpy_typeio.c @@ -760,6 +760,18 @@ PLyObject_ToDatum(PLyObToDatum *arg, int32 typmod, PyObject *plrv) if (PyUnicode_Check(plrv)) plrv_bo = PLyUnicode_Bytes(plrv); + else if (PyFloat_Check(plrv)) + { + /* use repr() for floats, str() is lossy */ +#if PY_MAJOR_VERSION >= 3 + PyObject *s = PyObject_Repr(plrv); + + plrv_bo = PLyUnicode_Bytes(s); + Py_XDECREF(s); +#else + plrv_bo = PyObject_Repr(plrv); +#endif + } else { #if PY_MAJOR_VERSION >= 3 diff --git a/src/pl/plpython/sql/plpython_types.sql b/src/pl/plpython/sql/plpython_types.sql index d9d0db66bc..19d920d3c7 100644 --- a/src/pl/plpython/sql/plpython_types.sql +++ b/src/pl/plpython/sql/plpython_types.sql @@ -122,6 +122,7 @@ SELECT * FROM test_type_conversion_float8(100); SELECT * FROM test_type_conversion_float8(-100); SELECT * FROM test_type_conversion_float8(5000000000.5); SELECT * FROM test_type_conversion_float8(null); +SELECT * FROM test_type_conversion_float8(100100100.654321); CREATE FUNCTION test_type_conversion_oid(x oid) RETURNS oid AS $$ -- 2.40.0