Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions doc/src/sgml/func/func-info.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -3827,8 +3827,9 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}
<indexterm>
<primary>pg_get_domain_ddl</primary>
</indexterm>
<function>pg_get_domain_ddl</function> ( <parameter>domain</parameter> <type>text</type> )
<returnvalue>regtype</returnvalue>
<function>pg_get_domain_ddl</function> ( <parameter>domain</parameter> <type>regtype</type>
<optional> <parameter>pretty</parameter> <type>boolean</type> </optional>)
<returnvalue>text</returnvalue>
</para>
<para>
Reconstructs the creating command for a domain.
Expand Down
6 changes: 6 additions & 0 deletions src/backend/catalog/system_functions.sql
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,12 @@ LANGUAGE INTERNAL
STRICT VOLATILE PARALLEL UNSAFE
AS 'pg_replication_origin_session_setup';

CREATE OR REPLACE FUNCTION
pg_get_domain_ddl(domain_name regtype, pretty bool DEFAULT false)
RETURNS text
LANGUAGE internal
AS 'pg_get_domain_ddl_ext';
Comment on lines +660 to +664
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this?
Isn't it better to have it in pg_proc.dat, also the one with a one-argument signature?


--
-- The default permissions for functions mean that anyone can execute them.
-- A number of functions shouldn't be executable by just anyone, but rather
Expand Down
100 changes: 79 additions & 21 deletions src/backend/utils/adt/ruleutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@
((pretty) ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) \
: PRETTYFLAG_INDENT)

#define GET_DDL_PRETTY_FLAGS(pretty) \
((pretty) ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) \
: 0)

Comment on lines +97 to +100
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#define GET_DDL_PRETTY_FLAGS(pretty) \
((pretty) ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT | PRETTYFLAG_SCHEMA) \
: 0)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like adding the GET_DDL_PRETTY_FLAGS, but maybe it's just me. If you have a strong feeling, let it be as it is

/* Default line length for pretty-print wrapping: 0 means wrap always */
#define WRAP_COLUMN_DEFAULT 0

Expand Down Expand Up @@ -546,6 +550,11 @@ static void get_json_table_nested_columns(TableFunc *tf, JsonTablePlan *plan,
deparse_context *context,
bool showimplicit,
bool needcomma);
static void get_formatted_string(StringInfo buf,
int prettyFlags,
int noOfTabChars,
const char *fmt,...) pg_attribute_printf(4, 5);
static char *pg_get_domain_ddl_worker(Oid domain_oid, int prettyFlags);

#define only_marker(rte) ((rte)->inh ? "" : "ONLY ")

Expand Down Expand Up @@ -13739,6 +13748,37 @@ get_range_partbound_string(List *bound_datums)
return buf->data;
}

/*
* get_formatted_string
*
* Return a formatted version of the string.
*
* pretty - If pretty is true, the output includes tabs (\t) and newlines (\n).
* noOfTabChars - indent with specified no of tabs.
* fmt - printf-style format string used by appendStringInfoVA.
*/
static void
get_formatted_string(StringInfo buf, int prettyFlags, int noOfTabChars, const char *fmt,...)
{
va_list args;

if (prettyFlags & PRETTYFLAG_INDENT)
{
appendStringInfoChar(buf, '\n');
/* Indent with tabs */
for (int i = 0; i < noOfTabChars; i++)
{
appendStringInfoChar(buf, '\t');
}
}
else
appendStringInfoChar(buf, ' ');

va_start(args, fmt);
appendStringInfoVA(buf, fmt, args);
va_end(args);
}


/*
* Helper function to scan domain constraints
Expand Down Expand Up @@ -13787,7 +13827,7 @@ scan_domain_constraints(Oid domain_oid, List **validcons, List **invalidcons)
*/
static void
build_create_domain_statement(StringInfo buf, Form_pg_type typForm,
Node *defaultExpr, List *validConstraints)
Node *defaultExpr, List *validConstraints, int prettyFlags)
{
HeapTuple baseTypeTuple;
Form_pg_type baseTypeForm;
Expand All @@ -13814,16 +13854,17 @@ build_create_domain_statement(StringInfo buf, Form_pg_type typForm,
/* Only add COLLATE if domain's collation differs from base type's */
if (typForm->typcollation != baseCollation)
{
appendStringInfo(buf, " COLLATE %s",
generate_collation_name(typForm->typcollation));
get_formatted_string(buf, prettyFlags, 1, "COLLATE %s",
generate_collation_name(typForm->typcollation));
}
}

/* Add default value if present */
if (defaultExpr != NULL)
{
char *defaultValue = deparse_expression_pretty(defaultExpr, NIL, false, false, 0, 0);
appendStringInfo(buf, " DEFAULT %s", defaultValue);
char *defaultValue = deparse_expression_pretty(defaultExpr, NIL, false, false, prettyFlags, 0);

get_formatted_string(buf, prettyFlags, 1, "DEFAULT %s", defaultValue);
}

/* Add valid constraints */
Expand All @@ -13837,14 +13878,14 @@ build_create_domain_statement(StringInfo buf, Form_pg_type typForm,
/* Look up the constraint info */
constraintTup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintOid));
if (!HeapTupleIsValid(constraintTup))
continue; /* constraint was dropped concurrently */
continue; /* constraint was dropped concurrently */

con = (Form_pg_constraint) GETSTRUCT(constraintTup);
constraintDef = pg_get_constraintdef_worker(constraintOid, false, PRETTYFLAG_PAREN, true);
constraintDef = pg_get_constraintdef_worker(constraintOid, false, prettyFlags, true);

appendStringInfo(buf, " CONSTRAINT %s %s",
quote_identifier(NameStr(con->conname)),
constraintDef);
get_formatted_string(buf, prettyFlags, 1, "CONSTRAINT %s",
quote_identifier(NameStr(con->conname)));
get_formatted_string(buf, prettyFlags, 2, "%s", constraintDef);

ReleaseSysCache(constraintTup);
}
Expand All @@ -13856,28 +13897,45 @@ build_create_domain_statement(StringInfo buf, Form_pg_type typForm,
* Helper function to add ALTER DOMAIN statements for invalid constraints
*/
static void
add_alter_domain_statements(StringInfo buf, List *invalidConstraints)
add_alter_domain_statements(StringInfo buf, List *invalidConstraints, int prettyFlags)
{
ListCell *lc;
ListCell *lc;

foreach(lc, invalidConstraints)
{
Oid constraintOid = lfirst_oid(lc);
char *alterStmt = pg_get_constraintdef_worker(constraintOid, true, PRETTYFLAG_PAREN, true);
Oid constraintOid = lfirst_oid(lc);
char *alterStmt = pg_get_constraintdef_worker(constraintOid, true, prettyFlags, true);

if (alterStmt)
appendStringInfo(buf, "\n%s;", alterStmt);
}
}

/*
* pg_get_domain_ddl - Get CREATE DOMAIN statement for a domain
* pg_get_domain_ddl_ext - Get CREATE DOMAIN statement for a domain with pretty-print option
*/
Datum
pg_get_domain_ddl(PG_FUNCTION_ARGS)
pg_get_domain_ddl_ext(PG_FUNCTION_ARGS)
{
StringInfoData buf;
Oid domain_oid = PG_GETARG_OID(0);
bool pretty = PG_GETARG_BOOL(1);
char *res;
int prettyFlags;

prettyFlags = GET_DDL_PRETTY_FLAGS(pretty);
Comment on lines +13921 to +13925
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool pretty = PG_GETARG_BOOL(1);
char *res;
int prettyFlags;
prettyFlags = GET_DDL_PRETTY_FLAGS(pretty);
bool pretty;
char *res;
int prettyFlags = true;
if (PG_ARGISNULL(1))
pretty = PG_GETARG_BOOL(1);
prettyFlags = pretty ? PRETTYFLAG_INDENT : 0;

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose this, instead of the GET_DDL_PRETTY_FLAGS, but it's your choice.


res = pg_get_domain_ddl_worker(domain_oid, prettyFlags);
if (res == NULL)
PG_RETURN_NULL();
PG_RETURN_TEXT_P(string_to_text(res));
}



static char *
pg_get_domain_ddl_worker(Oid domain_oid, int prettyFlags)
{
StringInfoData buf;
HeapTuple typeTuple;
Form_pg_type typForm;
Node *defaultExpr;
Expand All @@ -13887,7 +13945,7 @@ pg_get_domain_ddl(PG_FUNCTION_ARGS)
/* Look up the domain in pg_type */
typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(domain_oid));
if (!HeapTupleIsValid(typeTuple))
PG_RETURN_NULL();
return NULL;

typForm = (Form_pg_type) GETSTRUCT(typeTuple);

Expand All @@ -13899,16 +13957,16 @@ pg_get_domain_ddl(PG_FUNCTION_ARGS)

/* Build the DDL statement */
initStringInfo(&buf);
build_create_domain_statement(&buf, typForm, defaultExpr, validConstraints);
build_create_domain_statement(&buf, typForm, defaultExpr, validConstraints, prettyFlags);

/* Add ALTER DOMAIN statements for invalid constraints */
if (list_length(invalidConstraints) > 0)
add_alter_domain_statements(&buf, invalidConstraints);
add_alter_domain_statements(&buf, invalidConstraints, prettyFlags);

/* Cleanup */
list_free(validConstraints);
list_free(invalidConstraints);
ReleaseSysCache(typeTuple);

PG_RETURN_TEXT_P(cstring_to_text(buf.data));
return buf.data;
}
4 changes: 2 additions & 2 deletions src/include/catalog/pg_proc.dat
Original file line number Diff line number Diff line change
Expand Up @@ -8515,9 +8515,9 @@
{ oid => '2508', descr => 'constraint description with pretty-print option',
proname => 'pg_get_constraintdef', provolatile => 's', prorettype => 'text',
proargtypes => 'oid bool', prosrc => 'pg_get_constraintdef_ext' },
{ oid => '8024', descr => 'get CREATE statement for DOMAIN',
{ oid => '8024', descr => 'get CREATE statement for DOMAIN with pretty option',
proname => 'pg_get_domain_ddl', prorettype => 'text',
proargtypes => 'regtype', prosrc => 'pg_get_domain_ddl' },
proargtypes => 'regtype bool', prosrc => 'pg_get_domain_ddl_ext' },
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
proargtypes => 'regtype bool', prosrc => 'pg_get_domain_ddl_ext' },
proargtypes => 'regtype bool', prosrc => 'pg_get_domain_ddl_ext' },
{ oid => '8025', descr => 'get CREATE statement for DOMAIN',
proname => 'pg_get_domain_ddl', prorettype => 'text',
proargtypes => 'regtype', prosrc => 'pg_get_domain_ddl_ext' },

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this instead of adding the create function, better to have all teh changes in one place, maybe...

{ oid => '2509',
descr => 'deparse an encoded expression with pretty-print option',
proname => 'pg_get_expr', provolatile => 's', prorettype => 'text',
Expand Down
Loading