ERROR: PL/Python: return value of function with array return type is not a Python sequence
CONTEXT: while creating return value
PL/Python function "test_type_conversion_array_error"
+--
+-- Prepared statements
+--
+CREATE OR REPLACE FUNCTION test_prep_bool_input() RETURNS int
+LANGUAGE plpythonu
+AS $$
+plan = plpy.prepare("SELECT CASE WHEN $1 THEN 1 ELSE 0 END AS val", ['boolean'])
+rv = plpy.execute(plan, ['fa'], 5) # 'fa' is true in Python
+return rv[0]['val']
+$$;
+SELECT test_prep_bool_input(); -- 1
+ test_prep_bool_input
+----------------------
+ 1
+(1 row)
+
+CREATE OR REPLACE FUNCTION test_prep_bool_output() RETURNS bool
+LANGUAGE plpythonu
+AS $$
+plan = plpy.prepare("SELECT $1 = 1 AS val", ['int'])
+rv = plpy.execute(plan, [0], 5)
+plpy.info(rv[0])
+return rv[0]['val']
+$$;
+SELECT test_prep_bool_output(); -- false
+INFO: {'val': False}
+CONTEXT: PL/Python function "test_prep_bool_output"
+ test_prep_bool_output
+-----------------------
+ f
+(1 row)
+
+CREATE OR REPLACE FUNCTION test_prep_bytea_input(bb bytea) RETURNS int
+LANGUAGE plpythonu
+AS $$
+plan = plpy.prepare("SELECT octet_length($1) AS val", ['bytea'])
+rv = plpy.execute(plan, [bb], 5)
+return rv[0]['val']
+$$;
+SELECT test_prep_bytea_input(E'a\\000b'); -- 3 (embedded null formerly truncated value)
+ test_prep_bytea_input
+-----------------------
+ 3
+(1 row)
+
+CREATE OR REPLACE FUNCTION test_prep_bytea_output() RETURNS bytea
+LANGUAGE plpythonu
+AS $$
+plan = plpy.prepare("SELECT decode('aa00bb', 'hex') AS val")
+rv = plpy.execute(plan, [], 5)
+plpy.info(rv[0])
+return rv[0]['val']
+$$;
+SELECT test_prep_bytea_output();
+INFO: {'val': '\xaa\x00\xbb'}
+CONTEXT: PL/Python function "test_prep_bytea_output"
+ test_prep_bytea_output
+------------------------
+ \xaa00bb
+(1 row)
+
CREATE FUNCTION test_type_conversion_bool(x bool) RETURNS bool AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_bool(true);
INFO: (True, )
CONTEXT: PL/Python function "test_type_conversion_bool"
ret = [0]
plpy.info(ret, not not ret)
return ret
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_bool_other(0);
INFO: (0, False)
CONTEXT: PL/Python function "test_type_conversion_bool_other"
CREATE FUNCTION test_type_conversion_char(x char) RETURNS char AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_char('a');
INFO: ('a', )
CONTEXT: PL/Python function "test_type_conversion_char"
CREATE FUNCTION test_type_conversion_int2(x int2) RETURNS int2 AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_int2(100::int2);
INFO: (100, )
CONTEXT: PL/Python function "test_type_conversion_int2"
CREATE FUNCTION test_type_conversion_int4(x int4) RETURNS int4 AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_int4(100);
INFO: (100, )
CONTEXT: PL/Python function "test_type_conversion_int4"
CREATE FUNCTION test_type_conversion_int8(x int8) RETURNS int8 AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_int8(100);
-INFO: (100L, '>)
+INFO: (100, '>)
CONTEXT: PL/Python function "test_type_conversion_int8"
test_type_conversion_int8
---------------------------
(1 row)
SELECT * FROM test_type_conversion_int8(-100);
-INFO: (-100L, '>)
+INFO: (-100, '>)
CONTEXT: PL/Python function "test_type_conversion_int8"
test_type_conversion_int8
---------------------------
(1 row)
SELECT * FROM test_type_conversion_int8(5000000000);
-INFO: (5000000000L, '>)
+INFO: (5000000000, '>)
CONTEXT: PL/Python function "test_type_conversion_int8"
test_type_conversion_int8
---------------------------
CREATE FUNCTION test_type_conversion_numeric(x numeric) RETURNS numeric AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
/* The current implementation converts numeric to float. */
SELECT * FROM test_type_conversion_numeric(100);
INFO: (100.0, )
CREATE FUNCTION test_type_conversion_float4(x float4) RETURNS float4 AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_float4(100);
INFO: (100.0, )
CONTEXT: PL/Python function "test_type_conversion_float4"
CREATE FUNCTION test_type_conversion_float8(x float8) RETURNS float8 AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_float8(100);
INFO: (100.0, )
CONTEXT: PL/Python function "test_type_conversion_float8"
CREATE FUNCTION test_type_conversion_text(x text) RETURNS text AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_text('hello world');
INFO: ('hello world', )
CONTEXT: PL/Python function "test_type_conversion_text"
CREATE FUNCTION test_type_conversion_bytea(x bytea) RETURNS bytea AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_bytea('hello world');
INFO: (b'hello world', )
CONTEXT: PL/Python function "test_type_conversion_bytea"
CREATE FUNCTION test_type_marshal() RETURNS bytea AS $$
import marshal
return marshal.dumps('hello world')
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
CREATE FUNCTION test_type_unmarshal(x bytea) RETURNS text AS $$
import marshal
try:
return marshal.loads(x)
-except ValueError, e:
+except ValueError as e:
return 'FAILED: ' + str(e)
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT test_type_unmarshal(x) FROM test_type_marshal() x;
test_type_unmarshal
---------------------
CREATE DOMAIN booltrue AS bool CHECK (VALUE IS TRUE OR VALUE IS NULL);
CREATE FUNCTION test_type_conversion_booltrue(x booltrue, y bool) RETURNS booltrue AS $$
return y
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_booltrue(true, true);
test_type_conversion_booltrue
-------------------------------
CREATE FUNCTION test_type_conversion_uint2(x uint2, y int) RETURNS uint2 AS $$
plpy.info(x, type(x))
return y
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_uint2(100::uint2, 50);
INFO: (100, )
CONTEXT: PL/Python function "test_type_conversion_uint2"
CREATE DOMAIN nnint AS int CHECK (VALUE IS NOT NULL);
CREATE FUNCTION test_type_conversion_nnint(x nnint, y int) RETURNS nnint AS $$
return y
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_nnint(10, 20);
test_type_conversion_nnint
----------------------------
CREATE FUNCTION test_type_conversion_bytea10(x bytea10, y bytea) RETURNS bytea10 AS $$
plpy.info(x, type(x))
return y
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_bytea10('hello wold', 'hello wold');
INFO: (b'hello wold', )
CONTEXT: PL/Python function "test_type_conversion_bytea10"
CREATE FUNCTION test_type_conversion_array_int4(x int4[]) RETURNS int4[] AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_array_int4(ARRAY[0, 100]);
INFO: ([0, 100], )
CONTEXT: PL/Python function "test_type_conversion_array_int4"
CREATE FUNCTION test_type_conversion_array_bytea(x bytea[]) RETURNS bytea[] AS $$
plpy.info(x, type(x))
return x
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_array_bytea(ARRAY[E'\\xdeadbeef'::bytea, NULL]);
INFO: ([b'\xde\xad\xbe\xef', None], )
CONTEXT: PL/Python function "test_type_conversion_array_bytea"
CREATE FUNCTION test_type_conversion_array_mixed1() RETURNS text[] AS $$
return [123, 'abc']
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_array_mixed1();
test_type_conversion_array_mixed1
-----------------------------------
CREATE FUNCTION test_type_conversion_array_mixed2() RETURNS int[] AS $$
return [123, 'abc']
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_array_mixed2();
ERROR: invalid input syntax for integer: "abc"
CONTEXT: while creating return value
PL/Python function "test_type_conversion_array_mixed2"
CREATE FUNCTION test_type_conversion_array_record() RETURNS type_record[] AS $$
return [None]
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_array_record();
ERROR: PL/Python functions cannot return type type_record[]
DETAIL: PL/Python does not support conversion to arrays of row types.
CREATE FUNCTION test_type_conversion_array_string() RETURNS text[] AS $$
return 'abc'
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_array_string();
test_type_conversion_array_string
-----------------------------------
CREATE FUNCTION test_type_conversion_array_tuple() RETURNS text[] AS $$
return ('abc', 'def')
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_array_tuple();
test_type_conversion_array_tuple
----------------------------------
CREATE FUNCTION test_type_conversion_array_error() RETURNS int[] AS $$
return 5
-$$ LANGUAGE plpythonu;
+$$ LANGUAGE plpython3u;
SELECT * FROM test_type_conversion_array_error();
ERROR: PL/Python: return value of function with array return type is not a Python sequence
CONTEXT: while creating return value
PL/Python function "test_type_conversion_array_error"
+--
+-- Prepared statements
+--
+CREATE OR REPLACE FUNCTION test_prep_bool_input() RETURNS int
+LANGUAGE plpython3u
+AS $$
+plan = plpy.prepare("SELECT CASE WHEN $1 THEN 1 ELSE 0 END AS val", ['boolean'])
+rv = plpy.execute(plan, ['fa'], 5) # 'fa' is true in Python
+return rv[0]['val']
+$$;
+SELECT test_prep_bool_input(); -- 1
+ test_prep_bool_input
+----------------------
+ 1
+(1 row)
+
+CREATE OR REPLACE FUNCTION test_prep_bool_output() RETURNS bool
+LANGUAGE plpython3u
+AS $$
+plan = plpy.prepare("SELECT $1 = 1 AS val", ['int'])
+rv = plpy.execute(plan, [0], 5)
+plpy.info(rv[0])
+return rv[0]['val']
+$$;
+SELECT test_prep_bool_output(); -- false
+INFO: {'val': False}
+CONTEXT: PL/Python function "test_prep_bool_output"
+ test_prep_bool_output
+-----------------------
+ f
+(1 row)
+
+CREATE OR REPLACE FUNCTION test_prep_bytea_input(bb bytea) RETURNS int
+LANGUAGE plpython3u
+AS $$
+plan = plpy.prepare("SELECT octet_length($1) AS val", ['bytea'])
+rv = plpy.execute(plan, [bb], 5)
+return rv[0]['val']
+$$;
+SELECT test_prep_bytea_input(E'a\\000b'); -- 3 (embedded null formerly truncated value)
+ test_prep_bytea_input
+-----------------------
+ 3
+(1 row)
+
+CREATE OR REPLACE FUNCTION test_prep_bytea_output() RETURNS bytea
+LANGUAGE plpython3u
+AS $$
+plan = plpy.prepare("SELECT decode('aa00bb', 'hex') AS val")
+rv = plpy.execute(plan, [], 5)
+plpy.info(rv[0])
+return rv[0]['val']
+$$;
+SELECT test_prep_bytea_output();
+INFO: {'val': b'\xaa\x00\xbb'}
+CONTEXT: PL/Python function "test_prep_bytea_output"
+ test_prep_bytea_output
+------------------------
+ \xaa00bb
+(1 row)
+
/**********************************************************************
* plpython.c - python as a procedural language for PostgreSQL
*
- * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.139 2010/02/26 02:01:36 momjian Exp $
+ * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.140 2010/03/18 13:23:56 petere Exp $
*
*********************************************************************
*/
static char *PLy_strdup(const char *);
static void PLy_free(void *);
-static PyObject *PLyUnicode_Str(PyObject *unicode);
static PyObject *PLyUnicode_Bytes(PyObject *unicode);
static char *PLyUnicode_AsString(PyObject *unicode);
for (j = 0; j < nargs; j++)
{
- PyObject *elem,
- *so;
+ PyObject *elem;
elem = PySequence_GetItem(list, j);
if (elem != Py_None)
{
- if (PyUnicode_Check(elem))
- so = PLyUnicode_Str(elem);
- else
- so = PyObject_Str(elem);
- if (!so)
- PLy_elog(ERROR, "could not execute plan");
- Py_DECREF(elem);
-
PG_TRY();
{
- char *sv = PyString_AsString(so);
-
plan->values[j] =
- InputFunctionCall(&(plan->args[j].out.d.typfunc),
- sv,
- plan->args[j].out.d.typioparam,
- -1);
+ plan->args[j].out.d.func(NULL, &(plan->args[j].out.d), elem);
}
PG_CATCH();
{
- Py_DECREF(so);
+ Py_DECREF(elem);
PG_RE_THROW();
}
PG_END_TRY();
- Py_DECREF(so);
+ Py_DECREF(elem);
nulls[j] = ' ';
}
else
free(ptr);
}
-/*
- * Convert a Unicode object to a Python string.
- */
-static PyObject *
-PLyUnicode_Str(PyObject *unicode)
-{
-#if PY_MAJOR_VERSION >= 3
- /* In Python 3, this is a noop. */
- Py_INCREF(unicode);
- return unicode;
-#else
-
- /*
- * In Python 2, this means converting the Unicode to bytes in the server
- * encoding.
- */
- return PLyUnicode_Bytes(unicode);
-#endif
-}
-
/*
* Convert a Python unicode object to a Python string/bytes object in
* PostgreSQL server encoding. Reference ownership is passed to the