Fix broken ruleutils support for function TRANSFORM clauses.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 25 Jan 2021 18:03:11 +0000 (13:03 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 25 Jan 2021 18:03:43 +0000 (13:03 -0500)
I chanced to notice that this dumped core due to a faulty Assert.
To add insult to injury, the output has been misformatted since v11.
Obviously we need some regression testing here.

Discussion: https://postgr.es/m/d1cc628c-3953-4209-957b-29427acc38c8@www.fastmail.com

contrib/bool_plperl/expected/bool_plperl.out
contrib/bool_plperl/expected/bool_plperlu.out
contrib/bool_plperl/sql/bool_plperl.sql
contrib/bool_plperl/sql/bool_plperlu.sql
contrib/hstore_plpython/expected/hstore_plpython.out
contrib/hstore_plpython/sql/hstore_plpython.sql
src/backend/utils/adt/ruleutils.c
src/backend/utils/fmgr/funcapi.c

index 84c25acdb4f83446948674181c7c15d92b6b8a02..187df8db96f9ee1de3074369ace8f2ba0823f131 100644 (file)
@@ -52,7 +52,7 @@ SELECT perl2undef() IS NULL AS p;
 --- test transforming to perl
 CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void
 LANGUAGE plperl
-TRANSFORM FOR TYPE bool
+TRANSFORM FOR TYPE bool, for type boolean  -- duplicate to test ruleutils
 AS $$
 my ($x, $y, $z) = @_;
 
@@ -68,6 +68,21 @@ SELECT bool2perl (true, false, NULL);
  
 (1 row)
 
+--- test ruleutils
+\sf bool2perl
+CREATE OR REPLACE FUNCTION public.bool2perl(boolean, boolean, boolean)
+ RETURNS void
+ TRANSFORM FOR TYPE boolean, FOR TYPE boolean
+ LANGUAGE plperl
+AS $function$
+my ($x, $y, $z) = @_;
+
+die("NULL mistransformed") if (defined($z));
+die("TRUE mistransformed to UNDEF") if (!defined($x));
+die("FALSE mistransformed to UNDEF") if (!defined($y));
+die("TRUE mistransformed") if (!$x);
+die("FALSE mistransformed") if ($y);
+$function$
 --- test selecting bool through SPI
 CREATE FUNCTION spi_test()  RETURNS void
 LANGUAGE plperl
index 745ba98933862d4b1774a1d2d90fdf5406ed17f3..8337d337e992efaf668989f03498f3d2f95a40a6 100644 (file)
@@ -52,7 +52,7 @@ SELECT perl2undef() IS NULL AS p;
 --- test transforming to perl
 CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void
 LANGUAGE plperlu
-TRANSFORM FOR TYPE bool
+TRANSFORM FOR TYPE bool, for type boolean  -- duplicate to test ruleutils
 AS $$
 my ($x, $y, $z) = @_;
 
@@ -68,6 +68,21 @@ SELECT bool2perl (true, false, NULL);
  
 (1 row)
 
+--- test ruleutils
+\sf bool2perl
+CREATE OR REPLACE FUNCTION public.bool2perl(boolean, boolean, boolean)
+ RETURNS void
+ TRANSFORM FOR TYPE boolean, FOR TYPE boolean
+ LANGUAGE plperlu
+AS $function$
+my ($x, $y, $z) = @_;
+
+die("NULL mistransformed") if (defined($z));
+die("TRUE mistransformed to UNDEF") if (!defined($x));
+die("FALSE mistransformed to UNDEF") if (!defined($y));
+die("TRUE mistransformed") if (!$x);
+die("FALSE mistransformed") if ($y);
+$function$
 --- test selecting bool through SPI
 CREATE FUNCTION spi_test()  RETURNS void
 LANGUAGE plperlu
index dd99f545ea98e5237cb5d00c9d1d73a1f5c21d25..b7f570862cee524884b49b6e5adfdf73cc0d39a6 100644 (file)
@@ -33,7 +33,7 @@ SELECT perl2undef() IS NULL AS p;
 
 CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void
 LANGUAGE plperl
-TRANSFORM FOR TYPE bool
+TRANSFORM FOR TYPE bool, for type boolean  -- duplicate to test ruleutils
 AS $$
 my ($x, $y, $z) = @_;
 
@@ -46,6 +46,10 @@ $$;
 
 SELECT bool2perl (true, false, NULL);
 
+--- test ruleutils
+
+\sf bool2perl
+
 --- test selecting bool through SPI
 
 CREATE FUNCTION spi_test()  RETURNS void
index b756b0be676854ed13632c94cebc20f002df1c06..1480a0433067a3c40ba328a6f39c57d549e87807 100644 (file)
@@ -33,7 +33,7 @@ SELECT perl2undef() IS NULL AS p;
 
 CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void
 LANGUAGE plperlu
-TRANSFORM FOR TYPE bool
+TRANSFORM FOR TYPE bool, for type boolean  -- duplicate to test ruleutils
 AS $$
 my ($x, $y, $z) = @_;
 
@@ -46,6 +46,10 @@ $$;
 
 SELECT bool2perl (true, false, NULL);
 
+--- test ruleutils
+
+\sf bool2perl
+
 --- test selecting bool through SPI
 
 CREATE FUNCTION spi_test()  RETURNS void
index 1ab5feea93d79fe426d0b5b19d79a4ef445c8da6..ecf1dd61bc17f9ec99ca5538b454de5d9e54900a 100644 (file)
@@ -47,19 +47,29 @@ SELECT test1arr(array['aa=>bb, cc=>NULL'::hstore, 'dd=>ee']);
 (1 row)
 
 -- test python -> hstore
-CREATE FUNCTION test2() RETURNS hstore
+CREATE FUNCTION test2(a int, b text) RETURNS hstore
 LANGUAGE plpythonu
 TRANSFORM FOR TYPE hstore
 AS $$
-val = {'a': 1, 'b': 'boo', 'c': None}
+val = {'a': a, 'b': b, 'c': None}
 return val
 $$;
-SELECT test2();
+SELECT test2(1, 'boo');
               test2              
 ---------------------------------
  "a"=>"1", "b"=>"boo", "c"=>NULL
 (1 row)
 
+--- test ruleutils
+\sf test2
+CREATE OR REPLACE FUNCTION public.test2(a integer, b text)
+ RETURNS hstore
+ TRANSFORM FOR TYPE hstore
+ LANGUAGE plpythonu
+AS $function$
+val = {'a': a, 'b': b, 'c': None}
+return val
+$function$
 -- test python -> hstore[]
 CREATE FUNCTION test2arr() RETURNS hstore[]
 LANGUAGE plpythonu
index 2c54ee6aaad264be8ceb28ff9bcd7e4e2d31c568..b6d98b7dd5371df8a2ac1fb04a7e7a2490b00e5b 100644 (file)
@@ -40,15 +40,18 @@ SELECT test1arr(array['aa=>bb, cc=>NULL'::hstore, 'dd=>ee']);
 
 
 -- test python -> hstore
-CREATE FUNCTION test2() RETURNS hstore
+CREATE FUNCTION test2(a int, b text) RETURNS hstore
 LANGUAGE plpythonu
 TRANSFORM FOR TYPE hstore
 AS $$
-val = {'a': 1, 'b': 'boo', 'c': None}
+val = {'a': a, 'b': b, 'c': None}
 return val
 $$;
 
-SELECT test2();
+SELECT test2(1, 'boo');
+
+--- test ruleutils
+\sf test2
 
 
 -- test python -> hstore[]
index 8a1fbda57227e2f40a80963851c79d2f681c9dc9..1a844bc4613f9eb140ea3cd8ce08588a0b6f3564 100644 (file)
@@ -3126,13 +3126,14 @@ print_function_trftypes(StringInfo buf, HeapTuple proctup)
    {
        int         i;
 
-       appendStringInfoString(buf, "\n TRANSFORM ");
+       appendStringInfoString(buf, " TRANSFORM ");
        for (i = 0; i < ntypes; i++)
        {
            if (i != 0)
                appendStringInfoString(buf, ", ");
            appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
        }
+       appendStringInfoChar(buf, '\n');
    }
 }
 
index 2fd2e41f99b83ba983b4ac84bead0c1c53d3c4c4..717b62907c78e8baa808947a437ec19c98462dd2 100644 (file)
@@ -1357,7 +1357,9 @@ get_func_arg_info(HeapTuple procTup,
 /*
  * get_func_trftypes
  *
- * Returns the number of transformed types used by function.
+ * Returns the number of transformed types used by the function.
+ * If there are any, a palloc'd array of the type OIDs is returned
+ * into *p_trftypes.
  */
 int
 get_func_trftypes(HeapTuple procTup,
@@ -1386,7 +1388,6 @@ get_func_trftypes(HeapTuple procTup,
            ARR_HASNULL(arr) ||
            ARR_ELEMTYPE(arr) != OIDOID)
            elog(ERROR, "protrftypes is not a 1-D Oid array or it contains nulls");
-       Assert(nelems >= ((Form_pg_proc) GETSTRUCT(procTup))->pronargs);
        *p_trftypes = (Oid *) palloc(nelems * sizeof(Oid));
        memcpy(*p_trftypes, ARR_DATA_PTR(arr),
               nelems * sizeof(Oid));