提交 c1a94208 编写于 作者: A Alexey Grishchenko

Revert "PL/Python adding support for multi-dimensional arrays"

This reverts commit 41857ff3.
上级 c63f1b5d
...@@ -550,9 +550,6 @@ CREATE FUNCTION test_type_conversion_float8(x float8) returns float8 AS $$ retur ...@@ -550,9 +550,6 @@ CREATE FUNCTION test_type_conversion_float8(x float8) returns float8 AS $$ retur
CREATE FUNCTION test_type_conversion_numeric(x numeric) returns numeric AS $$ return x $$ language plpythonu; CREATE FUNCTION test_type_conversion_numeric(x numeric) returns numeric AS $$ return x $$ language plpythonu;
CREATE FUNCTION test_type_conversion_text(x text) returns text AS $$ return x $$ language plpythonu; CREATE FUNCTION test_type_conversion_text(x text) returns text AS $$ return x $$ language plpythonu;
CREATE FUNCTION test_type_conversion_bytea(x bytea) returns bytea AS $$ return x $$ language plpythonu; CREATE FUNCTION test_type_conversion_bytea(x bytea) returns bytea AS $$ return x $$ language plpythonu;
CREATE FUNCTION test_type_conversion_array_int4(x int4[]) RETURNS int4[] AS $$ return x $$ LANGUAGE plpythonu;
CREATE FUNCTION test_type_conversion_array_numeric(x numeric[]) returns numeric[] AS $$ return x $$ language plpythonu;
CREATE FUNCTION test_type_conversion_array_text(x text[]) RETURNS text[] AS $$ return x $$ LANGUAGE plpythonu;
CREATE FUNCTION test_type_marshal() returns bytea AS $$ CREATE FUNCTION test_type_marshal() returns bytea AS $$
import marshal import marshal
return marshal.dumps('hello world') return marshal.dumps('hello world')
...@@ -587,16 +584,6 @@ RETURNS circle AS $$ ...@@ -587,16 +584,6 @@ RETURNS circle AS $$
exec('y = ' + s) exec('y = ' + s)
return y return y
$$ language plpythonu; $$ language plpythonu;
CREATE FUNCTION test_return_array_int(s text)
RETURNS int[] AS $$
exec('y = ' + s)
return y
$$ language plpythonu;
CREATE FUNCTION test_return_array_text(s text)
RETURNS text[] AS $$
exec('y = ' + s)
return y
$$ language plpythonu;
CREATE FUNCTION test_return_setof_void(s text) CREATE FUNCTION test_return_setof_void(s text)
RETURNS setof void AS $$ RETURNS setof void AS $$
exec('y = ' + s) exec('y = ' + s)
......
...@@ -878,180 +878,6 @@ SELECT * FROM test_return_circle(E'"test\\0"'); ...@@ -878,180 +878,6 @@ SELECT * FROM test_return_circle(E'"test\\0"');
ERROR: could not convert Python object into cstring: Python string representation appears to contain null bytes ERROR: could not convert Python object into cstring: Python string representation appears to contain null bytes
CONTEXT: while creating return value CONTEXT: while creating return value
PL/Python function "test_return_circle" PL/Python function "test_return_circle"
--
-- Case 5: Return array of integers
--
-- Test returning arrays of fixed-width elements from PL/Python functions
--
-- From Python None
SELECT test_return_array_int('None');
test_return_array_int
-----------------------
(1 row)
SELECT * FROM test_return_array_int('None');
test_return_array_int
-----------------------
(1 row)
-- From Python empty list
SELECT test_return_array_int('[]');
test_return_array_int
-----------------------
{}
(1 row)
SELECT * FROM test_return_array_int('[]');
test_return_array_int
-----------------------
{}
(1 row)
-- From Python non-empty list
SELECT test_return_array_int('[1,2]');
test_return_array_int
-----------------------
{1,2}
(1 row)
SELECT * FROM test_return_array_int('[1,2]');
test_return_array_int
-----------------------
{1,2}
(1 row)
-- From Python multiple lists
SELECT test_return_array_int('[[1,2,3],[4,5,6]]');
test_return_array_int
-----------------------
{{1,2,3},{4,5,6}}
(1 row)
SELECT * FROM test_return_array_int('[[1,2,3],[4,5,6]]');
test_return_array_int
-----------------------
{{1,2,3},{4,5,6}}
(1 row)
-- Error conditions
-- Multi-dimensional array with non-fixed dimension sizes
SELECT test_return_array_int('[[1,2,3],[1,2]]');
ERROR: Multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length 2 while expected 3 (plpython.c:4865)
CONTEXT: while creating return value
PL/Python function "test_return_array_int"
SELECT * FROM test_return_array_int('[[1,2,3],[1,2]]');
ERROR: Multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length 2 while expected 3 (plpython.c:4865)
CONTEXT: while creating return value
PL/Python function "test_return_array_int"
-- Multi-dimensional array with mix of arrays and atomic elements
SELECT test_return_array_int('[[1,2,3],[1,[2,3],[4,5]]]');
ERROR: invalid input syntax for integer: "[2, 3]"
CONTEXT: while creating return value
PL/Python function "test_return_array_int"
SELECT * FROM test_return_array_int('[[1,2,3],[1,[2,3],[4,5]]]');
ERROR: invalid input syntax for integer: "[2, 3]"
CONTEXT: while creating return value
PL/Python function "test_return_array_int"
-- Multi-dimensional array with missing dimensions
SELECT test_return_array_int('[[1,2,3],None,[4,5,6]]');
ERROR: Multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length -1 while expected 3 (plpython.c:4865)
DETAIL: TypeError: object of type 'NoneType' has no len()
CONTEXT: while creating return value
PL/Python function "test_return_array_int"
SELECT * FROM test_return_array_int('[[1,2,3],None,[4,5,6]]');
ERROR: Multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length -1 while expected 3 (plpython.c:4865)
DETAIL: TypeError: object of type 'NoneType' has no len()
CONTEXT: while creating return value
PL/Python function "test_return_array_int"
--
-- Case 5: Return array of texts
--
-- Test returning arrays of variable-width elements from PL/Python functions
--
-- From Python None
SELECT test_return_array_text('None');
test_return_array_text
------------------------
(1 row)
SELECT * FROM test_return_array_text('None');
test_return_array_text
------------------------
(1 row)
-- From Python empty list
SELECT test_return_array_text('[]');
test_return_array_text
------------------------
{}
(1 row)
SELECT * FROM test_return_array_text('[]');
test_return_array_text
------------------------
{}
(1 row)
-- From Python non-empty list
SELECT test_return_array_text('["abc","def"]');
test_return_array_text
------------------------
{abc,def}
(1 row)
SELECT * FROM test_return_array_text('["abc","def"]');
test_return_array_text
------------------------
{abc,def}
(1 row)
-- From Python multiple lists
SELECT test_return_array_text('[["a","bcd","ef"],[None,"gh","ijklm"]]');
test_return_array_text
------------------------------
{{a,bcd,ef},{NULL,gh,ijklm}}
(1 row)
SELECT * FROM test_return_array_text('[["a","bcd","ef"],[None,"gh","ijklm"]]');
test_return_array_text
------------------------------
{{a,bcd,ef},{NULL,gh,ijklm}}
(1 row)
-- Error conditions
-- Multi-dimensional array with non-fixed dimension sizes
SELECT test_return_array_text('[["a","bcd","ef"],[None,"gh","ijklm","ERROR"]]');
ERROR: Multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length 4 while expected 3 (plpython.c:4865)
CONTEXT: while creating return value
PL/Python function "test_return_array_text"
SELECT * FROM test_return_array_text('[["a","bcd","ef"],[None,"gh","ijklm","ERROR"]]');
ERROR: Multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length 4 while expected 3 (plpython.c:4865)
CONTEXT: while creating return value
PL/Python function "test_return_array_text"
-- Multi-dimensional array with mix of arrays and atomic elements
SELECT test_return_array_text('[[["a"],"b"],["c",["d","e"]]]');
ERROR: Multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length 2 while expected 1 (plpython.c:4865)
CONTEXT: while creating return value
PL/Python function "test_return_array_text"
SELECT * FROM test_return_array_text('[[["a"],"b"],["c",["d","e"]]]');
ERROR: Multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length 2 while expected 1 (plpython.c:4865)
CONTEXT: while creating return value
PL/Python function "test_return_array_text"
-- Multi-dimensional array with missing dimensions
SELECT test_return_array_text('[["abc","def"],None,["ghij","k"]]');
ERROR: Multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length -1 while expected 2 (plpython.c:4865)
DETAIL: TypeError: object of type 'NoneType' has no len()
CONTEXT: while creating return value
PL/Python function "test_return_array_text"
SELECT * FROM test_return_array_text('[["abc","def"],None,["ghij","k"]]');
ERROR: Multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length -1 while expected 2 (plpython.c:4865)
DETAIL: TypeError: object of type 'NoneType' has no len()
CONTEXT: while creating return value
PL/Python function "test_return_array_text"
-- =================================================== -- ===================================================
-- TEST 2: RETURN VALUE TESTING - SETOF scalar values -- TEST 2: RETURN VALUE TESTING - SETOF scalar values
-- =================================================== -- ===================================================
......
...@@ -726,88 +726,6 @@ SELECT * FROM test_type_conversion_bytea(null); ...@@ -726,88 +726,6 @@ SELECT * FROM test_type_conversion_bytea(null);
(1 row) (1 row)
-- 1-dimensional arrays
SELECT * FROM test_type_conversion_array_int4(array[1,2,null,3,4]::int4[]);
test_type_conversion_array_int4
---------------------------------
{1,2,NULL,3,4}
(1 row)
SELECT * FROM test_type_conversion_array_int4(null);
test_type_conversion_array_int4
---------------------------------
(1 row)
SELECT * FROM test_type_conversion_array_numeric(array[null,1.23,2.34,3.45,null]::numeric[]);
test_type_conversion_array_numeric
------------------------------------
{NULL,1.23,2.34,3.45,NULL}
(1 row)
SELECT * FROM test_type_conversion_array_text(array['abc','def','ghij',null]::text[]);
test_type_conversion_array_text
---------------------------------
{abc,def,ghij,NULL}
(1 row)
SELECT * FROM test_type_conversion_array_text(null);
test_type_conversion_array_text
---------------------------------
(1 row)
-- Multi-dimensional arrays
SELECT a, array_dims(a) FROM test_type_conversion_array_int4(array[
array[1,2,3,4], array[5,null,7,8], array[null,null,11,12]
]::int4[]) as a;
a | array_dims
--------------------------------------------+------------
{{1,2,3,4},{5,NULL,7,8},{NULL,NULL,11,12}} | [1:3][1:4]
(1 row)
SELECT a, array_dims(a) FROM test_type_conversion_array_int4(array[
array[ array[1,2,3,4], array[5,null,7,8], array[null,null,11,12] ],
array[ array[13,null,15,16], array[17,18,19,20], array[null,null,23,null] ],
array[ array[25,26,27,null], array[29,null,null,32], array[null,null,null,null] ]
]::int4[]) as a;
a | array_dims
------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------
{{{1,2,3,4},{5,NULL,7,8},{NULL,NULL,11,12}},{{13,NULL,15,16},{17,18,19,20},{NULL,NULL,23,NULL}},{{25,26,27,NULL},{29,NULL,NULL,32},{NULL,NULL,NULL,NULL}}} | [1:3][1:3][1:4]
(1 row)
SELECT a, array_dims(a) FROM test_type_conversion_array_numeric(array[
array[null,1.23,2.34,3.45,null],
array[4.56,5.67,null,null,6.78]
]::numeric[]) as a;
a | array_dims
---------------------------------------------------------+------------
{{NULL,1.23,2.34,3.45,NULL},{4.56,5.67,NULL,NULL,6.78}} | [1:2][1:5]
(1 row)
SELECT a, array_dims(a) FROM test_type_conversion_array_text(array[
array['abc','def','ghij',null],
array[null,'kl','mnopq','rst'],
array['uvw','',null,'xyz']
]::text[]) as a;
a | array_dims
-------------------------------------------------------------+------------
{{abc,def,ghij,NULL},{NULL,kl,mnopq,rst},{uvw,"",NULL,xyz}} | [1:3][1:4]
(1 row)
SELECT a, array_dims(a) FROM test_type_conversion_array_text(array[
array[ array['abc','def','ghij',null],
array[null,'kl','mnopq','rst'],
array['uvw','',null,'xyz'] ],
array[ array['A','BCD',null,'EFG'],
array[null,'HIJK','LMN','OPQR'],
array['STUV','WXYZ',null,null] ]
]::text[]) as a;
a | array_dims
-----------------------------------------------------------------------------------------------------------------------------+-----------------
{{{abc,def,ghij,NULL},{NULL,kl,mnopq,rst},{uvw,"",NULL,xyz}},{{A,BCD,NULL,EFG},{NULL,HIJK,LMN,OPQR},{STUV,WXYZ,NULL,NULL}}} | [1:2][1:3][1:4]
(1 row)
SELECT test_type_unmarshal(x) FROM test_type_marshal() x; SELECT test_type_unmarshal(x) FROM test_type_marshal() x;
test_type_unmarshal test_type_unmarshal
--------------------- ---------------------
......
...@@ -2552,111 +2552,62 @@ PLyList_FromArray(PLyDatumToOb *arg, Datum d) ...@@ -2552,111 +2552,62 @@ PLyList_FromArray(PLyDatumToOb *arg, Datum d)
{ {
ArrayType *array = DatumGetArrayTypeP(d); ArrayType *array = DatumGetArrayTypeP(d);
PLyDatumToOb *elm = arg->elm; PLyDatumToOb *elm = arg->elm;
int ndim; PyObject *list;
int *dims; int length;
int *lb; int lbound;
char *dataptr;
bits8 *bitmap;
int bitmask;
int i; int i;
int dim; char *dataptr;
int indx[MAXDIM]; bits8 *bitmap;
PyObject *lists[MAXDIM]; int bitmask;
if (ARR_NDIM(array) == 0) if (ARR_NDIM(array) == 0)
return PyList_New(0); return PyList_New(0);
/* Array dimensions and left bounds */ if (ARR_NDIM(array) != 1)
ndim = ARR_NDIM(array); ereport(ERROR,
dims = ARR_DIMS(array); (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
lb = ARR_LBOUND(array); errmsg("cannot convert multidimensional array to Python list"),
errdetail("PL/Python only supports one-dimensional arrays.")));
length = ARR_DIMS(array)[0];
lbound = ARR_LBOUND(array)[0];
list = PyList_New(length);
/* Internal array representation pointers */
dataptr = ARR_DATA_PTR(array); dataptr = ARR_DATA_PTR(array);
bitmap = ARR_NULLBITMAP(array); bitmap = ARR_NULLBITMAP(array);
bitmask = 1; bitmask = 1;
/* Iterators initialization */ for (i = 0; i < length; i++)
for (i = 0; i < ndim; i++) {
indx[i] = lb[i];
lists[i] = NULL;
}
lists[0] = PyList_New(dims[0]);
/* We need this incref to keep the pointer valid after the array traversal
* terminates, as this traversal does DECREF for all the lists in array */
Py_INCREF(lists[0]);
/* In this cycle we are going over array dimensions. Postgres offers you an
* option to iterate over all the multi-dimensional array elemens in order.
* For 3-dimesnional array the order of iteration would be following - first
* you start with [0,0,0] elements through [0,0,k], then [0,1,0] till [0,1,k]
* till [0,m,k], then [1,0,0] till [1,0,k] till [1,m,k], and so on.
* In Python, each 1-d array is a separate list object, so 3-d array of
* [n,m,k] element is a list of n m-element arrays, each element of which is
* k-element array. In this cycle we traverse from outter dimensions to
* inner ones, creating nested Python lists during traversal */
dim = 0;
while (dim >= 0)
{ {
/* If we finished up iterating over current dimension - go one level up */ /* Get source element, checking for NULL */
if (indx[dim] > dims[dim]) if (bitmap && (*bitmap & bitmask) == 0)
{ {
Py_DECREF(lists[dim]); Py_INCREF(Py_None);
indx[dim] = 0; PyList_SET_ITEM(list, i, Py_None);
dim -= 1;
} }
/* If we are processing inner dimension - create one more list */ else
else if (dim < ndim - 1)
{ {
lists[dim+1] = PyList_New(dims[dim+1]); Datum itemvalue;
/* We need this INCREF as we keep array pointer on our side,
* while PyList_SET_ITEM steals the reference */
Py_INCREF(lists[dim+1]);
PyList_SET_ITEM(lists[dim], indx[dim] - lb[dim], lists[dim+1]); itemvalue = fetch_att(dataptr, elm->typbyval, elm->typlen);
indx[dim] += 1; PyList_SET_ITEM(list, i, elm->func(elm, itemvalue));
dim += 1; dataptr = att_addlength_pointer(dataptr, elm->typlen, dataptr);
indx[dim] = lb[dim]; dataptr = (char *) att_align_nominal(dataptr, elm->typalign);
} }
/* If we are iterating over the outter dimension, fill the list with
* values from the original Postgres array */ /* advance bitmap pointer if any */
else if (dim == ndim - 1) if (bitmap)
{ {
for (indx[dim] = lb[dim]; indx[dim] <= dims[dim]; indx[dim]++) bitmask <<= 1;
if (bitmask == 0x100 /* (1<<8) */)
{ {
/* checking for NULL */ bitmap++;
if (bitmap && (*bitmap & bitmask) == 0) bitmask = 1;
{
Py_INCREF(Py_None);
PyList_SET_ITEM(lists[dim], indx[dim] - lb[dim], Py_None);
}
else
{
Datum itemvalue;
itemvalue = fetch_att(dataptr, elm->typbyval, elm->typlen);
PyList_SET_ITEM(lists[dim], indx[dim] - lb[dim], elm->func(elm, itemvalue));
dataptr = att_addlength_pointer(dataptr, elm->typlen, dataptr);
dataptr = (char *) att_align_nominal(dataptr, elm->typalign);
}
/* advance bitmap pointer if any */
if (bitmap)
{
bitmask <<= 1;
if (bitmask == 0x100 /* (1<<8) */)
{
bitmap++;
bitmask = 1;
}
}
} }
} }
} }
return lists[0]; return list;
} }
static PyObject * static PyObject *
...@@ -2905,116 +2856,39 @@ PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv) ...@@ -2905,116 +2856,39 @@ PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
Datum *elems; Datum *elems;
bool *nulls; bool *nulls;
int len; int len;
PyObject *pyptr; int lbs;
int ndim;
int dims[MAXDIM];
int lbs[MAXDIM];
int indx[MAXDIM];
PyObject *stack[MAXDIM];
int dim;
int idxelem;
Assert(plrv != Py_None); Assert(plrv != Py_None);
if (!PySequence_Check(plrv)) if (!PySequence_Check(plrv))
PLy_elog(ERROR, "return value of function with array return type is not a Python sequence"); PLy_elog(ERROR, "return value of function with array return type is not a Python sequence");
pyptr = plrv; len = PySequence_Length(plrv);
ndim = 0;
len = 1;
/* We want to iterate through all iterable objects except by strings */
while (pyptr != NULL && PySequence_Check(pyptr) &&
!(PyString_Check(pyptr) || PyBytes_Check(pyptr) || PyUnicode_Check(pyptr))) {
dims[ndim] = PySequence_Length(pyptr);
if (dims[ndim] < 0)
PLy_elog(ERROR, "Cannot determine sequence length for function return value");
len *= dims[ndim];
stack[ndim] = pyptr;
ndim += 1;
if (dims[ndim - 1] == 0) {
pyptr = NULL;
break;
}
pyptr = PySequence_GetItem(pyptr, 0);
}
/* Pyptr points to element of n-dimensional array, we don't need its reference */
Py_XDECREF(pyptr);
/* We need this incref to keep the pointer valid after the array traversal
* terminates, as this traversal does DECREF for all the lists in array, and
* stack[0] corresponds to function return value */
Py_INCREF(stack[0]);
elems = palloc(sizeof(*elems) * len); elems = palloc(sizeof(*elems) * len);
nulls = palloc(sizeof(*nulls) * len); nulls = palloc(sizeof(*nulls) * len);
for (i = 0; i < ndim; i++) { for (i = 0; i < len; i++)
indx[i] = 0;
lbs[i] = 1;
}
/* In this cycle we are going over nested Python lists, fetching elements
* from the deepest level and putting them into a linear array for Postgres
* to interpret them as n-dimensional array. This is a cycle implementation
* of DFS (recursive traversal of nested arrays here), keeping the stack in
* "stack" variable */
dim = 0;
idxelem = 0;
while (dim >= 0)
{ {
/* If we finished up iterating over current list - go one level up */ PyObject *obj = PySequence_GetItem(plrv, i);
if (indx[dim] == dims[dim])
{
Py_DECREF(stack[dim]);
indx[dim] = 0;
dim -= 1;
}
/* If we are processing inner list - create one more list */
else if (dim < ndim - 1)
{
stack[dim+1] = PySequence_GetItem(stack[dim], indx[dim]);
if (PySequence_Length(stack[dim+1]) != dims[dim+1])
PLy_elog(ERROR, "Multidimensional arrays must have array expressions with matching dimensions. "
"PL/Python function return value has sequence length %d while expected %d",
(int)PySequence_Length(stack[dim+1]), dims[dim+1]);
indx[dim] += 1;
dim += 1;
}
/* If we are iterating over the outter list, fill the output array */
else if (dim == ndim - 1)
{
for (indx[dim] = 0; indx[dim] < dims[dim]; indx[dim]++) {
PyObject *obj = PySequence_GetItem(stack[dim], indx[dim]);
if (obj == Py_None) if (obj == Py_None)
nulls[idxelem] = true; nulls[i] = true;
else else
{ {
nulls[idxelem] = false; nulls[i] = false;
/* /*
* We don't support arrays of row types yet, so the first argument * We don't support arrays of row types yet, so the first argument
* can be NULL. * can be NULL.
*/ */
elems[idxelem] = arg->elm->func(arg->elm, -1, obj); elems[i] = arg->elm->func(arg->elm, -1, obj);
}
Py_XDECREF(obj);
idxelem += 1;
}
} }
Py_XDECREF(obj);
} }
array = construct_md_array(elems, lbs = 1;
nulls, array = construct_md_array(elems, nulls, 1, &len, &lbs,
ndim, get_element_type(arg->typoid), arg->elm->typlen, arg->elm->typbyval, arg->elm->typalign);
dims,
lbs,
get_element_type(arg->typoid),
arg->elm->typlen,
arg->elm->typbyval,
arg->elm->typalign);
return PointerGetDatum(array); return PointerGetDatum(array);
} }
......
...@@ -576,9 +576,6 @@ CREATE FUNCTION test_type_conversion_float8(x float8) returns float8 AS $$ retur ...@@ -576,9 +576,6 @@ CREATE FUNCTION test_type_conversion_float8(x float8) returns float8 AS $$ retur
CREATE FUNCTION test_type_conversion_numeric(x numeric) returns numeric AS $$ return x $$ language plpythonu; CREATE FUNCTION test_type_conversion_numeric(x numeric) returns numeric AS $$ return x $$ language plpythonu;
CREATE FUNCTION test_type_conversion_text(x text) returns text AS $$ return x $$ language plpythonu; CREATE FUNCTION test_type_conversion_text(x text) returns text AS $$ return x $$ language plpythonu;
CREATE FUNCTION test_type_conversion_bytea(x bytea) returns bytea AS $$ return x $$ language plpythonu; CREATE FUNCTION test_type_conversion_bytea(x bytea) returns bytea AS $$ return x $$ language plpythonu;
CREATE FUNCTION test_type_conversion_array_int4(x int4[]) RETURNS int4[] AS $$ return x $$ LANGUAGE plpythonu;
CREATE FUNCTION test_type_conversion_array_numeric(x numeric[]) returns numeric[] AS $$ return x $$ language plpythonu;
CREATE FUNCTION test_type_conversion_array_text(x text[]) RETURNS text[] AS $$ return x $$ LANGUAGE plpythonu;
CREATE FUNCTION test_type_marshal() returns bytea AS $$ CREATE FUNCTION test_type_marshal() returns bytea AS $$
import marshal import marshal
return marshal.dumps('hello world') return marshal.dumps('hello world')
...@@ -614,16 +611,6 @@ RETURNS circle AS $$ ...@@ -614,16 +611,6 @@ RETURNS circle AS $$
exec('y = ' + s) exec('y = ' + s)
return y return y
$$ language plpythonu; $$ language plpythonu;
CREATE FUNCTION test_return_array_int(s text)
RETURNS int[] AS $$
exec('y = ' + s)
return y
$$ language plpythonu;
CREATE FUNCTION test_return_array_text(s text)
RETURNS text[] AS $$
exec('y = ' + s)
return y
$$ language plpythonu;
CREATE FUNCTION test_return_setof_void(s text) CREATE FUNCTION test_return_setof_void(s text)
RETURNS setof void AS $$ RETURNS setof void AS $$
exec('y = ' + s) exec('y = ' + s)
......
...@@ -356,77 +356,6 @@ SELECT * FROM test_return_circle('{None: None}'); ...@@ -356,77 +356,6 @@ SELECT * FROM test_return_circle('{None: None}');
SELECT test_return_circle(E'"test\\0"'); SELECT test_return_circle(E'"test\\0"');
SELECT * FROM test_return_circle(E'"test\\0"'); SELECT * FROM test_return_circle(E'"test\\0"');
--
-- Case 5: Return array of integers
--
-- Test returning arrays of fixed-width elements from PL/Python functions
--
-- From Python None
SELECT test_return_array_int('None');
SELECT * FROM test_return_array_int('None');
-- From Python empty list
SELECT test_return_array_int('[]');
SELECT * FROM test_return_array_int('[]');
-- From Python non-empty list
SELECT test_return_array_int('[1,2]');
SELECT * FROM test_return_array_int('[1,2]');
-- From Python multiple lists
SELECT test_return_array_int('[[1,2,3],[4,5,6]]');
SELECT * FROM test_return_array_int('[[1,2,3],[4,5,6]]');
-- Error conditions
-- Multi-dimensional array with non-fixed dimension sizes
SELECT test_return_array_int('[[1,2,3],[1,2]]');
SELECT * FROM test_return_array_int('[[1,2,3],[1,2]]');
-- Multi-dimensional array with mix of arrays and atomic elements
SELECT test_return_array_int('[[1,2,3],[1,[2,3],[4,5]]]');
SELECT * FROM test_return_array_int('[[1,2,3],[1,[2,3],[4,5]]]');
-- Multi-dimensional array with missing dimensions
SELECT test_return_array_int('[[1,2,3],None,[4,5,6]]');
SELECT * FROM test_return_array_int('[[1,2,3],None,[4,5,6]]');
--
-- Case 5: Return array of texts
--
-- Test returning arrays of variable-width elements from PL/Python functions
--
-- From Python None
SELECT test_return_array_text('None');
SELECT * FROM test_return_array_text('None');
-- From Python empty list
SELECT test_return_array_text('[]');
SELECT * FROM test_return_array_text('[]');
-- From Python non-empty list
SELECT test_return_array_text('["abc","def"]');
SELECT * FROM test_return_array_text('["abc","def"]');
-- From Python multiple lists
SELECT test_return_array_text('[["a","bcd","ef"],[None,"gh","ijklm"]]');
SELECT * FROM test_return_array_text('[["a","bcd","ef"],[None,"gh","ijklm"]]');
-- Error conditions
-- Multi-dimensional array with non-fixed dimension sizes
SELECT test_return_array_text('[["a","bcd","ef"],[None,"gh","ijklm","ERROR"]]');
SELECT * FROM test_return_array_text('[["a","bcd","ef"],[None,"gh","ijklm","ERROR"]]');
-- Multi-dimensional array with mix of arrays and atomic elements
SELECT test_return_array_text('[[["a"],"b"],["c",["d","e"]]]');
SELECT * FROM test_return_array_text('[[["a"],"b"],["c",["d","e"]]]');
-- Multi-dimensional array with missing dimensions
SELECT test_return_array_text('[["abc","def"],None,["ghij","k"]]');
SELECT * FROM test_return_array_text('[["abc","def"],None,["ghij","k"]]');
-- =================================================== -- ===================================================
-- TEST 2: RETURN VALUE TESTING - SETOF scalar values -- TEST 2: RETURN VALUE TESTING - SETOF scalar values
......
...@@ -187,39 +187,6 @@ SELECT * FROM test_type_conversion_text('hello world'); ...@@ -187,39 +187,6 @@ SELECT * FROM test_type_conversion_text('hello world');
SELECT * FROM test_type_conversion_text(null); SELECT * FROM test_type_conversion_text(null);
SELECT * FROM test_type_conversion_bytea('hello world'); SELECT * FROM test_type_conversion_bytea('hello world');
SELECT * FROM test_type_conversion_bytea(null); SELECT * FROM test_type_conversion_bytea(null);
-- 1-dimensional arrays
SELECT * FROM test_type_conversion_array_int4(array[1,2,null,3,4]::int4[]);
SELECT * FROM test_type_conversion_array_int4(null);
SELECT * FROM test_type_conversion_array_numeric(array[null,1.23,2.34,3.45,null]::numeric[]);
SELECT * FROM test_type_conversion_array_text(array['abc','def','ghij',null]::text[]);
SELECT * FROM test_type_conversion_array_text(null);
-- Multi-dimensional arrays
SELECT a, array_dims(a) FROM test_type_conversion_array_int4(array[
array[1,2,3,4], array[5,null,7,8], array[null,null,11,12]
]::int4[]) as a;
SELECT a, array_dims(a) FROM test_type_conversion_array_int4(array[
array[ array[1,2,3,4], array[5,null,7,8], array[null,null,11,12] ],
array[ array[13,null,15,16], array[17,18,19,20], array[null,null,23,null] ],
array[ array[25,26,27,null], array[29,null,null,32], array[null,null,null,null] ]
]::int4[]) as a;
SELECT a, array_dims(a) FROM test_type_conversion_array_numeric(array[
array[null,1.23,2.34,3.45,null],
array[4.56,5.67,null,null,6.78]
]::numeric[]) as a;
SELECT a, array_dims(a) FROM test_type_conversion_array_text(array[
array['abc','def','ghij',null],
array[null,'kl','mnopq','rst'],
array['uvw','',null,'xyz']
]::text[]) as a;
SELECT a, array_dims(a) FROM test_type_conversion_array_text(array[
array[ array['abc','def','ghij',null],
array[null,'kl','mnopq','rst'],
array['uvw','',null,'xyz'] ],
array[ array['A','BCD',null,'EFG'],
array[null,'HIJK','LMN','OPQR'],
array['STUV','WXYZ',null,null] ]
]::text[]) as a;
SELECT test_type_unmarshal(x) FROM test_type_marshal() x; SELECT test_type_unmarshal(x) FROM test_type_marshal() x;
SELECT (split(10)).*; SELECT (split(10)).*;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册