Fix broken ruleutils support for function TRANSFORM clauses.

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
This commit is contained in:
Tom Lane 2021-01-25 13:03:11 -05:00
parent 652f7818bf
commit a26194f22b
8 changed files with 66 additions and 13 deletions

View File

@ -52,7 +52,7 @@ SELECT perl2undef() IS NULL AS p;
--- test transforming to perl --- test transforming to perl
CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void
LANGUAGE plperl LANGUAGE plperl
TRANSFORM FOR TYPE bool TRANSFORM FOR TYPE bool, for type boolean -- duplicate to test ruleutils
AS $$ AS $$
my ($x, $y, $z) = @_; my ($x, $y, $z) = @_;
@ -68,6 +68,21 @@ SELECT bool2perl (true, false, NULL);
(1 row) (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 --- test selecting bool through SPI
CREATE FUNCTION spi_test() RETURNS void CREATE FUNCTION spi_test() RETURNS void
LANGUAGE plperl LANGUAGE plperl

View File

@ -52,7 +52,7 @@ SELECT perl2undef() IS NULL AS p;
--- test transforming to perl --- test transforming to perl
CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void
LANGUAGE plperlu LANGUAGE plperlu
TRANSFORM FOR TYPE bool TRANSFORM FOR TYPE bool, for type boolean -- duplicate to test ruleutils
AS $$ AS $$
my ($x, $y, $z) = @_; my ($x, $y, $z) = @_;
@ -68,6 +68,21 @@ SELECT bool2perl (true, false, NULL);
(1 row) (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 --- test selecting bool through SPI
CREATE FUNCTION spi_test() RETURNS void CREATE FUNCTION spi_test() RETURNS void
LANGUAGE plperlu LANGUAGE plperlu

View File

@ -33,7 +33,7 @@ SELECT perl2undef() IS NULL AS p;
CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void
LANGUAGE plperl LANGUAGE plperl
TRANSFORM FOR TYPE bool TRANSFORM FOR TYPE bool, for type boolean -- duplicate to test ruleutils
AS $$ AS $$
my ($x, $y, $z) = @_; my ($x, $y, $z) = @_;
@ -46,6 +46,10 @@ $$;
SELECT bool2perl (true, false, NULL); SELECT bool2perl (true, false, NULL);
--- test ruleutils
\sf bool2perl
--- test selecting bool through SPI --- test selecting bool through SPI
CREATE FUNCTION spi_test() RETURNS void CREATE FUNCTION spi_test() RETURNS void

View File

@ -33,7 +33,7 @@ SELECT perl2undef() IS NULL AS p;
CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void CREATE FUNCTION bool2perl(bool, bool, bool) RETURNS void
LANGUAGE plperlu LANGUAGE plperlu
TRANSFORM FOR TYPE bool TRANSFORM FOR TYPE bool, for type boolean -- duplicate to test ruleutils
AS $$ AS $$
my ($x, $y, $z) = @_; my ($x, $y, $z) = @_;
@ -46,6 +46,10 @@ $$;
SELECT bool2perl (true, false, NULL); SELECT bool2perl (true, false, NULL);
--- test ruleutils
\sf bool2perl
--- test selecting bool through SPI --- test selecting bool through SPI
CREATE FUNCTION spi_test() RETURNS void CREATE FUNCTION spi_test() RETURNS void

View File

@ -47,19 +47,29 @@ SELECT test1arr(array['aa=>bb, cc=>NULL'::hstore, 'dd=>ee']);
(1 row) (1 row)
-- test python -> hstore -- test python -> hstore
CREATE FUNCTION test2() RETURNS hstore CREATE FUNCTION test2(a int, b text) RETURNS hstore
LANGUAGE plpythonu LANGUAGE plpythonu
TRANSFORM FOR TYPE hstore TRANSFORM FOR TYPE hstore
AS $$ AS $$
val = {'a': 1, 'b': 'boo', 'c': None} val = {'a': a, 'b': b, 'c': None}
return val return val
$$; $$;
SELECT test2(); SELECT test2(1, 'boo');
test2 test2
--------------------------------- ---------------------------------
"a"=>"1", "b"=>"boo", "c"=>NULL "a"=>"1", "b"=>"boo", "c"=>NULL
(1 row) (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[] -- test python -> hstore[]
CREATE FUNCTION test2arr() RETURNS hstore[] CREATE FUNCTION test2arr() RETURNS hstore[]
LANGUAGE plpythonu LANGUAGE plpythonu

View File

@ -40,15 +40,18 @@ SELECT test1arr(array['aa=>bb, cc=>NULL'::hstore, 'dd=>ee']);
-- test python -> hstore -- test python -> hstore
CREATE FUNCTION test2() RETURNS hstore CREATE FUNCTION test2(a int, b text) RETURNS hstore
LANGUAGE plpythonu LANGUAGE plpythonu
TRANSFORM FOR TYPE hstore TRANSFORM FOR TYPE hstore
AS $$ AS $$
val = {'a': 1, 'b': 'boo', 'c': None} val = {'a': a, 'b': b, 'c': None}
return val return val
$$; $$;
SELECT test2(); SELECT test2(1, 'boo');
--- test ruleutils
\sf test2
-- test python -> hstore[] -- test python -> hstore[]

View File

@ -3127,13 +3127,14 @@ print_function_trftypes(StringInfo buf, HeapTuple proctup)
{ {
int i; int i;
appendStringInfoString(buf, "\n TRANSFORM "); appendStringInfoString(buf, " TRANSFORM ");
for (i = 0; i < ntypes; i++) for (i = 0; i < ntypes; i++)
{ {
if (i != 0) if (i != 0)
appendStringInfoString(buf, ", "); appendStringInfoString(buf, ", ");
appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i])); appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
} }
appendStringInfoChar(buf, '\n');
} }
} }

View File

@ -1182,7 +1182,9 @@ get_func_arg_info(HeapTuple procTup,
/* /*
* get_func_trftypes * 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 int
get_func_trftypes(HeapTuple procTup, get_func_trftypes(HeapTuple procTup,
@ -1211,7 +1213,6 @@ get_func_trftypes(HeapTuple procTup,
ARR_HASNULL(arr) || ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID) ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "protrftypes is not a 1-D Oid array"); elog(ERROR, "protrftypes is not a 1-D Oid array");
Assert(nelems >= ((Form_pg_proc) GETSTRUCT(procTup))->pronargs);
*p_trftypes = (Oid *) palloc(nelems * sizeof(Oid)); *p_trftypes = (Oid *) palloc(nelems * sizeof(Oid));
memcpy(*p_trftypes, ARR_DATA_PTR(arr), memcpy(*p_trftypes, ARR_DATA_PTR(arr),
nelems * sizeof(Oid)); nelems * sizeof(Oid));