diff --git a/src/pl/plpython/expected/plpython_function.out b/src/pl/plpython/expected/plpython_function.out index a9374a5650709b251df9a9a3ec37af58dd590291..72fa12ea39eb8d31d126ea4410c325e824896356 100755 --- a/src/pl/plpython/expected/plpython_function.out +++ b/src/pl/plpython/expected/plpython_function.out @@ -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_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_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 $$ import marshal return marshal.dumps('hello world') @@ -587,16 +584,6 @@ RETURNS circle AS $$ exec('y = ' + s) return y $$ 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) RETURNS setof void AS $$ exec('y = ' + s) diff --git a/src/pl/plpython/expected/plpython_returns.out b/src/pl/plpython/expected/plpython_returns.out index d2f86eb8b29fa2e23841d7191767d64d0cba0cf9..08806f927475c5a3207cdf4d854d2ccdf01e29c9 100644 --- a/src/pl/plpython/expected/plpython_returns.out +++ b/src/pl/plpython/expected/plpython_returns.out @@ -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 CONTEXT: while creating return value 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 -- =================================================== diff --git a/src/pl/plpython/expected/plpython_test.out b/src/pl/plpython/expected/plpython_test.out index fd895135b5419060441ff3f516df1150de53ee6b..57ba4dbb7de082f1d205f91d3fdb4ebb8b21535a 100755 --- a/src/pl/plpython/expected/plpython_test.out +++ b/src/pl/plpython/expected/plpython_test.out @@ -726,88 +726,6 @@ SELECT * FROM test_type_conversion_bytea(null); (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; test_type_unmarshal --------------------- diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index 3e8a92cbb3460e602de56cd420d30c46fffd8071..78c8303f71be03b0768492a1cda7415629ae20ac 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -2552,111 +2552,62 @@ PLyList_FromArray(PLyDatumToOb *arg, Datum d) { ArrayType *array = DatumGetArrayTypeP(d); PLyDatumToOb *elm = arg->elm; - int ndim; - int *dims; - int *lb; - char *dataptr; - bits8 *bitmap; - int bitmask; + PyObject *list; + int length; + int lbound; int i; - int dim; - int indx[MAXDIM]; - PyObject *lists[MAXDIM]; + char *dataptr; + bits8 *bitmap; + int bitmask; if (ARR_NDIM(array) == 0) return PyList_New(0); - /* Array dimensions and left bounds */ - ndim = ARR_NDIM(array); - dims = ARR_DIMS(array); - lb = ARR_LBOUND(array); + if (ARR_NDIM(array) != 1) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + 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); bitmap = ARR_NULLBITMAP(array); bitmask = 1; - /* Iterators initialization */ - 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) + for (i = 0; i < length; i++) { - /* If we finished up iterating over current dimension - go one level up */ - if (indx[dim] > dims[dim]) + /* Get source element, checking for NULL */ + if (bitmap && (*bitmap & bitmask) == 0) { - Py_DECREF(lists[dim]); - indx[dim] = 0; - dim -= 1; + Py_INCREF(Py_None); + PyList_SET_ITEM(list, i, Py_None); } - /* If we are processing inner dimension - create one more list */ - else if (dim < ndim - 1) + else { - lists[dim+1] = PyList_New(dims[dim+1]); - - /* We need this INCREF as we keep array pointer on our side, - * while PyList_SET_ITEM steals the reference */ - Py_INCREF(lists[dim+1]); + Datum itemvalue; - PyList_SET_ITEM(lists[dim], indx[dim] - lb[dim], lists[dim+1]); - indx[dim] += 1; - dim += 1; - indx[dim] = lb[dim]; + itemvalue = fetch_att(dataptr, elm->typbyval, elm->typlen); + PyList_SET_ITEM(list, i, elm->func(elm, itemvalue)); + dataptr = att_addlength_pointer(dataptr, elm->typlen, dataptr); + 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 */ - else if (dim == ndim - 1) + + /* advance bitmap pointer if any */ + if (bitmap) { - for (indx[dim] = lb[dim]; indx[dim] <= dims[dim]; indx[dim]++) + bitmask <<= 1; + if (bitmask == 0x100 /* (1<<8) */) { - /* checking for NULL */ - if (bitmap && (*bitmap & bitmask) == 0) - { - 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; - } - } + bitmap++; + bitmask = 1; } } } - return lists[0]; + return list; } static PyObject * @@ -2905,116 +2856,39 @@ PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv) Datum *elems; bool *nulls; int len; - PyObject *pyptr; - int ndim; - int dims[MAXDIM]; - int lbs[MAXDIM]; - int indx[MAXDIM]; - PyObject *stack[MAXDIM]; - int dim; - int idxelem; + int lbs; Assert(plrv != Py_None); if (!PySequence_Check(plrv)) PLy_elog(ERROR, "return value of function with array return type is not a Python sequence"); - pyptr = 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]); - + len = PySequence_Length(plrv); elems = palloc(sizeof(*elems) * len); nulls = palloc(sizeof(*nulls) * len); - for (i = 0; i < ndim; 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) + for (i = 0; i < len; i++) { - /* If we finished up iterating over current list - go one level up */ - 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]); + PyObject *obj = PySequence_GetItem(plrv, i); - if (obj == Py_None) - nulls[idxelem] = true; - else - { - nulls[idxelem] = false; + if (obj == Py_None) + nulls[i] = true; + else + { + nulls[i] = false; - /* - * We don't support arrays of row types yet, so the first argument - * can be NULL. - */ - elems[idxelem] = arg->elm->func(arg->elm, -1, obj); - } - Py_XDECREF(obj); - idxelem += 1; - } + /* + * We don't support arrays of row types yet, so the first argument + * can be NULL. + */ + elems[i] = arg->elm->func(arg->elm, -1, obj); } + Py_XDECREF(obj); } - array = construct_md_array(elems, - nulls, - ndim, - dims, - lbs, - get_element_type(arg->typoid), - arg->elm->typlen, - arg->elm->typbyval, - arg->elm->typalign); + lbs = 1; + array = construct_md_array(elems, nulls, 1, &len, &lbs, + get_element_type(arg->typoid), arg->elm->typlen, arg->elm->typbyval, arg->elm->typalign); return PointerGetDatum(array); } diff --git a/src/pl/plpython/sql/plpython_function.sql b/src/pl/plpython/sql/plpython_function.sql index c4bd43b03561695781f4d7c492260372ef99b898..d5f7ee1d131f718a08b61fb748393d6619952391 100644 --- a/src/pl/plpython/sql/plpython_function.sql +++ b/src/pl/plpython/sql/plpython_function.sql @@ -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_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_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 $$ import marshal return marshal.dumps('hello world') @@ -614,16 +611,6 @@ RETURNS circle AS $$ exec('y = ' + s) return y $$ 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) RETURNS setof void AS $$ exec('y = ' + s) diff --git a/src/pl/plpython/sql/plpython_returns.sql b/src/pl/plpython/sql/plpython_returns.sql index 6f82336a2bcaba603610d90f801f8b76ec5d3416..90f2dd98e89ee530de33095801c4d409fe4cf6c0 100644 --- a/src/pl/plpython/sql/plpython_returns.sql +++ b/src/pl/plpython/sql/plpython_returns.sql @@ -356,77 +356,6 @@ SELECT * FROM test_return_circle('{None: None}'); SELECT 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 diff --git a/src/pl/plpython/sql/plpython_test.sql b/src/pl/plpython/sql/plpython_test.sql index b22e6a360813a0ac4fb9358e89a7dcd1e2d93ae1..660a586c140030396c0992c4ee90c5ba9f3b0e63 100644 --- a/src/pl/plpython/sql/plpython_test.sql +++ b/src/pl/plpython/sql/plpython_test.sql @@ -187,39 +187,6 @@ SELECT * FROM test_type_conversion_text('hello world'); SELECT * FROM test_type_conversion_text(null); SELECT * FROM test_type_conversion_bytea('hello world'); 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 (split(10)).*;