Handle domains over arrays like plain arrays in PL/python.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 26 Nov 2013 12:22:38 +0000 (14:22 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 26 Nov 2013 12:33:31 +0000 (14:33 +0200)
Domains over arrays are now converted to/from python lists when passed as
arguments or return values. Like regular arrays.

This has some potential to break applications that rely on the old behavior
that they are passed as strings, but in practice there probably aren't many
such applications out there.

Rodolfo Campero

src/pl/plpython/expected/plpython_types.out
src/pl/plpython/expected/plpython_types_3.out
src/pl/plpython/plpy_typeio.c
src/pl/plpython/sql/plpython_types.sql

index 91106e04550b274ef9e4d7903b54b2b9f0325191..785ffca9cd8f78ffda13a67f53a80ec2f47b985a 100644 (file)
@@ -664,6 +664,34 @@ SELECT * FROM test_type_conversion_array_error();
 ERROR:  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"
+CREATE DOMAIN ordered_pair_domain AS integer[] CHECK (array_length(VALUE,1)=2 AND VALUE[1] < VALUE[2]);
+CREATE FUNCTION test_type_conversion_array_domain(x ordered_pair_domain) RETURNS ordered_pair_domain AS $$
+plpy.info(x, type(x))
+return x
+$$ LANGUAGE plpythonu;
+SELECT * FROM test_type_conversion_array_domain(ARRAY[0, 100]::ordered_pair_domain);
+INFO:  ([0, 100], <type 'list'>)
+CONTEXT:  PL/Python function "test_type_conversion_array_domain"
+ test_type_conversion_array_domain 
+-----------------------------------
+ {0,100}
+(1 row)
+
+SELECT * FROM test_type_conversion_array_domain(NULL::ordered_pair_domain);
+INFO:  (None, <type 'NoneType'>)
+CONTEXT:  PL/Python function "test_type_conversion_array_domain"
+ test_type_conversion_array_domain 
+-----------------------------------
+(1 row)
+
+CREATE FUNCTION test_type_conversion_array_domain_check_violation() RETURNS ordered_pair_domain AS $$
+return [2,1]
+$$ LANGUAGE plpythonu;
+SELECT * FROM test_type_conversion_array_domain_check_violation();
+ERROR:  value for domain ordered_pair_domain violates check constraint "ordered_pair_domain_check"
+CONTEXT:  while creating return value
+PL/Python function "test_type_conversion_array_domain_check_violation"
 ---
 --- Composite types
 ---
index 523c2ecda23711c08bbec8cc573ef79233d4dc03..25331f268a1e456a484ccba328198eed2cd87313 100644 (file)
@@ -664,6 +664,34 @@ SELECT * FROM test_type_conversion_array_error();
 ERROR:  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"
+CREATE DOMAIN ordered_pair_domain AS integer[] CHECK (array_length(VALUE,1)=2 AND VALUE[1] < VALUE[2]);
+CREATE FUNCTION test_type_conversion_array_domain(x ordered_pair_domain) RETURNS ordered_pair_domain AS $$
+plpy.info(x, type(x))
+return x
+$$ LANGUAGE plpython3u;
+SELECT * FROM test_type_conversion_array_domain(ARRAY[0, 100]::ordered_pair_domain);
+INFO:  ([0, 100], <class 'list'>)
+CONTEXT:  PL/Python function "test_type_conversion_array_domain"
+ test_type_conversion_array_domain 
+-----------------------------------
+ {0,100}
+(1 row)
+
+SELECT * FROM test_type_conversion_array_domain(NULL::ordered_pair_domain);
+INFO:  (None, <class 'NoneType'>)
+CONTEXT:  PL/Python function "test_type_conversion_array_domain"
+ test_type_conversion_array_domain 
+-----------------------------------
+(1 row)
+
+CREATE FUNCTION test_type_conversion_array_domain_check_violation() RETURNS ordered_pair_domain AS $$
+return [2,1]
+$$ LANGUAGE plpython3u;
+SELECT * FROM test_type_conversion_array_domain_check_violation();
+ERROR:  value for domain ordered_pair_domain violates check constraint "ordered_pair_domain_check"
+CONTEXT:  while creating return value
+PL/Python function "test_type_conversion_array_domain_check_violation"
 ---
 --- Composite types
 ---
index caccbf9b88ff6e373e5f1a2858e2a56ae4f60275..0a2307abdb98306a703b9b343f52e08126c87de7 100644 (file)
@@ -373,7 +373,7 @@ PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup)
    arg->typioparam = getTypeIOParam(typeTup);
    arg->typbyval = typeStruct->typbyval;
 
-   element_type = get_element_type(arg->typoid);
+   element_type = get_base_element_type(arg->typoid);
 
    /*
     * Select a conversion function to convert Python objects to PostgreSQL
@@ -427,7 +427,8 @@ static void
 PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup)
 {
    Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
-   Oid         element_type = get_element_type(typeOid);
+   /* It's safe to handle domains of array types as its base array type. */
+   Oid         element_type = get_base_element_type(typeOid);
 
    /* Get the type's conversion information */
    perm_fmgr_info(typeStruct->typoutput, &arg->typfunc);
@@ -808,6 +809,7 @@ static Datum
 PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
 {
    ArrayType  *array;
+   Datum       rv;
    int         i;
    Datum      *elems;
    bool       *nulls;
@@ -844,8 +846,15 @@ PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
 
    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);
+                              get_base_element_type(arg->typoid), arg->elm->typlen, arg->elm->typbyval, arg->elm->typalign);
+   /*
+    * If the result type is a domain of array, the resulting array must be
+    * checked.
+    */
+   rv = PointerGetDatum(array);
+   if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
+       domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
+   return rv;
 }
 
 
index e63d07e1f9aeec09e935dd7ee9528cd5ced7736a..ee6b0e9e981d4f8615f99a34198ed6d81bb6b9ff 100644 (file)
@@ -294,6 +294,26 @@ $$ LANGUAGE plpythonu;
 SELECT * FROM test_type_conversion_array_error();
 
 
+--
+-- Domains over arrays
+--
+
+CREATE DOMAIN ordered_pair_domain AS integer[] CHECK (array_length(VALUE,1)=2 AND VALUE[1] < VALUE[2]);
+
+CREATE FUNCTION test_type_conversion_array_domain(x ordered_pair_domain) RETURNS ordered_pair_domain AS $$
+plpy.info(x, type(x))
+return x
+$$ LANGUAGE plpythonu;
+
+SELECT * FROM test_type_conversion_array_domain(ARRAY[0, 100]::ordered_pair_domain);
+SELECT * FROM test_type_conversion_array_domain(NULL::ordered_pair_domain);
+
+CREATE FUNCTION test_type_conversion_array_domain_check_violation() RETURNS ordered_pair_domain AS $$
+return [2,1]
+$$ LANGUAGE plpythonu;
+SELECT * FROM test_type_conversion_array_domain_check_violation();
+
+
 ---
 --- Composite types
 ---