On Tue, 7 Apr 2026 at 05:44, Euler Taveira <[email protected]> wrote:
There are other functions. See pg_restore_extended_stats() [1] and related
functions. If you are looking for flexibility, this key-value pair arguments is
one of the ways to achieve it.
Ah, I missed that one indeed my search didn't find it because it used
type "any" for the variadic. That makes the usage nicer imo than the one
used here, because you can actually give booleans to it (not only 'true'
& 'false' as strings).
Looking at those examples I foresee another big downside to the VARIADIC
approach. It's impossible for an SQL autoformatter to make the function
call look nice, because it does not know the two arguments are supposed
to be together. They will all be put on a single line. The only way to
get a nicely looking function call is hand-formatting the code.
postgres=# create function foo(arg1 int default 0, arg2 int) returns int as $$
begin return arg1 + arg2; end; $$ language plpgsql;
ERROR: input parameters after one with a default value must also have defaults
LINE 1: create function foo(arg1 int default 0, arg2 int) returns in...
You don't give an example how VARIADIC gives you the ability to make
that behave differently. But I guess you mean that:
SELECT foo();
would start erroring "with 'arg2' is required" and users would have to do
SELECT foo('arg2', 123);
There's a pretty simple way to get that same behaviour for the named
arguments approach though. Simply use DEFAULT NULL as the default for
arg2, and make it nonstrict. Then you can check for NULL in the
implementation and throw an error, just like you would do for the
VARIADIC version. With that
SELECT foo(); --errors
SELECT foo(arg2 => 123) -- works
So I don't see how this VARIADIC differs in this case.
In any case it seems unlikely to me that we want to ever add new
required arguments to these functions. Simply for backwards
compatibility reasons that sounds like a huge hassle that we'll probably
want to avoid by giving any new arguments a default. So even if there
was a difference, I don't really consider that a useful benefit of the
VARIADIC approach.
The VARIADIC argument forces you to always specify the argument name; that's a
good thing. The regular argument list requires you to remember the order of the
arguments (unless you are using named arguments).
I definitely agree with this. But I think that's solvable in practice by
having examples in the docs showing how to use named arguments for these
functions (see attached v6). That way most users will use that named
argument syntax as opposed to the positional one.
It is just a few arguments for the current functions but I predict that
pg_get_table_dll may have a dozen of arguments. IMO the VARIADIC approach is
superior when you want several options. The function call is smaller in
comparison to your proposal. (Let's say you want to specify the last argument
value. Inform all the other default arguments plus the argument you want to
change. For VARIADIC, specify only the argument you want to change.)
If you use named arguments to call the function, then all of this
doesn't matter. And actually the VARIADIC can be more confusing.
Especially with many arguments because it can be unclear which of the
arguments is a key and which one is a value.
And even for few arguments a reader can be confused, if the reader
doesn't realize that the arguments are interpreted as key value pairs.
For instance, I'd say that for a call like below, it's not obvious that
'foreign_keys' and 'all' are a pair. I'd have to look at the function
docs to realize that these are not two separate arguments (one set to
'foreign_keys', and the other to 'all'):
select pg_get_table_ddl('mytable', 'foreign_keys', 'all');
while with the named argument syntax makes that's immediately clearer:
select pg_get_table_ddl('mytable', foreign_keys => 'all');
I meant modifying the pg_proc.dat every time a new argument is added.
Sure, but I don't understand why that would be problem. We do that all
the time in major releases. Even with the VARIADIC approach, I don't
think we should be adding optional arguments in minor releases.
So to summarize (from my biased viewpoint) I think the downsides are:
1. Uncommon calling convention: only pg_restore_*_stats and
pg_logical_slot_*_changes use it, while all other functions support
named parameters.
2. Needs custom option parsing logic
3. More characters to type because you have to quote booleans, integers
and argument names.
4. Requires functions to be marked as NOSTRICT, which then needs
additional NULL handling
5. It can be unclear to a reader of a query that the function arguments
should be interpreted as key-value pair
6. Breaks auto formatting
And the benefit:
1. Forces people to specify the argument name
I don't think those benefits outweigh the downsides.
From aed0f64b2159c9f83ae1321442c4e8c861afde7a Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <[email protected]>
Date: Mon, 6 Apr 2026 17:05:27 +0200
Subject: [PATCH v6] Use named arguments for pg_get_*_ddl() functions
In 4881981f92024 some infrastructure was introduced to allow optional
key-value pairs as arguments. This removes that infrastructure in favor
of named arguments. No custom parsing and typechecking logic is needed
this way.
---
doc/src/sgml/func/func-info.sgml | 65 +++--
src/backend/utils/adt/ddlutils.c | 256 ++-----------------
src/include/catalog/pg_proc.dat | 36 ++-
src/test/regress/expected/database_ddl.out | 10 +-
src/test/regress/expected/role_ddl.out | 4 +-
src/test/regress/expected/tablespace_ddl.out | 4 +-
src/test/regress/sql/database_ddl.sql | 9 +-
src/test/regress/sql/role_ddl.sql | 4 +-
src/test/regress/sql/tablespace_ddl.sql | 4 +-
src/tools/pgindent/typedefs.list | 2 -
10 files changed, 88 insertions(+), 306 deletions(-)
diff --git a/doc/src/sgml/func/func-info.sgml b/doc/src/sgml/func/func-info.sgml
index 80cf11083d6..179f2492845 100644
--- a/doc/src/sgml/func/func-info.sgml
+++ b/doc/src/sgml/func/func-info.sgml
@@ -3895,8 +3895,10 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
</indexterm>
<function>pg_get_role_ddl</function>
( <parameter>role</parameter> <type>regrole</type>
- <optional>, <literal>VARIADIC</literal> <parameter>options</parameter>
- <type>text</type> </optional> )
+ <optional>, <parameter>pretty</parameter> <type>boolean</type>
+ <literal>DEFAULT false</literal> </optional>
+ <optional>, <parameter>memberships</parameter> <type>boolean</type>
+ <literal>DEFAULT true</literal> </optional> )
<returnvalue>setof text</returnvalue>
</para>
<para>
@@ -3904,10 +3906,15 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
<command>ALTER ROLE ... SET</command> statements for the given role.
Each statement is returned as a separate row.
Password information is never included in the output.
- The following options are supported: <literal>pretty</literal> (boolean)
- for pretty-printed output and <literal>memberships</literal> (boolean,
- default true) to include <command>GRANT</command> statements for
- role memberships and their options.
+ If <parameter>pretty</parameter> is true, the output is formatted with
+ newlines and indentation.
+ If <parameter>memberships</parameter> is true (the default),
+ <command>GRANT</command> statements for role memberships and their
+ options are included.
+ For example:
+<programlisting>
+SELECT * FROM pg_get_role_ddl('myrole', memberships => false, pretty => true);
+</programlisting>
</para></entry>
</row>
<row>
@@ -3917,15 +3924,19 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
</indexterm>
<function>pg_get_tablespace_ddl</function>
( <parameter>tablespace</parameter> <type>oid</type>
- <optional>, <literal>VARIADIC</literal> <parameter>options</parameter>
- <type>text</type> </optional> )
+ <optional>, <parameter>pretty</parameter> <type>boolean</type>
+ <literal>DEFAULT false</literal> </optional>
+ <optional>, <parameter>owner</parameter> <type>boolean</type>
+ <literal>DEFAULT true</literal> </optional> )
<returnvalue>setof text</returnvalue>
</para>
<para>
<function>pg_get_tablespace_ddl</function>
( <parameter>tablespace</parameter> <type>name</type>
- <optional>, <literal>VARIADIC</literal> <parameter>options</parameter>
- <type>text</type> </optional> )
+ <optional>, <parameter>pretty</parameter> <type>boolean</type>
+ <literal>DEFAULT false</literal> </optional>
+ <optional>, <parameter>owner</parameter> <type>boolean</type>
+ <literal>DEFAULT true</literal> </optional> )
<returnvalue>setof text</returnvalue>
</para>
<para>
@@ -3933,9 +3944,14 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
the specified tablespace (by OID or name). If the tablespace has
options set, an <command>ALTER TABLESPACE ... SET</command> statement
is also returned. Each statement is returned as a separate row.
- The following options are supported: <literal>pretty</literal> (boolean)
- for formatted output and <literal>owner</literal> (boolean) to include
- <literal>OWNER</literal>.
+ If <parameter>pretty</parameter> is true, the output is formatted with
+ newlines and indentation.
+ If <parameter>owner</parameter> is true (the default), an
+ <literal>OWNER</literal> clause is included.
+ For example:
+<programlisting>
+SELECT * FROM pg_get_tablespace_ddl('pg_default', pretty => true);
+</programlisting>
</para></entry>
</row>
<row>
@@ -3945,8 +3961,12 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
</indexterm>
<function>pg_get_database_ddl</function>
( <parameter>database</parameter> <type>regdatabase</type>
- <optional>, <literal>VARIADIC</literal> <parameter>options</parameter>
- <type>text</type> </optional> )
+ <optional>, <parameter>pretty</parameter> <type>boolean</type>
+ <literal>DEFAULT false</literal> </optional>
+ <optional>, <parameter>owner</parameter> <type>boolean</type>
+ <literal>DEFAULT true</literal> </optional>
+ <optional>, <parameter>tablespace</parameter> <type>boolean</type>
+ <literal>DEFAULT true</literal> </optional> )
<returnvalue>setof text</returnvalue>
</para>
<para>
@@ -3954,11 +3974,16 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
specified database, followed by <command>ALTER DATABASE</command>
statements for connection limit, template status, and configuration
settings. Each statement is returned as a separate row.
- The following options are supported:
- <literal>pretty</literal> (boolean) for formatted output,
- <literal>owner</literal> (boolean) to include <literal>OWNER</literal>,
- and <literal>tablespace</literal> (boolean) to include
- <literal>TABLESPACE</literal>.
+ If <parameter>pretty</parameter> is true, the output is formatted with
+ newlines and indentation.
+ If <parameter>owner</parameter> is true (the default), an
+ <literal>OWNER</literal> clause is included.
+ If <parameter>tablespace</parameter> is true (the default), a
+ <literal>TABLESPACE</literal> clause is included.
+ For example:
+<programlisting>
+SELECT * FROM pg_get_database_ddl('mydb', pretty => true, tablespace => false);
+</programlisting>
</para></entry>
</row>
</tbody>
diff --git a/src/backend/utils/adt/ddlutils.c b/src/backend/utils/adt/ddlutils.c
index b16c277d000..f19901d7523 100644
--- a/src/backend/utils/adt/ddlutils.c
+++ b/src/backend/utils/adt/ddlutils.c
@@ -39,42 +39,12 @@
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
-#include "utils/pg_locale.h"
#include "utils/rel.h"
#include "utils/ruleutils.h"
#include "utils/syscache.h"
#include "utils/timestamp.h"
#include "utils/varlena.h"
-/* Option value types for DDL option parsing */
-typedef enum
-{
- DDL_OPT_BOOL,
- DDL_OPT_TEXT,
- DDL_OPT_INT,
-} DdlOptType;
-
-/*
- * A single DDL option descriptor: caller fills in name and type,
- * parse_ddl_options fills in isset + the appropriate value field.
- */
-typedef struct DdlOption
-{
- const char *name; /* option name (case-insensitive match) */
- DdlOptType type; /* expected value type */
- bool isset; /* true if caller supplied this option */
- /* fields for specific option types */
- union
- {
- bool boolval; /* filled in for DDL_OPT_BOOL */
- char *textval; /* filled in for DDL_OPT_TEXT (palloc'd) */
- int intval; /* filled in for DDL_OPT_INT */
- };
-} DdlOption;
-
-
-static void parse_ddl_options(FunctionCallInfo fcinfo, int variadic_start,
- DdlOption *opts, int nopts);
static void append_ddl_option(StringInfo buf, bool pretty, int indent,
const char *fmt,...)
pg_attribute_printf(4, 5);
@@ -83,150 +53,11 @@ static void append_guc_value(StringInfo buf, const char *name,
static List *pg_get_role_ddl_internal(Oid roleid, bool pretty,
bool memberships);
static List *pg_get_tablespace_ddl_internal(Oid tsid, bool pretty, bool no_owner);
-static Datum pg_get_tablespace_ddl_srf(FunctionCallInfo fcinfo, Oid tsid, bool isnull);
+static Datum pg_get_tablespace_ddl_srf(FunctionCallInfo fcinfo, Oid tsid);
static List *pg_get_database_ddl_internal(Oid dbid, bool pretty,
bool no_owner, bool no_tablespace);
-/*
- * parse_ddl_options
- * Parse variadic name/value option pairs
- *
- * Options are passed as alternating key/value text pairs. The caller
- * provides an array of DdlOption descriptors specifying the accepted
- * option names and their types; this function matches each supplied
- * pair against the array, validates the value, and fills in the
- * result fields.
- */
-static void
-parse_ddl_options(FunctionCallInfo fcinfo, int variadic_start,
- DdlOption *opts, int nopts)
-{
- Datum *args;
- bool *nulls;
- Oid *types;
- int nargs;
-
- /* Clear all output fields */
- for (int i = 0; i < nopts; i++)
- {
- opts[i].isset = false;
- switch (opts[i].type)
- {
- case DDL_OPT_BOOL:
- opts[i].boolval = false;
- break;
- case DDL_OPT_TEXT:
- opts[i].textval = NULL;
- break;
- case DDL_OPT_INT:
- opts[i].intval = 0;
- break;
- }
- }
-
- nargs = extract_variadic_args(fcinfo, variadic_start, true,
- &args, &types, &nulls);
-
- if (nargs <= 0)
- return;
-
- /* Handle DEFAULT NULL case */
- if (nargs == 1 && nulls[0])
- return;
-
- if (nargs % 2 != 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("variadic arguments must be name/value pairs"),
- errhint("Provide an even number of variadic arguments that can be divided into pairs.")));
-
- /*
- * For each option name/value pair, find corresponding positional option
- * for the option name, and assign the option value.
- */
- for (int i = 0; i < nargs; i += 2)
- {
- char *name;
- char *valstr;
- DdlOption *opt = NULL;
-
- if (nulls[i])
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("option name at variadic position %d is null", i + 1)));
-
- name = TextDatumGetCString(args[i]);
-
- if (nulls[i + 1])
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("value for option \"%s\" must not be null", name)));
-
- /* Find matching option descriptor */
- for (int j = 0; j < nopts; j++)
- {
- if (pg_strcasecmp(name, opts[j].name) == 0)
- {
- opt = &opts[j];
- break;
- }
- }
-
- if (opt == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unrecognized option: \"%s\"", name)));
-
- if (opt->isset)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("option \"%s\" is specified more than once",
- name)));
-
- valstr = TextDatumGetCString(args[i + 1]);
-
- switch (opt->type)
- {
- case DDL_OPT_BOOL:
- if (!parse_bool(valstr, &opt->boolval))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid value for boolean option \"%s\": %s",
- name, valstr)));
- break;
-
- case DDL_OPT_TEXT:
- opt->textval = valstr;
- valstr = NULL; /* don't pfree below */
- break;
-
- case DDL_OPT_INT:
- {
- char *endp;
- long val;
-
- errno = 0;
- val = strtol(valstr, &endp, 10);
- if (*endp != '\0' || errno == ERANGE ||
- val < PG_INT32_MIN || val > PG_INT32_MAX)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid value for integer option \"%s\": %s",
- name, valstr)));
- opt->intval = (int) val;
- }
- break;
- }
-
- opt->isset = true;
-
- if (valstr)
- pfree(valstr);
- pfree(name);
- }
-}
-
/*
* Helper to append a formatted string with optional pretty-printing.
*/
@@ -601,27 +432,13 @@ pg_get_role_ddl(PG_FUNCTION_ARGS)
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;
- Oid roleid;
- DdlOption opts[] = {
- {"pretty", DDL_OPT_BOOL},
- {"memberships", DDL_OPT_BOOL},
- };
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- if (PG_ARGISNULL(0))
- {
- MemoryContextSwitchTo(oldcontext);
- SRF_RETURN_DONE(funcctx);
- }
-
- roleid = PG_GETARG_OID(0);
- parse_ddl_options(fcinfo, 1, opts, lengthof(opts));
-
- statements = pg_get_role_ddl_internal(roleid,
- opts[0].isset && opts[0].boolval,
- !opts[1].isset || opts[1].boolval);
+ statements = pg_get_role_ddl_internal(PG_GETARG_OID(0),
+ PG_GETARG_BOOL(1),
+ PG_GETARG_BOOL(2));
funcctx->user_fctx = statements;
funcctx->max_calls = list_length(statements);
@@ -755,7 +572,7 @@ pg_get_tablespace_ddl_internal(Oid tsid, bool pretty, bool no_owner)
* pg_get_tablespace_ddl_srf - common SRF logic for tablespace DDL
*/
static Datum
-pg_get_tablespace_ddl_srf(FunctionCallInfo fcinfo, Oid tsid, bool isnull)
+pg_get_tablespace_ddl_srf(FunctionCallInfo fcinfo, Oid tsid)
{
FuncCallContext *funcctx;
List *statements;
@@ -763,25 +580,13 @@ pg_get_tablespace_ddl_srf(FunctionCallInfo fcinfo, Oid tsid, bool isnull)
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;
- DdlOption opts[] = {
- {"pretty", DDL_OPT_BOOL},
- {"owner", DDL_OPT_BOOL},
- };
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- if (isnull)
- {
- MemoryContextSwitchTo(oldcontext);
- SRF_RETURN_DONE(funcctx);
- }
-
- parse_ddl_options(fcinfo, 1, opts, lengthof(opts));
-
statements = pg_get_tablespace_ddl_internal(tsid,
- opts[0].isset && opts[0].boolval,
- opts[1].isset && !opts[1].boolval);
+ PG_GETARG_BOOL(1),
+ !PG_GETARG_BOOL(2));
funcctx->user_fctx = statements;
funcctx->max_calls = list_length(statements);
@@ -813,14 +618,7 @@ pg_get_tablespace_ddl_srf(FunctionCallInfo fcinfo, Oid tsid, bool isnull)
Datum
pg_get_tablespace_ddl_oid(PG_FUNCTION_ARGS)
{
- Oid tsid = InvalidOid;
- bool isnull;
-
- isnull = PG_ARGISNULL(0);
- if (!isnull)
- tsid = PG_GETARG_OID(0);
-
- return pg_get_tablespace_ddl_srf(fcinfo, tsid, isnull);
+ return pg_get_tablespace_ddl_srf(fcinfo, PG_GETARG_OID(0));
}
/*
@@ -830,19 +628,10 @@ pg_get_tablespace_ddl_oid(PG_FUNCTION_ARGS)
Datum
pg_get_tablespace_ddl_name(PG_FUNCTION_ARGS)
{
- Oid tsid = InvalidOid;
- Name tspname;
- bool isnull;
+ Name tspname = PG_GETARG_NAME(0);
- isnull = PG_ARGISNULL(0);
-
- if (!isnull)
- {
- tspname = PG_GETARG_NAME(0);
- tsid = get_tablespace_oid(NameStr(*tspname), false);
- }
-
- return pg_get_tablespace_ddl_srf(fcinfo, tsid, isnull);
+ return pg_get_tablespace_ddl_srf(fcinfo,
+ get_tablespace_oid(NameStr(*tspname), false));
}
/*
@@ -1122,29 +911,14 @@ pg_get_database_ddl(PG_FUNCTION_ARGS)
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;
- Oid dbid;
- DdlOption opts[] = {
- {"pretty", DDL_OPT_BOOL},
- {"owner", DDL_OPT_BOOL},
- {"tablespace", DDL_OPT_BOOL},
- };
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- if (PG_ARGISNULL(0))
- {
- MemoryContextSwitchTo(oldcontext);
- SRF_RETURN_DONE(funcctx);
- }
-
- dbid = PG_GETARG_OID(0);
- parse_ddl_options(fcinfo, 1, opts, lengthof(opts));
-
- statements = pg_get_database_ddl_internal(dbid,
- opts[0].isset && opts[0].boolval,
- opts[1].isset && !opts[1].boolval,
- opts[2].isset && !opts[2].boolval);
+ statements = pg_get_database_ddl_internal(PG_GETARG_OID(0),
+ PG_GETARG_BOOL(1),
+ !PG_GETARG_BOOL(2),
+ !PG_GETARG_BOOL(3));
funcctx->user_fctx = statements;
funcctx->max_calls = list_length(statements);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3ea17fc5629..1b5b6a683d3 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8610,36 +8610,32 @@
proname => 'pg_get_constraintdef', provolatile => 's', prorettype => 'text',
proargtypes => 'oid bool', prosrc => 'pg_get_constraintdef_ext' },
{ oid => '8760', descr => 'get DDL to recreate a role',
- proname => 'pg_get_role_ddl', provariadic => 'text', proisstrict => 'f',
+ proname => 'pg_get_role_ddl',
provolatile => 's', proretset => 't', prorows => '10', prorettype => 'text',
- proargtypes => 'regrole text',
- proargmodes => '{i,v}',
- proallargtypes => '{regrole,text}',
- pronargdefaults => '1', proargdefaults => '{NULL}',
+ proargtypes => 'regrole bool bool',
+ proargnames => '{roleid,pretty,memberships}',
+ pronargdefaults => '2', proargdefaults => '{false,true}',
prosrc => 'pg_get_role_ddl' },
{ oid => '8758', descr => 'get DDL to recreate a tablespace',
- proname => 'pg_get_tablespace_ddl', provariadic => 'text', proisstrict => 'f',
+ proname => 'pg_get_tablespace_ddl',
provolatile => 's', proretset => 't', prorows => '10', prorettype => 'text',
- proargtypes => 'oid text',
- proargmodes => '{i,v}',
- proallargtypes => '{oid,text}',
- pronargdefaults => '1', proargdefaults => '{NULL}',
+ proargtypes => 'oid bool bool',
+ proargnames => '{tablespace_oid,pretty,owner}',
+ pronargdefaults => '2', proargdefaults => '{false,true}',
prosrc => 'pg_get_tablespace_ddl_oid' },
{ oid => '8759', descr => 'get DDL to recreate a tablespace',
- proname => 'pg_get_tablespace_ddl', provariadic => 'text', proisstrict => 'f',
+ proname => 'pg_get_tablespace_ddl',
provolatile => 's', proretset => 't', prorows => '10', prorettype => 'text',
- proargtypes => 'name text',
- proargmodes => '{i,v}',
- proallargtypes => '{name,text}',
- pronargdefaults => '1', proargdefaults => '{NULL}',
+ proargtypes => 'name bool bool',
+ proargnames => '{tablespace_name,pretty,owner}',
+ pronargdefaults => '2', proargdefaults => '{false,true}',
prosrc => 'pg_get_tablespace_ddl_name' },
{ oid => '8762', descr => 'get DDL to recreate a database',
- proname => 'pg_get_database_ddl', provariadic => 'text', proisstrict => 'f',
+ proname => 'pg_get_database_ddl',
provolatile => 's', proretset => 't', prorows => '10', prorettype => 'text',
- proargtypes => 'regdatabase text',
- proargmodes => '{i,v}',
- proallargtypes => '{regdatabase,text}',
- pronargdefaults => '1', proargdefaults => '{NULL}',
+ proargtypes => 'regdatabase bool bool bool',
+ proargnames => '{database,pretty,owner,tablespace}',
+ pronargdefaults => '3', proargdefaults => '{false,true,true}',
prosrc => 'pg_get_database_ddl' },
{ oid => '2509',
descr => 'deparse an encoded expression with pretty-print option',
diff --git a/src/test/regress/expected/database_ddl.out b/src/test/regress/expected/database_ddl.out
index 97657e52cfa..67332212f56 100644
--- a/src/test/regress/expected/database_ddl.out
+++ b/src/test/regress/expected/database_ddl.out
@@ -36,12 +36,6 @@ SELECT * FROM pg_get_database_ddl(NULL);
---------------------
(0 rows)
--- Invalid option value (should error)
-SELECT * FROM pg_get_database_ddl('regression_database_ddl', 'owner', 'invalid');
-ERROR: invalid value for boolean option "owner": invalid
--- Duplicate option (should error)
-SELECT * FROM pg_get_database_ddl('regression_database_ddl', 'owner', 'false', 'owner', 'true');
-ERROR: option "owner" is specified more than once
-- Without options
SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_database_ddl');
ddl_filter
@@ -53,7 +47,7 @@ SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_data
(4 rows)
-- With owner
-SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_database_ddl', 'owner', 'true');
+SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_database_ddl', owner => true);
ddl_filter
--------------------------------------------------------------------------------------
CREATE DATABASE regression_database_ddl WITH TEMPLATE = template0 ENCODING = 'UTF8';
@@ -64,7 +58,7 @@ SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_data
-- Pretty-printed output
\pset format unaligned
-SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_database_ddl', 'pretty', 'true', 'tablespace', 'false');
+SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_database_ddl', pretty => true, tablespace => false);
ddl_filter
CREATE DATABASE regression_database_ddl
WITH TEMPLATE = template0
diff --git a/src/test/regress/expected/role_ddl.out b/src/test/regress/expected/role_ddl.out
index 575111da55c..e87e168e1f5 100644
--- a/src/test/regress/expected/role_ddl.out
+++ b/src/test/regress/expected/role_ddl.out
@@ -65,7 +65,7 @@ SELECT * FROM pg_get_role_ddl('regress_role-with-dash');
-- Pretty-printed output
\pset format unaligned
-SELECT * FROM pg_get_role_ddl('regress_role_ddl_test3', 'pretty', 'true');
+SELECT * FROM pg_get_role_ddl('regress_role_ddl_test3', pretty => true);
pg_get_role_ddl
CREATE ROLE regress_role_ddl_test3
SUPERUSER
@@ -99,7 +99,7 @@ SELECT * FROM pg_get_role_ddl('regress_role_ddl_member');
(3 rows)
-- Role with memberships suppressed
-SELECT * FROM pg_get_role_ddl('regress_role_ddl_member', 'memberships', 'false');
+SELECT * FROM pg_get_role_ddl('regress_role_ddl_member', memberships => false);
pg_get_role_ddl
--------------------------------------------------------------------------------------------------------------------
CREATE ROLE regress_role_ddl_member NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION NOBYPASSRLS;
diff --git a/src/test/regress/expected/tablespace_ddl.out b/src/test/regress/expected/tablespace_ddl.out
index e52043273a9..4f0f4401d2f 100644
--- a/src/test/regress/expected/tablespace_ddl.out
+++ b/src/test/regress/expected/tablespace_ddl.out
@@ -43,7 +43,7 @@ SELECT * FROM pg_get_tablespace_ddl('regress_allopt_tblsp');
-- pretty-printed output
\pset format unaligned
-SELECT * FROM pg_get_tablespace_ddl('regress_allopt_tblsp', 'pretty', 'true');
+SELECT * FROM pg_get_tablespace_ddl('regress_allopt_tblsp', pretty => true);
pg_get_tablespace_ddl
CREATE TABLESPACE regress_allopt_tblsp
OWNER regress_tblspc_ddl_user
@@ -52,7 +52,7 @@ ALTER TABLESPACE regress_allopt_tblsp SET (seq_page_cost='1.5', random_page_cost
(2 rows)
\pset format aligned
-- tablespace with owner suppressed
-SELECT * FROM pg_get_tablespace_ddl('regress_allopt_tblsp', 'owner', 'false');
+SELECT * FROM pg_get_tablespace_ddl('regress_allopt_tblsp', owner => false);
pg_get_tablespace_ddl
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE TABLESPACE regress_allopt_tblsp LOCATION '';
diff --git a/src/test/regress/sql/database_ddl.sql b/src/test/regress/sql/database_ddl.sql
index 89753ac6411..547e4d0f800 100644
--- a/src/test/regress/sql/database_ddl.sql
+++ b/src/test/regress/sql/database_ddl.sql
@@ -35,21 +35,16 @@ SELECT * FROM pg_get_database_ddl('regression_database');
-- NULL value
SELECT * FROM pg_get_database_ddl(NULL);
--- Invalid option value (should error)
-SELECT * FROM pg_get_database_ddl('regression_database_ddl', 'owner', 'invalid');
-
--- Duplicate option (should error)
-SELECT * FROM pg_get_database_ddl('regression_database_ddl', 'owner', 'false', 'owner', 'true');
-- Without options
SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_database_ddl');
-- With owner
-SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_database_ddl', 'owner', 'true');
+SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_database_ddl', owner => true);
-- Pretty-printed output
\pset format unaligned
-SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_database_ddl', 'pretty', 'true', 'tablespace', 'false');
+SELECT ddl_filter(pg_get_database_ddl) FROM pg_get_database_ddl('regression_database_ddl', pretty => true, tablespace => false);
\pset format aligned
-- Permission check: revoke CONNECT on database
diff --git a/src/test/regress/sql/role_ddl.sql b/src/test/regress/sql/role_ddl.sql
index 3d0142242ec..1667a1f6e10 100644
--- a/src/test/regress/sql/role_ddl.sql
+++ b/src/test/regress/sql/role_ddl.sql
@@ -40,7 +40,7 @@ SELECT * FROM pg_get_role_ddl('regress_role-with-dash');
-- Pretty-printed output
\pset format unaligned
-SELECT * FROM pg_get_role_ddl('regress_role_ddl_test3', 'pretty', 'true');
+SELECT * FROM pg_get_role_ddl('regress_role_ddl_test3', pretty => true);
\pset format aligned
-- Role with memberships
@@ -57,7 +57,7 @@ RESET ROLE;
SELECT * FROM pg_get_role_ddl('regress_role_ddl_member');
-- Role with memberships suppressed
-SELECT * FROM pg_get_role_ddl('regress_role_ddl_member', 'memberships', 'false');
+SELECT * FROM pg_get_role_ddl('regress_role_ddl_member', memberships => false);
-- Non-existent role (should error)
SELECT * FROM pg_get_role_ddl(9999999::oid);
diff --git a/src/test/regress/sql/tablespace_ddl.sql b/src/test/regress/sql/tablespace_ddl.sql
index ee3cc6e2e1e..fece93df251 100644
--- a/src/test/regress/sql/tablespace_ddl.sql
+++ b/src/test/regress/sql/tablespace_ddl.sql
@@ -30,11 +30,11 @@ SELECT * FROM pg_get_tablespace_ddl('regress_allopt_tblsp');
-- pretty-printed output
\pset format unaligned
-SELECT * FROM pg_get_tablespace_ddl('regress_allopt_tblsp', 'pretty', 'true');
+SELECT * FROM pg_get_tablespace_ddl('regress_allopt_tblsp', pretty => true);
\pset format aligned
-- tablespace with owner suppressed
-SELECT * FROM pg_get_tablespace_ddl('regress_allopt_tblsp', 'owner', 'false');
+SELECT * FROM pg_get_tablespace_ddl('regress_allopt_tblsp', owner => false);
DROP TABLESPACE regress_allopt_tblsp;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index e9430e07b36..fbd1f499aec 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -637,8 +637,6 @@ DataChecksumsWorkerResult
DataDirSyncMethod
DataDumperPtr
DataPageDeleteStack
-DdlOptType
-DdlOption
DataTypesUsageChecks
DataTypesUsageVersionCheck
DatabaseInfo
base-commit: 93dc1ace2007fe7c1103ccda3d7bc13b4eb4352f
--
2.53.0