Re: [PATCH] Add pg_get_table_ddl() to reconstruct CREATE TABLE statements

Akshay Joshi <akshay.joshi@enterprisedb.com>

From: Akshay Joshi <akshay.joshi@enterprisedb.com>
To: Zsolt Parragi <zsolt.parragi@percona.com>
Cc: pgsql-hackers@lists.postgresql.org
Date: 2026-06-22T06:26:58Z
Lists: pgsql-hackers

Attachments

Thanks for the review; you're right, `includes_foreign_keys=false` on its
own is a half-measure. Re-running with the default to add FKs back collides
with the existing CREATE TABLE, UNIQUE indexes, etc.

I've added an only_foreign_keys option (boolean, default false) as the
natural complement of includes_foreign_keys=false. When set to true, the
function emits only the ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY
statements and suppresses everything else (CREATE TABLE, owner, indexes,
non-FK constraints, rules, statistics, replica identity, RLS toggles).
Partition-child recursion still runs so child FKs are reached too.
Combining `only_foreign_keys=true` with `includes_foreign_keys=false` is
rejected upfront since it would produce no output.

The documentation paragraph for `includes_foreign_keys` now directs users
to `only_foreign_keys` as the intended second pass. Regression coverage
adds three cases: the FK-only emission for your cons example, the zero-row
result for a table without FKs, and the error path.

The v8 patch is ready for review.

On Sat, Jun 20, 2026 at 1:15 AM Zsolt Parragi <zsolt.parragi@percona.com>
wrote:

> The previous features all look good to me, I only have one question
> for the new flag.
>
> > Calling
> > pg_get_table_ddl(t, 'includes_foreign_keys', 'false') now emits
> everything
> > except FOREIGN KEY constraints. This covers the multi-tenant clone
> > workflow: create tables first without cross-table references, then re-run
> > with the default to add the constraints once all targets exist.
>
> I think this feature needs a bit more documentation, an
> "only_foreign_keys" flag, or both.
>
> CREATE TABLE refd (id int PRIMARY KEY);
> CREATE TABLE cons (a int CHECK(a>0), b int UNIQUE, c int REFERENCES
> refd(id));
>
> -- pass 1: running without foreign keys
> SELECT * FROM pg_get_table_ddl('cons','includes_foreign_keys','false');
> -- execute everything
>
> -- loading data
>
> -- pass 2: running with everything
> SELECT * FROM pg_get_table_ddl('cons','includes_foreign_keys','true');
> -- ERROR: relation "cons" already exists (and the unique constraint
> also collides)
>
> I could do a "grep FOREIGN KEY" before executing (unless it's a tricky
> schema where that phrase appears elsewhere), or since psql continues
> on error, it will simply work if I accept a significant error noise,
> but then the documentation should be clear about this limitation.
> Following the documented approach and getting a bunch of unexpected
> errors could be confusing for users.
>
>
>