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
44 changes: 44 additions & 0 deletions doc/src/sgml/func/func-info.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -3797,4 +3797,48 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres}

</sect2>

<sect2 id="functions-get-object-ddl">
<title>Get Object DDL Functions</title>

<para>
The functions shown in <xref linkend="functions-get-object-ddl-table"/>
print the DDL statements for various database objects.
(This is a decompiled reconstruction, not the original text
of the command.)
</para>

<table id="functions-get-object-ddl-table">
<title>Get Object DDL Functions</title>
<tgroup cols="1">
<thead>
<row>
<entry role="func_table_entry"><para role="func_signature">
Function
</para>
<para>
Description
</para></entry>
</row>
</thead>

<tbody>
<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
<primary>pg_get_domain_ddl</primary>
</indexterm>
<function>pg_get_domain_ddl</function> ( <parameter>domain</parameter> <type>text</type> )
<returnvalue>regtype</returnvalue>
</para>
<para>
Reconstructs the creating command for a domain.
The result is a complete <command>CREATE DOMAIN</command> statement.
</para></entry>
</row>
</tbody>
</tgroup>
</table>

</sect2>

</sect1>
174 changes: 174 additions & 0 deletions src/backend/utils/adt/ruleutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -13738,3 +13738,177 @@ get_range_partbound_string(List *bound_datums)

return buf->data;
}


/*
* Helper function to scan domain constraints
*/
static void
scan_domain_constraints(Oid domain_oid, List **validcons, List **invalidcons)
{
Relation constraintRel;
SysScanDesc sscan;
ScanKeyData skey;
HeapTuple constraintTup;

*validcons = NIL;
*invalidcons = NIL;

constraintRel = table_open(ConstraintRelationId, AccessShareLock);

ScanKeyInit(&skey,
Anum_pg_constraint_contypid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(domain_oid));

sscan = systable_beginscan(constraintRel,
ConstraintTypidIndexId,
true,
NULL,
1,
&skey);

while (HeapTupleIsValid(constraintTup = systable_getnext(sscan)))
{
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTup);

if (con->convalidated)
*validcons = lappend_oid(*validcons, con->oid);
else
*invalidcons = lappend_oid(*invalidcons, con->oid);
}

systable_endscan(sscan);
table_close(constraintRel, AccessShareLock);
}

/*
* Helper function to build CREATE DOMAIN statement
*/
static void
build_create_domain_statement(StringInfo buf, Form_pg_type typForm,
Node *defaultExpr, List *validConstraints)
{
HeapTuple baseTypeTuple;
Form_pg_type baseTypeForm;
Oid baseCollation = InvalidOid;
ListCell *lc;

appendStringInfo(buf, "CREATE DOMAIN %s.%s AS %s",
quote_identifier(get_namespace_name(typForm->typnamespace)),
quote_identifier(NameStr(typForm->typname)),
format_type_be(typForm->typbasetype));

/* Add collation if it differs from base type's collation */
if (OidIsValid(typForm->typcollation))
{
/* Get base type's collation for comparison */
baseTypeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typForm->typbasetype));
if (HeapTupleIsValid(baseTypeTuple))
{
baseTypeForm = (Form_pg_type) GETSTRUCT(baseTypeTuple);
baseCollation = baseTypeForm->typcollation;
ReleaseSysCache(baseTypeTuple);
}

/* 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));
}
}

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

/* Add valid constraints */
foreach(lc, validConstraints)
{
Oid constraintOid = lfirst_oid(lc);
HeapTuple constraintTup;
Form_pg_constraint con;
char *constraintDef;

/* Look up the constraint info */
constraintTup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintOid));
if (!HeapTupleIsValid(constraintTup))
continue; /* constraint was dropped concurrently */

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

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

ReleaseSysCache(constraintTup);
}

appendStringInfoChar(buf, ';');
}

/*
* Helper function to add ALTER DOMAIN statements for invalid constraints
*/
static void
add_alter_domain_statements(StringInfo buf, List *invalidConstraints)
{
ListCell *lc;

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

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

/*
* pg_get_domain_ddl - Get CREATE DOMAIN statement for a domain
*/
Datum
pg_get_domain_ddl(PG_FUNCTION_ARGS)
{
StringInfoData buf;
Oid domain_oid = PG_GETARG_OID(0);
HeapTuple typeTuple;
Form_pg_type typForm;
Node *defaultExpr;
List *validConstraints;
List *invalidConstraints;

/* Look up the domain in pg_type */
typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(domain_oid));
if (!HeapTupleIsValid(typeTuple))
PG_RETURN_NULL();

typForm = (Form_pg_type) GETSTRUCT(typeTuple);

/* Get default expression */
defaultExpr = get_typdefault(domain_oid);

/* Scan for valid and invalid constraints */
scan_domain_constraints(domain_oid, &validConstraints, &invalidConstraints);

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

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

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

PG_RETURN_TEXT_P(cstring_to_text(buf.data));
}
3 changes: 3 additions & 0 deletions src/include/catalog/pg_proc.dat
Original file line number Diff line number Diff line change
Expand Up @@ -8515,6 +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',
proname => 'pg_get_domain_ddl', prorettype => 'text',
proargtypes => 'regtype', prosrc => 'pg_get_domain_ddl' },
{ oid => '2509',
descr => 'deparse an encoded expression with pretty-print option',
proname => 'pg_get_expr', provolatile => 's', prorettype => 'text',
Expand Down
Loading