Fix incorrect declarations of variadic pg_get_*_ddl() functions.

The final parameter of an ordinary variadic function should be an
array type.  CREATE FUNCTION won't accept a declaration that isn't
like that, but it's possible to put an incorrect combination into a
pg_proc.dat entry.  Sadly, the opr_sanity test that was supposed to
check that is broken and does not report functions with non-array
final parameters.  This allowed exactly such a thinko to sneak into
the recently-added pg_get_*_ddl() functions: their last argument
should be declared text[] but was declared text.  (We'd probably
have noticed eventually, when somebody tried to actually pass a
variadic array to one of those functions.  But their regression
tests do not do that.)

Fix those functions, and fix the opr_sanity test so we'll notice
next time.  Bump catversion for new pg_proc contents.

Author: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/D41A334E-ED9E-42EE-830D-28D4D36E9317@gmail.com
This commit is contained in:
Tom Lane 2026-06-23 15:06:34 -04:00
parent 049b742daa
commit 2af70e9374
5 changed files with 14 additions and 14 deletions

View file

@ -3882,7 +3882,7 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
<function>pg_get_role_ddl</function>
( <parameter>role</parameter> <type>regrole</type>
<optional>, <literal>VARIADIC</literal> <parameter>options</parameter>
<type>text</type> </optional> )
<type>text[]</type> </optional> )
<returnvalue>setof text</returnvalue>
</para>
<para>
@ -3904,14 +3904,14 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
<function>pg_get_tablespace_ddl</function>
( <parameter>tablespace</parameter> <type>oid</type>
<optional>, <literal>VARIADIC</literal> <parameter>options</parameter>
<type>text</type> </optional> )
<type>text[]</type> </optional> )
<returnvalue>setof text</returnvalue>
</para>
<para role="func_signature">
<function>pg_get_tablespace_ddl</function>
( <parameter>tablespace</parameter> <type>name</type>
<optional>, <literal>VARIADIC</literal> <parameter>options</parameter>
<type>text</type> </optional> )
<type>text[]</type> </optional> )
<returnvalue>setof text</returnvalue>
</para>
<para>
@ -3932,7 +3932,7 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
<function>pg_get_database_ddl</function>
( <parameter>database</parameter> <type>regdatabase</type>
<optional>, <literal>VARIADIC</literal> <parameter>options</parameter>
<type>text</type> </optional> )
<type>text[]</type> </optional> )
<returnvalue>setof text</returnvalue>
</para>
<para>

View file

@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202606091
#define CATALOG_VERSION_NO 202606231
#endif

View file

@ -8593,26 +8593,26 @@
{ oid => '6501', descr => 'get DDL to recreate a role',
proname => 'pg_get_role_ddl', prorows => '10', provariadic => 'text',
proisstrict => 'f', proretset => 't', provolatile => 's',
pronargdefaults => '1', prorettype => 'text', proargtypes => 'regrole text',
proallargtypes => '{regrole,text}', proargmodes => '{i,v}',
pronargdefaults => '1', prorettype => 'text', proargtypes => 'regrole _text',
proallargtypes => '{regrole,_text}', proargmodes => '{i,v}',
proargdefaults => '{NULL}', prosrc => 'pg_get_role_ddl' },
{ oid => '6499', descr => 'get DDL to recreate a tablespace',
proname => 'pg_get_tablespace_ddl', prorows => '10', provariadic => 'text',
proisstrict => 'f', proretset => 't', provolatile => 's',
pronargdefaults => '1', prorettype => 'text', proargtypes => 'oid text',
proallargtypes => '{oid,text}', proargmodes => '{i,v}',
pronargdefaults => '1', prorettype => 'text', proargtypes => 'oid _text',
proallargtypes => '{oid,_text}', proargmodes => '{i,v}',
proargdefaults => '{NULL}', prosrc => 'pg_get_tablespace_ddl_oid' },
{ oid => '6500', descr => 'get DDL to recreate a tablespace',
proname => 'pg_get_tablespace_ddl', prorows => '10', provariadic => 'text',
proisstrict => 'f', proretset => 't', provolatile => 's',
pronargdefaults => '1', prorettype => 'text', proargtypes => 'name text',
proallargtypes => '{name,text}', proargmodes => '{i,v}',
pronargdefaults => '1', prorettype => 'text', proargtypes => 'name _text',
proallargtypes => '{name,_text}', proargmodes => '{i,v}',
proargdefaults => '{NULL}', prosrc => 'pg_get_tablespace_ddl_name' },
{ oid => '6502', descr => 'get DDL to recreate a database',
proname => 'pg_get_database_ddl', prorows => '10', provariadic => 'text',
proisstrict => 'f', proretset => 't', provolatile => 's',
pronargdefaults => '1', prorettype => 'text',
proargtypes => 'regdatabase text', proallargtypes => '{regdatabase,text}',
proargtypes => 'regdatabase _text', proallargtypes => '{regdatabase,_text}',
proargmodes => '{i,v}', proargdefaults => '{NULL}',
prosrc => 'pg_get_database_ddl' },
{ oid => '2509',

View file

@ -487,7 +487,7 @@ AND case proargtypes[array_length(proargtypes, 1)-1]
ELSE (SELECT t.oid
FROM pg_type t
WHERE t.typarray = proargtypes[array_length(proargtypes, 1)-1])
END != provariadic;
END IS DISTINCT FROM provariadic;
oid | provariadic | proargtypes
-----+-------------+-------------
(0 rows)

View file

@ -360,7 +360,7 @@ AND case proargtypes[array_length(proargtypes, 1)-1]
ELSE (SELECT t.oid
FROM pg_type t
WHERE t.typarray = proargtypes[array_length(proargtypes, 1)-1])
END != provariadic;
END IS DISTINCT FROM provariadic;
-- Check that all and only those functions with a variadic type have
-- a variadic argument.