Hello all!! I'm attaching the v2 of this patch! There's a lot of changes but I'll try to mention the biggest ones:
* Adopted the new structure following the previous committed patches of tablespaces and databases. * Added the options for pretty and owner, also added the statement that will alter the publication to have the owner. I didn't know if it was required since the CREATE PUBLICATION doesn't have a way to add the OWNER, but since all the other functions were doing the same, I think it's the way to do it. * Some improvements on managing the string splits, there's really useful functions for bitmapsets and lists so I use them to decide if we were in the first element or not. * I decided to use the cache instead of opening the relation with a shared lock, I hope it was the right decision since it didn't make sense to me to have a lock for a DDL. * I took all the comments and check the grammar * Even more tests were added since many corner cases were not detected in the first version, the regress tests helped a lot on finding corner cases * Added the EXCEPT clause that was added after the first version. Thank you for your reviews! -- Jonathan Gonzalez V. EDB: https://www.enterprisedb.com
From 626f15915820da1053c89f546caf4c5ae3419b0d Mon Sep 17 00:00:00 2001 From: "Jonathan Gonzalez V." <[email protected]> Date: Sun, 5 Oct 2025 18:11:56 +0200 Subject: [PATCH v2 1/1] Introduce a new function pg_get_publication_ddl() that returns the CREATE ddl statement for a given PUBLICATION. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function accepts a publication name or OID indistinctively, providing an easy way to call the function as a user from inside the Postgres code, or any SQL statement. Comprehensive regression tests are included covering various possible situations for a given publication. Reviewed-by: Hüseyin Demir <[email protected]> Reviewed-by: Cary Huang <[email protected]> Reviewed-by: Peter Smith <[email protected]> Reviewed-by: Man Zeng <[email protected]> Signed-off-by: Jonathan Gonzalez V. <[email protected]> --- doc/src/sgml/func/func-info.sgml | 35 + src/backend/utils/adt/ddlutils.c | 383 +++++++++- src/include/catalog/pg_proc.dat | 16 + src/test/regress/expected/publication_ddl.out | 671 ++++++++++++++++++ src/test/regress/parallel_schedule | 5 +- src/test/regress/sql/publication_ddl.sql | 248 +++++++ 6 files changed, 1356 insertions(+), 2 deletions(-) create mode 100644 src/test/regress/expected/publication_ddl.out create mode 100644 src/test/regress/sql/publication_ddl.sql diff --git a/doc/src/sgml/func/func-info.sgml b/doc/src/sgml/func/func-info.sgml index 00f64f50ceb..705bf32a17f 100644 --- a/doc/src/sgml/func/func-info.sgml +++ b/doc/src/sgml/func/func-info.sgml @@ -3961,6 +3961,41 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres} <literal>TABLESPACE</literal>. </para></entry> </row> + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_get_publication_ddl</primary> + </indexterm> + <function>pg_get_publication_ddl</function> + ( <parameter>publication</parameter> <type>oid</type> + <optional>, <literal>VARIADIC</literal> <parameter>options</parameter> + <type>text</type> </optional> ) + <returnvalue>setof text</returnvalue> + </para> + <para role="func_signature"> + <function>pg_get_publication_ddl</function> + ( <parameter>publication</parameter> <type>text</type> + <optional>, <literal>VARIADIC</literal> <parameter>options</parameter> + <type>text</type> </optional> ) + <returnvalue>setof text</returnvalue> + </para> + <para> + Reconstructs the <command>CREATE PUBLICATION</command> statement for + the specified publication (by OID or name), followed by an + <command>ALTER PUBLICATION ... OWNER TO</command> statement (the + <command>CREATE PUBLICATION</command> grammar has no + <literal>OWNER</literal> clause). Each statement is returned as a + separate row. An error is raised if no publication with the supplied + OID or name exists. When the publication was created with + <literal>FOR ALL TABLES, ALL SEQUENCES</literal>, the emitted + statement always lists <literal>ALL TABLES</literal> before + <literal>ALL SEQUENCES</literal> regardless of the original order. + The following options are supported: + <literal>pretty</literal> (boolean) for formatted output and + <literal>owner</literal> (boolean) to include + <literal>OWNER</literal>. + </para></entry> + </row> </tbody> </tgroup> </table> diff --git a/src/backend/utils/adt/ddlutils.c b/src/backend/utils/adt/ddlutils.c index f32fcd453ef..39cdcdf5a63 100644 --- a/src/backend/utils/adt/ddlutils.c +++ b/src/backend/utils/adt/ddlutils.c @@ -20,12 +20,14 @@ #include "access/genam.h" #include "access/htup_details.h" +#include "access/relation.h" #include "access/table.h" #include "catalog/pg_auth_members.h" #include "catalog/pg_authid.h" #include "catalog/pg_collation.h" #include "catalog/pg_database.h" #include "catalog/pg_db_role_setting.h" +#include "catalog/pg_publication_rel.h" #include "catalog/pg_tablespace.h" #include "commands/tablespace.h" #include "common/relpath.h" @@ -86,7 +88,10 @@ 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 List *pg_get_database_ddl_internal(Oid dbid, bool pretty, bool no_owner, bool no_tablespace); - +static Datum pg_get_publication_ddl_srf(FunctionCallInfo fcinfo, + Oid puboid, bool isnull); +static List *pg_get_publication_ddl_internal(Oid puboid, bool pretty, + bool no_owner); /* * parse_ddl_options @@ -1185,3 +1190,379 @@ pg_get_database_ddl(PG_FUNCTION_ARGS) SRF_RETURN_DONE(funcctx); } } + +/* + * pg_get_publication_ddl_srf - common SRF logic for publication DDL + */ +static Datum +pg_get_publication_ddl_srf(FunctionCallInfo fcinfo, Oid puboid, bool isnull) +{ + FuncCallContext *funcctx; + List *statements; + + 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_publication_ddl_internal(puboid, + opts[0].isset && opts[0].boolval, + opts[1].isset && !opts[1].boolval); + + funcctx->user_fctx = statements; + funcctx->max_calls = list_length(statements); + + MemoryContextSwitchTo(oldcontext); + } + + funcctx = SRF_PERCALL_SETUP(); + statements = (List *) funcctx->user_fctx; + + if (funcctx->call_cntr < funcctx->max_calls) + { + char *stmt; + + stmt = (char *) list_nth(statements, funcctx->call_cntr); + + SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(stmt)); + } + else + { + list_free_deep(statements); + SRF_RETURN_DONE(funcctx); + } +} + +/* + * pg_get_publication_ddl_oid + * Return DDL to recreate a publication, taking OID. + */ +Datum +pg_get_publication_ddl_oid(PG_FUNCTION_ARGS) +{ + Oid puboid = InvalidOid; + bool isnull; + + isnull = PG_ARGISNULL(0); + if (!isnull) + puboid = PG_GETARG_OID(0); + + return pg_get_publication_ddl_srf(fcinfo, puboid, isnull); +} + +/* + * pg_get_publication_ddl_name + * Return DDL to recreate a publication, taking name. + */ +Datum +pg_get_publication_ddl_name(PG_FUNCTION_ARGS) +{ + Oid puboid = InvalidOid; + bool isnull; + + isnull = PG_ARGISNULL(0); + if (!isnull) + { + char *pubname = text_to_cstring(PG_GETARG_TEXT_PP(0)); + + puboid = get_publication_oid(pubname, false); + pfree(pubname); + } + + return pg_get_publication_ddl_srf(fcinfo, puboid, isnull); +} + +/* + * pg_get_publication_ddl_internal + * Common code for pg_get_publication_ddl_oid and + * pg_get_publication_ddl_name. + * + * Returns a List of palloc'd strings. The first element is the + * CREATE PUBLICATION statement; if no_owner is false a second element + * carries an ALTER PUBLICATION ... OWNER TO statement (the CREATE + * PUBLICATION grammar has no OWNER clause, so ownership must be applied + * as a follow-on statement). + */ +static List * +pg_get_publication_ddl_internal(Oid puboid, bool pretty, bool no_owner) +{ + Publication *pub; + StringInfo buf; + List *statements = NIL; + List *pub_incl_relids = NIL; + List *pub_excl_relids = NIL; + List *pub_schemas = NIL; + bool first_perm = true; + + if (!SearchSysCacheExists1(PUBLICATIONOID, ObjectIdGetDatum(puboid))) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("publication with OID %u does not exist", puboid))); + + pub = GetPublication(puboid); + + buf = makeStringInfo(); + + appendStringInfo(buf, "CREATE PUBLICATION %s", quote_identifier(pub->name)); + + /* + * Having all tables or all sequences means that there are no per-table + * publications + */ + if (pub->alltables || pub->allsequences) + { + append_ddl_option(buf, pretty, 4, "FOR "); + + if (pub->alltables) + { + appendStringInfoString(buf, "ALL TABLES"); + pub_excl_relids = GetExcludedPublicationTables(pub->oid, PUBLICATION_PART_ROOT); + } + if (pub->allsequences) + appendStringInfo(buf, + "%sALL SEQUENCES", + pub->alltables ? ", " : ""); + } + else + { + pub_incl_relids = GetIncludedPublicationRelations(pub->oid, PUBLICATION_PART_ROOT); + pub_schemas = GetPublicationSchemas(pub->oid); + } + + if (pub_incl_relids != NIL) + { + ListCell *pub_cell; + char *schemaname = NULL; + char *tablename; + + append_ddl_option(buf, pretty, 4, "FOR TABLE "); + + /* + * Publication can have table relations + */ + foreach(pub_cell, pub_incl_relids) + { + HeapTuple pubtuple = NULL; + HeapTuple reltup; + Form_pg_class relform; + Datum columns, + conditions; + Oid relid = pub_cell->oid_value; + bool cols_nulls, + condition_nulls; + + reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(reltup)) + elog(ERROR, + "cache lookup failed for relation %u", + relid); + + relform = (Form_pg_class) GETSTRUCT(reltup); + tablename = NameStr(relform->relname); + schemaname = get_namespace_name(relform->relnamespace); + + appendStringInfo(buf, "%s%s", + foreach_current_index(pub_cell) > 0 ? ", " : "", + quote_qualified_identifier(schemaname, tablename)); + + pfree(schemaname); + + pubtuple = SearchSysCache2(PUBLICATIONRELMAP, ObjectIdGetDatum(relid), + ObjectIdGetDatum(pub->oid)); + + if (!HeapTupleIsValid(pubtuple)) + elog(ERROR, + "cache lookup failed for publication relation %u in publication %u", + relid, pub->oid); + + columns = SysCacheGetAttr(PUBLICATIONRELMAP, pubtuple, + Anum_pg_publication_rel_prattrs, + &cols_nulls); + + conditions = SysCacheGetAttr(PUBLICATIONRELMAP, pubtuple, + Anum_pg_publication_rel_prqual, + &condition_nulls); + + /* If non-null, we have a list of columns to publish */ + if (!cols_nulls) + { + Bitmapset *attmap; + int attnum = -1; + + attmap = pub_collist_to_bitmapset(NULL, columns, NULL); + + appendStringInfoChar(buf, '('); + while ((attnum = bms_next_member(attmap, attnum)) >= 0) + { + appendStringInfo(buf, "%s%s", + bms_member_index(attmap, attnum) ? ", " : "", + quote_identifier(get_attname(relid, attnum, true))); + } + appendStringInfoChar(buf, ')'); + + bms_free(attmap); + } + + /* + * If there is a condition it goes after the columns. We can have + * conditions without columns as well. + */ + if (!condition_nulls) + { + Node *node; + List *context; + char *str; + + node = stringToNode(TextDatumGetCString(conditions)); + context = deparse_context_for(tablename, relid); + str = deparse_expression(node, context, false, false); + appendStringInfo(buf, " WHERE %s", str); + } + + ReleaseSysCache(pubtuple); + ReleaseSysCache(reltup); + } + } + + /* If we have schemas, they will go right before the WITH */ + if (pub_schemas != NIL) + { + ListCell *schema_cell; + + /* + * Schemas can be preceded by a list of tables. When they are, the + * "TABLES IN SCHEMA" stays inline as a continuation of the existing + * FOR clause; otherwise it starts the FOR clause on its own line in + * pretty mode. + */ + if (pub_incl_relids == NIL) + append_ddl_option(buf, pretty, 4, "FOR TABLES IN SCHEMA"); + else + appendStringInfoString(buf, ", TABLES IN SCHEMA"); + + foreach(schema_cell, pub_schemas) + { + char *nspname = get_namespace_name(schema_cell->oid_value); + + appendStringInfo(buf, "%s %s", + foreach_current_index(schema_cell) > 0 ? "," : "", + quote_identifier(nspname)); + pfree(nspname); + } + } + + if (pub_excl_relids != NIL) + { + ListCell *excl_cell; + char *schemaname = NULL; + + appendStringInfoString(buf, " EXCEPT (TABLE "); + + foreach(excl_cell, pub_excl_relids) + { + HeapTuple tp = SearchSysCache1(RELOID, ObjectIdGetDatum(excl_cell->oid_value)); + Form_pg_class reltup; + + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for relation %u", excl_cell->oid_value); + + reltup = (Form_pg_class) GETSTRUCT(tp); + schemaname = get_namespace_name(reltup->relnamespace); + + appendStringInfo(buf, "%s%s", + foreach_current_index(excl_cell) > 0 ? ", " : "", + quote_qualified_identifier(schemaname, NameStr(reltup->relname))); + + pfree(schemaname); + ReleaseSysCache(tp); + } + + appendStringInfoChar(buf, ')'); + } + + /* Always add the WITH options */ + append_ddl_option(buf, pretty, 4, "WITH ("); + + /* Publish string */ + appendStringInfoString(buf, "publish='"); + + /* + * We need to know if we're the second permission added to prefix with a + * ", " string + */ + if (pub->pubactions.pubinsert) + { + /* + * By precedence we know that the insert will always be first, no need + * to check previous values + */ + appendStringInfoString(buf, "insert"); + first_perm = false; + } + + if (pub->pubactions.pubupdate) + { + appendStringInfo(buf, "%supdate", first_perm ? "" : ", "); + first_perm = false; + } + if (pub->pubactions.pubdelete) + { + appendStringInfo(buf, "%sdelete", first_perm ? "" : ", "); + first_perm = false; + } + + if (pub->pubactions.pubtruncate) + { + appendStringInfo(buf, "%struncate", first_perm ? "" : ", "); + } + + appendStringInfoString(buf, "', "); + + /* publish_generated_columns string */ + appendStringInfo(buf, "publish_generated_columns='%s', ", + pub->pubgencols_type == PUBLISH_GENCOLS_NONE ? "none" : "stored"); + + /* publish_via_partition_root value */ + appendStringInfo(buf, "publish_via_partition_root='%s')", + pub->pubviaroot ? "true" : "false"); + + appendStringInfoChar(buf, ';'); + statements = lappend(statements, pstrdup(buf->data)); + + /* OWNER */ + if (!no_owner) + { + HeapTuple tup; + Form_pg_publication pubform; + char *owner; + + tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(puboid)); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "cache lookup failed for publication %u", puboid); + pubform = (Form_pg_publication) GETSTRUCT(tup); + owner = GetUserNameFromId(pubform->pubowner, false); + ReleaseSysCache(tup); + + resetStringInfo(buf); + appendStringInfo(buf, "ALTER PUBLICATION %s OWNER TO %s;", + quote_identifier(pub->name), quote_identifier(owner)); + pfree(owner); + statements = lappend(statements, pstrdup(buf->data)); + } + + return statements; +} diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index be157a5fbe9..2579b530e28 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -12317,6 +12317,22 @@ proname => 'pg_relation_is_publishable', provolatile => 's', prorettype => 'bool', proargtypes => 'regclass', prosrc => 'pg_relation_is_publishable' }, +{ oid => '6122', descr => 'get DDL to recreate a publication', + proname => 'pg_get_publication_ddl', provariadic => 'text', proisstrict => 'f', + provolatile => 's', proretset => 't', prorows => '2', prorettype => 'text', + proargtypes => 'oid text', + proargmodes => '{i,v}', + proallargtypes => '{oid,text}', + pronargdefaults => '1', proargdefaults => '{NULL}', + prosrc => 'pg_get_publication_ddl_oid' }, +{ oid => '6123', descr => 'get DDL to recreate a publication', + proname => 'pg_get_publication_ddl', provariadic => 'text', proisstrict => 'f', + provolatile => 's', proretset => 't', prorows => '2', prorettype => 'text', + proargtypes => 'text text', + proargmodes => '{i,v}', + proallargtypes => '{text,text}', + pronargdefaults => '1', proargdefaults => '{NULL}', + prosrc => 'pg_get_publication_ddl_name' }, # rls { oid => '3298', diff --git a/src/test/regress/expected/publication_ddl.out b/src/test/regress/expected/publication_ddl.out new file mode 100644 index 00000000000..9fcb6582205 --- /dev/null +++ b/src/test/regress/expected/publication_ddl.out @@ -0,0 +1,671 @@ +-- +-- Test for DDL statement from: +-- - pg_get_publication_ddl +-- +-- suppress warning that depends on wal_level +SET client_min_messages = 'ERROR'; +-- Run the body under a stable role so the ALTER PUBLICATION ... OWNER TO +-- output is deterministic across environments. +CREATE ROLE regress_publication_ddl_user LOGIN SUPERUSER; +SET SESSION AUTHORIZATION 'regress_publication_ddl_user'; +-- test with a non-existing publication +SELECT pg_get_publication_ddl('non-existing'); +ERROR: publication "non-existing" does not exist +SELECT pg_get_publication_ddl(0::oid); +ERROR: publication with OID 0 does not exist +-- empty publication is possible and allowed +CREATE PUBLICATION testpub_ddl_1; +SELECT pg_get_publication_ddl('testpub_ddl_1'); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_1 WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_1 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_1')); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_1 WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_1 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_1', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_1 + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_1 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- NULL input should produce an empty result set +SELECT count(*) = 0 AS is_null FROM pg_get_publication_ddl(NULL::oid); + is_null +--------- + t +(1 row) + +SELECT count(*) = 0 AS is_null FROM pg_get_publication_ddl(NULL::text); + is_null +--------- + t +(1 row) + +-- create base table to test basic table publication +CREATE TABLE testpub_ddl_tbl1 (foo int, bar int); +CREATE TABLE testpub_ddl_tbl2 (foo int, bar int); +CREATE TABLE testpub_ddl_tbl3 (foo int, bar int, beque int, baz int); +CREATE TABLE testpub_ddl_tbl4 (foo int, bar int, beque bool); +CREATE TABLE testpub_ddl_tbl5 (foo int, "bar beque" int); +CREATE PUBLICATION testpub_ddl_2 FOR TABLE testpub_ddl_tbl1, testpub_ddl_tbl2, testpub_ddl_tbl3 WITH (publish='delete', publish_generated_columns='stored', publish_via_partition_root='true'); +SELECT pg_get_publication_ddl('testpub_ddl_2'); + pg_get_publication_ddl +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_2 FOR TABLE public.testpub_ddl_tbl1, public.testpub_ddl_tbl2, public.testpub_ddl_tbl3 WITH (publish='delete', publish_generated_columns='stored', publish_via_partition_root='true'); + ALTER PUBLICATION testpub_ddl_2 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_2')); + pg_get_publication_ddl +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_2 FOR TABLE public.testpub_ddl_tbl1, public.testpub_ddl_tbl2, public.testpub_ddl_tbl3 WITH (publish='delete', publish_generated_columns='stored', publish_via_partition_root='true'); + ALTER PUBLICATION testpub_ddl_2 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_2', 'pretty', 'true'); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_2 + + FOR TABLE public.testpub_ddl_tbl1, public.testpub_ddl_tbl2, public.testpub_ddl_tbl3 + + WITH (publish='delete', publish_generated_columns='stored', publish_via_partition_root='true'); + ALTER PUBLICATION testpub_ddl_2 OWNER TO regress_publication_ddl_user; +(2 rows) + +ALTER PUBLICATION testpub_ddl_2 SET (publish = 'delete, update'); +SELECT pg_get_publication_ddl('testpub_ddl_2'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_2 FOR TABLE public.testpub_ddl_tbl1, public.testpub_ddl_tbl2, public.testpub_ddl_tbl3 WITH (publish='update, delete', publish_generated_columns='stored', publish_via_partition_root='true'); + ALTER PUBLICATION testpub_ddl_2 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_2')); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_2 FOR TABLE public.testpub_ddl_tbl1, public.testpub_ddl_tbl2, public.testpub_ddl_tbl3 WITH (publish='update, delete', publish_generated_columns='stored', publish_via_partition_root='true'); + ALTER PUBLICATION testpub_ddl_2 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_2', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_2 + + FOR TABLE public.testpub_ddl_tbl1, public.testpub_ddl_tbl2, public.testpub_ddl_tbl3 + + WITH (publish='update, delete', publish_generated_columns='stored', publish_via_partition_root='true'); + ALTER PUBLICATION testpub_ddl_2 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create publication for one table +CREATE PUBLICATION testpub_ddl_3 FOR TABLE ONLY testpub_ddl_tbl1; +SELECT pg_get_publication_ddl('testpub_ddl_3'); + pg_get_publication_ddl +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_3 FOR TABLE public.testpub_ddl_tbl1 WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_3 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_3')); + pg_get_publication_ddl +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_3 FOR TABLE public.testpub_ddl_tbl1 WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_3 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_3', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_3 + + FOR TABLE public.testpub_ddl_tbl1 + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_3 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create publication for one table with two columns and a condition +CREATE PUBLICATION testpub_ddl_4 FOR TABLE ONLY testpub_ddl_tbl3 (bar,baz) WHERE (bar = baz); +SELECT pg_get_publication_ddl('testpub_ddl_4'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_4 FOR TABLE public.testpub_ddl_tbl3(bar, baz) WHERE (bar = baz) WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_4 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_4')); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_4 FOR TABLE public.testpub_ddl_tbl3(bar, baz) WHERE (bar = baz) WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_4 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_4', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_4 + + FOR TABLE public.testpub_ddl_tbl3(bar, baz) WHERE (bar = baz) + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_4 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create publication for one table with two columns and a condition with an expression +CREATE PUBLICATION testpub_ddl_5 FOR TABLE ONLY testpub_ddl_tbl4 (bar,beque) WHERE (beque IS TRUE); +SELECT pg_get_publication_ddl('testpub_ddl_5'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_5 FOR TABLE public.testpub_ddl_tbl4(bar, beque) WHERE (beque IS TRUE) WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_5 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_5')); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_5 FOR TABLE public.testpub_ddl_tbl4(bar, beque) WHERE (beque IS TRUE) WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_5 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_5', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_5 + + FOR TABLE public.testpub_ddl_tbl4(bar, beque) WHERE (beque IS TRUE) + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_5 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create publication for all tables +CREATE PUBLICATION testpub_ddl_6 FOR ALL TABLES; +SELECT pg_get_publication_ddl('testpub_ddl_6'); + pg_get_publication_ddl +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_6 FOR ALL TABLES WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_6 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_6')); + pg_get_publication_ddl +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_6 FOR ALL TABLES WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_6 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_6', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_6 + + FOR ALL TABLES + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_6 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create publication for all sequences +CREATE PUBLICATION testpub_ddl_7 FOR ALL SEQUENCES; +SELECT pg_get_publication_ddl('testpub_ddl_7'); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_7 FOR ALL SEQUENCES WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_7 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_7')); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_7 FOR ALL SEQUENCES WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_7 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_7', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_7 + + FOR ALL SEQUENCES + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_7 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create publication for all tables and all sequences +CREATE PUBLICATION testpub_ddl_8 FOR ALL TABLES, ALL SEQUENCES; +SELECT pg_get_publication_ddl('testpub_ddl_8'); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_8 FOR ALL TABLES, ALL SEQUENCES WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_8 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_8')); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_8 FOR ALL TABLES, ALL SEQUENCES WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_8 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_8', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_8 + + FOR ALL TABLES, ALL SEQUENCES + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_8 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- explicit publish_generated_columns='none' +CREATE PUBLICATION testpub_ddl_9 FOR ALL TABLES WITH (publish_generated_columns='none'); +SELECT pg_get_publication_ddl('testpub_ddl_9'); + pg_get_publication_ddl +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_9 FOR ALL TABLES WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_9 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_9')); + pg_get_publication_ddl +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_9 FOR ALL TABLES WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_9 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_9', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_9 + + FOR ALL TABLES + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_9 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- columns in publication must be quoted +CREATE PUBLICATION testpub_ddl_10 FOR TABLE testpub_ddl_tbl5("bar beque"); +SELECT pg_get_publication_ddl('testpub_ddl_10'); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_10 FOR TABLE public.testpub_ddl_tbl5("bar beque") WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_10 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_10')); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_10 FOR TABLE public.testpub_ddl_tbl5("bar beque") WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_10 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_10', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_10 + + FOR TABLE public.testpub_ddl_tbl5("bar beque") + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_10 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create schema for schema publication +CREATE SCHEMA pub_schema_test_ddl; +CREATE TABLE pub_schema_test_ddl.schema_tbl1 (foo int, bar int); +CREATE TABLE pub_schema_test_ddl.schema_tbl2 (foo int, bar int); +CREATE TABLE pub_schema_test_ddl.schema_tbl3 (foo int, bar int, baz int); +-- create a publication for a list of tables +CREATE PUBLICATION testpub_ddl_schema_1 FOR TABLE pub_schema_test_ddl.schema_tbl1, pub_schema_test_ddl.schema_tbl2, TABLES IN SCHEMA pub_schema_test_ddl; +SELECT pg_get_publication_ddl('testpub_ddl_schema_1'); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_schema_1 FOR TABLE pub_schema_test_ddl.schema_tbl1, pub_schema_test_ddl.schema_tbl2, TABLES IN SCHEMA pub_schema_test_ddl WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_1 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_schema_1')); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_schema_1 FOR TABLE pub_schema_test_ddl.schema_tbl1, pub_schema_test_ddl.schema_tbl2, TABLES IN SCHEMA pub_schema_test_ddl WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_1 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_schema_1', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_schema_1 + + FOR TABLE pub_schema_test_ddl.schema_tbl1, pub_schema_test_ddl.schema_tbl2, TABLES IN SCHEMA pub_schema_test_ddl + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_1 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create publication in schema only for table +CREATE PUBLICATION testpub_ddl_schema_2 FOR TABLES IN SCHEMA pub_schema_test_ddl, TABLE pub_schema_test_ddl.schema_tbl1; +SELECT pg_get_publication_ddl('testpub_ddl_schema_2'); + pg_get_publication_ddl +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_schema_2 FOR TABLE pub_schema_test_ddl.schema_tbl1, TABLES IN SCHEMA pub_schema_test_ddl WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_2 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_schema_2')); + pg_get_publication_ddl +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_schema_2 FOR TABLE pub_schema_test_ddl.schema_tbl1, TABLES IN SCHEMA pub_schema_test_ddl WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_2 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_schema_2', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_schema_2 + + FOR TABLE pub_schema_test_ddl.schema_tbl1, TABLES IN SCHEMA pub_schema_test_ddl + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_2 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create publication for all tables in schema +CREATE PUBLICATION testpub_ddl_schema_3 FOR TABLES IN SCHEMA pub_schema_test_ddl; +SELECT pg_get_publication_ddl('testpub_ddl_schema_3'); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_schema_3 FOR TABLES IN SCHEMA pub_schema_test_ddl WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_3 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_schema_3')); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_schema_3 FOR TABLES IN SCHEMA pub_schema_test_ddl WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_3 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_schema_3', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_schema_3 + + FOR TABLES IN SCHEMA pub_schema_test_ddl + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_3 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- a new schema for multiple schemas +CREATE SCHEMA pub_schema_test_ddl_2; +CREATE TABLE pub_schema_test_ddl_2.schema_tbl1 (foo int, bar int); +-- create a publication for a list of schemas +CREATE PUBLICATION testpub_ddl_schema_4 FOR TABLES IN SCHEMA pub_schema_test_ddl, pub_schema_test_ddl_2; +SELECT pg_get_publication_ddl('testpub_ddl_schema_4'); + pg_get_publication_ddl +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_schema_4 FOR TABLES IN SCHEMA pub_schema_test_ddl, pub_schema_test_ddl_2 WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_4 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_schema_4')); + pg_get_publication_ddl +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_schema_4 FOR TABLES IN SCHEMA pub_schema_test_ddl, pub_schema_test_ddl_2 WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_4 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_schema_4', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_schema_4 + + FOR TABLES IN SCHEMA pub_schema_test_ddl, pub_schema_test_ddl_2 + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_4 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create a publication for a specific schema and a table in public schema +-- both with the same name +CREATE TABLE schema_tbl1 (foo int, bar int); +CREATE PUBLICATION testpub_ddl_schema_5 FOR TABLE pub_schema_test_ddl.schema_tbl1, schema_tbl1; +SELECT pg_get_publication_ddl('testpub_ddl_schema_5'); + pg_get_publication_ddl +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_schema_5 FOR TABLE pub_schema_test_ddl.schema_tbl1, public.schema_tbl1 WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_5 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_schema_5')); + pg_get_publication_ddl +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_schema_5 FOR TABLE pub_schema_test_ddl.schema_tbl1, public.schema_tbl1 WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_5 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_schema_5', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_schema_5 + + FOR TABLE pub_schema_test_ddl.schema_tbl1, public.schema_tbl1 + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_schema_5 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create tables for partition test +CREATE TABLE testpub_ddl_part (foo int, bar int) PARTITION BY RANGE (foo); +CREATE TABLE testpub_ddl_part_p1 PARTITION OF testpub_ddl_part FOR VALUES FROM (0) TO (10); +CREATE TABLE testpub_ddl_part_p2 PARTITION OF testpub_ddl_part FOR VALUES FROM (10) TO (20); +CREATE PUBLICATION testpub_ddl_part1 FOR TABLE testpub_ddl_part; +SELECT pg_get_publication_ddl('testpub_ddl_part1'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_part1 FOR TABLE public.testpub_ddl_part WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_part1 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_part1')); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_part1 FOR TABLE public.testpub_ddl_part WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_part1 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_part1', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_part1 + + FOR TABLE public.testpub_ddl_part + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_part1 OWNER TO regress_publication_ddl_user; +(2 rows) + +CREATE PUBLICATION testpub_ddl_part2 FOR TABLE testpub_ddl_part WITH (publish_via_partition_root='false'); +SELECT pg_get_publication_ddl('testpub_ddl_part2'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_part2 FOR TABLE public.testpub_ddl_part WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_part2 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_part2')); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_part2 FOR TABLE public.testpub_ddl_part WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_part2 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_part2', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_part2 + + FOR TABLE public.testpub_ddl_part + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_part2 OWNER TO regress_publication_ddl_user; +(2 rows) + +CREATE PUBLICATION testpub_ddl_part3 FOR TABLE testpub_ddl_part WITH (publish_via_partition_root='true'); +SELECT pg_get_publication_ddl('testpub_ddl_part3'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_part3 FOR TABLE public.testpub_ddl_part WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='true'); + ALTER PUBLICATION testpub_ddl_part3 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_part3')); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_part3 FOR TABLE public.testpub_ddl_part WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='true'); + ALTER PUBLICATION testpub_ddl_part3 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_part3', 'pretty', 'true'); + pg_get_publication_ddl +----------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_part3 + + FOR TABLE public.testpub_ddl_part + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='true'); + ALTER PUBLICATION testpub_ddl_part3 OWNER TO regress_publication_ddl_user; +(2 rows) + +CREATE PUBLICATION testpub_ddl_part4 FOR TABLE testpub_ddl_part_p1; +SELECT pg_get_publication_ddl('testpub_ddl_part4'); + pg_get_publication_ddl +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_part4 FOR TABLE public.testpub_ddl_part_p1 WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_part4 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_part4')); + pg_get_publication_ddl +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_part4 FOR TABLE public.testpub_ddl_part_p1 WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_part4 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_part4', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_part4 + + FOR TABLE public.testpub_ddl_part_p1 + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_part4 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- identifiers that require quoting: publication, schema, table and column +CREATE SCHEMA "Pub Schema"; +CREATE TABLE "Pub Schema"."Quoted Table" ("Col One" int, "select" int); +CREATE PUBLICATION "Quoted Pub" FOR TABLE "Pub Schema"."Quoted Table" ("Col One", "select") WHERE ("Col One" > 0); +SELECT pg_get_publication_ddl('Quoted Pub'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION "Quoted Pub" FOR TABLE "Pub Schema"."Quoted Table"("Col One", "select") WHERE ("Col One" > 0) WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION "Quoted Pub" OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='Quoted Pub')); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION "Quoted Pub" FOR TABLE "Pub Schema"."Quoted Table"("Col One", "select") WHERE ("Col One" > 0) WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION "Quoted Pub" OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('Quoted Pub', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION "Quoted Pub" + + FOR TABLE "Pub Schema"."Quoted Table"("Col One", "select") WHERE ("Col One" > 0) + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION "Quoted Pub" OWNER TO regress_publication_ddl_user; +(2 rows) + +-- Tables for EXCEPT +CREATE TABLE testpub_ddl_except1 (foo int, bar int); +CREATE TABLE testpub_ddl_except2 (foo int, bar int); +-- create publication for all tables except one +CREATE PUBLICATION testpub_ddl_except1 FOR ALL TABLES EXCEPT (TABLE testpub_ddl_except1); +SELECT pg_get_publication_ddl('testpub_ddl_except1'); + pg_get_publication_ddl +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_except1 FOR ALL TABLES EXCEPT (TABLE public.testpub_ddl_except1) WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_except1 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_except1')); + pg_get_publication_ddl +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_except1 FOR ALL TABLES EXCEPT (TABLE public.testpub_ddl_except1) WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_except1 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_except1', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_except1 + + FOR ALL TABLES EXCEPT (TABLE public.testpub_ddl_except1) + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_except1 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- create publication for all tables except two tables +CREATE PUBLICATION testpub_ddl_except2 FOR ALL SEQUENCES, ALL TABLES EXCEPT (TABLE testpub_ddl_except1, testpub_ddl_except2); +SELECT pg_get_publication_ddl('testpub_ddl_except2'); + pg_get_publication_ddl +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_except2 FOR ALL TABLES, ALL SEQUENCES EXCEPT (TABLE public.testpub_ddl_except1, public.testpub_ddl_except2) WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_except2 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_except2')); + pg_get_publication_ddl +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE PUBLICATION testpub_ddl_except2 FOR ALL TABLES, ALL SEQUENCES EXCEPT (TABLE public.testpub_ddl_except1, public.testpub_ddl_except2) WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_except2 OWNER TO regress_publication_ddl_user; +(2 rows) + +SELECT pg_get_publication_ddl('testpub_ddl_except2', 'pretty', 'true'); + pg_get_publication_ddl +------------------------------------------------------------------------------------------------------------------------------ + CREATE PUBLICATION testpub_ddl_except2 + + FOR ALL TABLES, ALL SEQUENCES EXCEPT (TABLE public.testpub_ddl_except1, public.testpub_ddl_except2) + + WITH (publish='insert, update, delete, truncate', publish_generated_columns='none', publish_via_partition_root='false'); + ALTER PUBLICATION testpub_ddl_except2 OWNER TO regress_publication_ddl_user; +(2 rows) + +-- cleanup publications +DROP PUBLICATION testpub_ddl_1; +DROP PUBLICATION testpub_ddl_2; +DROP PUBLICATION testpub_ddl_3; +DROP PUBLICATION testpub_ddl_4; +DROP PUBLICATION testpub_ddl_5; +DROP PUBLICATION testpub_ddl_6; +DROP PUBLICATION testpub_ddl_7; +DROP PUBLICATION testpub_ddl_8; +DROP PUBLICATION testpub_ddl_9; +DROP PUBLICATION testpub_ddl_10; +DROP PUBLICATION testpub_ddl_schema_1; +DROP PUBLICATION testpub_ddl_schema_2; +DROP PUBLICATION testpub_ddl_schema_3; +DROP PUBLICATION testpub_ddl_schema_4; +DROP PUBLICATION testpub_ddl_schema_5; +DROP PUBLICATION testpub_ddl_part1; +DROP PUBLICATION testpub_ddl_part2; +DROP PUBLICATION testpub_ddl_part3; +DROP PUBLICATION testpub_ddl_part4; +DROP PUBLICATION "Quoted Pub"; +DROP PUBLICATION testpub_ddl_except1; +DROP PUBLICATION testpub_ddl_except2; +-- cleanup tables +DROP TABLE testpub_ddl_tbl1; +DROP TABLE testpub_ddl_tbl2; +DROP TABLE testpub_ddl_tbl3; +DROP TABLE testpub_ddl_tbl4; +DROP TABLE testpub_ddl_tbl5; +-- cleanup tables in schemas +DROP TABLE pub_schema_test_ddl.schema_tbl1; +DROP TABLE pub_schema_test_ddl.schema_tbl2; +DROP TABLE pub_schema_test_ddl.schema_tbl3; +DROP TABLE pub_schema_test_ddl_2.schema_tbl1; +DROP TABLE schema_tbl1; +-- cleanup tables for partitions +DROP TABLE testpub_ddl_part; +-- cleanup tables for quoted names +DROP TABLE "Pub Schema"."Quoted Table"; +-- cleanup tables for except +DROP TABLE testpub_ddl_except1; +DROP TABLE testpub_ddl_except2; +-- cleanup schemas +DROP SCHEMA pub_schema_test_ddl; +DROP SCHEMA pub_schema_test_ddl_2; +DROP SCHEMA "Pub Schema"; +-- cleanup role +RESET SESSION AUTHORIZATION; +DROP ROLE regress_publication_ddl_user; +RESET client_min_messages; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..3d3a6c57af5 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -135,7 +135,6 @@ test: compression compression_lz4 compression_pglz cluster # oidjoins is read-only, though, and should run late for best coverage test: oidjoins event_trigger - # event_trigger_login cannot run concurrently with any other tests because # on-login event handling could catch connection of a concurrent test. test: event_trigger_login @@ -143,6 +142,10 @@ test: event_trigger_login # this test also uses event triggers, so likewise run it by itself test: fast_default +# run retail DDL tests last to avoid object name collisions and +# interference with previous tests. +test: publication_ddl + # run tablespace test at the end because it drops the tablespace created during # setup that other tests may use. test: tablespace diff --git a/src/test/regress/sql/publication_ddl.sql b/src/test/regress/sql/publication_ddl.sql new file mode 100644 index 00000000000..9ec41bc0ae0 --- /dev/null +++ b/src/test/regress/sql/publication_ddl.sql @@ -0,0 +1,248 @@ +-- +-- Test for DDL statement from: +-- - pg_get_publication_ddl +-- + +-- suppress warning that depends on wal_level +SET client_min_messages = 'ERROR'; + +-- Run the body under a stable role so the ALTER PUBLICATION ... OWNER TO +-- output is deterministic across environments. +CREATE ROLE regress_publication_ddl_user LOGIN SUPERUSER; +SET SESSION AUTHORIZATION 'regress_publication_ddl_user'; + +-- test with a non-existing publication +SELECT pg_get_publication_ddl('non-existing'); +SELECT pg_get_publication_ddl(0::oid); + +-- empty publication is possible and allowed +CREATE PUBLICATION testpub_ddl_1; +SELECT pg_get_publication_ddl('testpub_ddl_1'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_1')); +SELECT pg_get_publication_ddl('testpub_ddl_1', 'pretty', 'true'); + +-- NULL input should produce an empty result set +SELECT count(*) = 0 AS is_null FROM pg_get_publication_ddl(NULL::oid); +SELECT count(*) = 0 AS is_null FROM pg_get_publication_ddl(NULL::text); + +-- create base table to test basic table publication +CREATE TABLE testpub_ddl_tbl1 (foo int, bar int); +CREATE TABLE testpub_ddl_tbl2 (foo int, bar int); +CREATE TABLE testpub_ddl_tbl3 (foo int, bar int, beque int, baz int); +CREATE TABLE testpub_ddl_tbl4 (foo int, bar int, beque bool); +CREATE TABLE testpub_ddl_tbl5 (foo int, "bar beque" int); + +CREATE PUBLICATION testpub_ddl_2 FOR TABLE testpub_ddl_tbl1, testpub_ddl_tbl2, testpub_ddl_tbl3 WITH (publish='delete', publish_generated_columns='stored', publish_via_partition_root='true'); + +SELECT pg_get_publication_ddl('testpub_ddl_2'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_2')); +SELECT pg_get_publication_ddl('testpub_ddl_2', 'pretty', 'true'); + +ALTER PUBLICATION testpub_ddl_2 SET (publish = 'delete, update'); + +SELECT pg_get_publication_ddl('testpub_ddl_2'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_2')); +SELECT pg_get_publication_ddl('testpub_ddl_2', 'pretty', 'true'); + +-- create publication for one table +CREATE PUBLICATION testpub_ddl_3 FOR TABLE ONLY testpub_ddl_tbl1; + +SELECT pg_get_publication_ddl('testpub_ddl_3'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_3')); +SELECT pg_get_publication_ddl('testpub_ddl_3', 'pretty', 'true'); + +-- create publication for one table with two columns and a condition +CREATE PUBLICATION testpub_ddl_4 FOR TABLE ONLY testpub_ddl_tbl3 (bar,baz) WHERE (bar = baz); + +SELECT pg_get_publication_ddl('testpub_ddl_4'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_4')); +SELECT pg_get_publication_ddl('testpub_ddl_4', 'pretty', 'true'); + +-- create publication for one table with two columns and a condition with an expression +CREATE PUBLICATION testpub_ddl_5 FOR TABLE ONLY testpub_ddl_tbl4 (bar,beque) WHERE (beque IS TRUE); + +SELECT pg_get_publication_ddl('testpub_ddl_5'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_5')); +SELECT pg_get_publication_ddl('testpub_ddl_5', 'pretty', 'true'); + +-- create publication for all tables +CREATE PUBLICATION testpub_ddl_6 FOR ALL TABLES; + +SELECT pg_get_publication_ddl('testpub_ddl_6'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_6')); +SELECT pg_get_publication_ddl('testpub_ddl_6', 'pretty', 'true'); + +-- create publication for all sequences +CREATE PUBLICATION testpub_ddl_7 FOR ALL SEQUENCES; +SELECT pg_get_publication_ddl('testpub_ddl_7'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_7')); +SELECT pg_get_publication_ddl('testpub_ddl_7', 'pretty', 'true'); + +-- create publication for all tables and all sequences +CREATE PUBLICATION testpub_ddl_8 FOR ALL TABLES, ALL SEQUENCES; + +SELECT pg_get_publication_ddl('testpub_ddl_8'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_8')); +SELECT pg_get_publication_ddl('testpub_ddl_8', 'pretty', 'true'); + +-- explicit publish_generated_columns='none' +CREATE PUBLICATION testpub_ddl_9 FOR ALL TABLES WITH (publish_generated_columns='none'); +SELECT pg_get_publication_ddl('testpub_ddl_9'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_9')); +SELECT pg_get_publication_ddl('testpub_ddl_9', 'pretty', 'true'); + +-- columns in publication must be quoted +CREATE PUBLICATION testpub_ddl_10 FOR TABLE testpub_ddl_tbl5("bar beque"); +SELECT pg_get_publication_ddl('testpub_ddl_10'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_10')); +SELECT pg_get_publication_ddl('testpub_ddl_10', 'pretty', 'true'); + +-- create schema for schema publication +CREATE SCHEMA pub_schema_test_ddl; +CREATE TABLE pub_schema_test_ddl.schema_tbl1 (foo int, bar int); +CREATE TABLE pub_schema_test_ddl.schema_tbl2 (foo int, bar int); +CREATE TABLE pub_schema_test_ddl.schema_tbl3 (foo int, bar int, baz int); + +-- create a publication for a list of tables +CREATE PUBLICATION testpub_ddl_schema_1 FOR TABLE pub_schema_test_ddl.schema_tbl1, pub_schema_test_ddl.schema_tbl2, TABLES IN SCHEMA pub_schema_test_ddl; +SELECT pg_get_publication_ddl('testpub_ddl_schema_1'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_schema_1')); +SELECT pg_get_publication_ddl('testpub_ddl_schema_1', 'pretty', 'true'); + +-- create publication in schema only for table +CREATE PUBLICATION testpub_ddl_schema_2 FOR TABLES IN SCHEMA pub_schema_test_ddl, TABLE pub_schema_test_ddl.schema_tbl1; +SELECT pg_get_publication_ddl('testpub_ddl_schema_2'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_schema_2')); +SELECT pg_get_publication_ddl('testpub_ddl_schema_2', 'pretty', 'true'); + +-- create publication for all tables in schema +CREATE PUBLICATION testpub_ddl_schema_3 FOR TABLES IN SCHEMA pub_schema_test_ddl; +SELECT pg_get_publication_ddl('testpub_ddl_schema_3'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_schema_3')); +SELECT pg_get_publication_ddl('testpub_ddl_schema_3', 'pretty', 'true'); + +-- a new schema for multiple schemas +CREATE SCHEMA pub_schema_test_ddl_2; +CREATE TABLE pub_schema_test_ddl_2.schema_tbl1 (foo int, bar int); + +-- create a publication for a list of schemas +CREATE PUBLICATION testpub_ddl_schema_4 FOR TABLES IN SCHEMA pub_schema_test_ddl, pub_schema_test_ddl_2; +SELECT pg_get_publication_ddl('testpub_ddl_schema_4'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_schema_4')); +SELECT pg_get_publication_ddl('testpub_ddl_schema_4', 'pretty', 'true'); + +-- create a publication for a specific schema and a table in public schema +-- both with the same name +CREATE TABLE schema_tbl1 (foo int, bar int); +CREATE PUBLICATION testpub_ddl_schema_5 FOR TABLE pub_schema_test_ddl.schema_tbl1, schema_tbl1; +SELECT pg_get_publication_ddl('testpub_ddl_schema_5'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_schema_5')); +SELECT pg_get_publication_ddl('testpub_ddl_schema_5', 'pretty', 'true'); + +-- create tables for partition test +CREATE TABLE testpub_ddl_part (foo int, bar int) PARTITION BY RANGE (foo); +CREATE TABLE testpub_ddl_part_p1 PARTITION OF testpub_ddl_part FOR VALUES FROM (0) TO (10); +CREATE TABLE testpub_ddl_part_p2 PARTITION OF testpub_ddl_part FOR VALUES FROM (10) TO (20); + +CREATE PUBLICATION testpub_ddl_part1 FOR TABLE testpub_ddl_part; +SELECT pg_get_publication_ddl('testpub_ddl_part1'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_part1')); +SELECT pg_get_publication_ddl('testpub_ddl_part1', 'pretty', 'true'); + +CREATE PUBLICATION testpub_ddl_part2 FOR TABLE testpub_ddl_part WITH (publish_via_partition_root='false'); +SELECT pg_get_publication_ddl('testpub_ddl_part2'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_part2')); +SELECT pg_get_publication_ddl('testpub_ddl_part2', 'pretty', 'true'); + +CREATE PUBLICATION testpub_ddl_part3 FOR TABLE testpub_ddl_part WITH (publish_via_partition_root='true'); +SELECT pg_get_publication_ddl('testpub_ddl_part3'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_part3')); +SELECT pg_get_publication_ddl('testpub_ddl_part3', 'pretty', 'true'); + +CREATE PUBLICATION testpub_ddl_part4 FOR TABLE testpub_ddl_part_p1; +SELECT pg_get_publication_ddl('testpub_ddl_part4'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_part4')); +SELECT pg_get_publication_ddl('testpub_ddl_part4', 'pretty', 'true'); + +-- identifiers that require quoting: publication, schema, table and column +CREATE SCHEMA "Pub Schema"; +CREATE TABLE "Pub Schema"."Quoted Table" ("Col One" int, "select" int); +CREATE PUBLICATION "Quoted Pub" FOR TABLE "Pub Schema"."Quoted Table" ("Col One", "select") WHERE ("Col One" > 0); +SELECT pg_get_publication_ddl('Quoted Pub'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='Quoted Pub')); +SELECT pg_get_publication_ddl('Quoted Pub', 'pretty', 'true'); + +-- Tables for EXCEPT +CREATE TABLE testpub_ddl_except1 (foo int, bar int); +CREATE TABLE testpub_ddl_except2 (foo int, bar int); + +-- create publication for all tables except one +CREATE PUBLICATION testpub_ddl_except1 FOR ALL TABLES EXCEPT (TABLE testpub_ddl_except1); +SELECT pg_get_publication_ddl('testpub_ddl_except1'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_except1')); +SELECT pg_get_publication_ddl('testpub_ddl_except1', 'pretty', 'true'); + +-- create publication for all tables except two tables +CREATE PUBLICATION testpub_ddl_except2 FOR ALL SEQUENCES, ALL TABLES EXCEPT (TABLE testpub_ddl_except1, testpub_ddl_except2); +SELECT pg_get_publication_ddl('testpub_ddl_except2'); +SELECT pg_get_publication_ddl((SELECT oid FROM pg_publication WHERE pubname='testpub_ddl_except2')); +SELECT pg_get_publication_ddl('testpub_ddl_except2', 'pretty', 'true'); + +-- cleanup publications +DROP PUBLICATION testpub_ddl_1; +DROP PUBLICATION testpub_ddl_2; +DROP PUBLICATION testpub_ddl_3; +DROP PUBLICATION testpub_ddl_4; +DROP PUBLICATION testpub_ddl_5; +DROP PUBLICATION testpub_ddl_6; +DROP PUBLICATION testpub_ddl_7; +DROP PUBLICATION testpub_ddl_8; +DROP PUBLICATION testpub_ddl_9; +DROP PUBLICATION testpub_ddl_10; +DROP PUBLICATION testpub_ddl_schema_1; +DROP PUBLICATION testpub_ddl_schema_2; +DROP PUBLICATION testpub_ddl_schema_3; +DROP PUBLICATION testpub_ddl_schema_4; +DROP PUBLICATION testpub_ddl_schema_5; +DROP PUBLICATION testpub_ddl_part1; +DROP PUBLICATION testpub_ddl_part2; +DROP PUBLICATION testpub_ddl_part3; +DROP PUBLICATION testpub_ddl_part4; +DROP PUBLICATION "Quoted Pub"; +DROP PUBLICATION testpub_ddl_except1; +DROP PUBLICATION testpub_ddl_except2; + +-- cleanup tables +DROP TABLE testpub_ddl_tbl1; +DROP TABLE testpub_ddl_tbl2; +DROP TABLE testpub_ddl_tbl3; +DROP TABLE testpub_ddl_tbl4; +DROP TABLE testpub_ddl_tbl5; + +-- cleanup tables in schemas +DROP TABLE pub_schema_test_ddl.schema_tbl1; +DROP TABLE pub_schema_test_ddl.schema_tbl2; +DROP TABLE pub_schema_test_ddl.schema_tbl3; +DROP TABLE pub_schema_test_ddl_2.schema_tbl1; +DROP TABLE schema_tbl1; + +-- cleanup tables for partitions +DROP TABLE testpub_ddl_part; + +-- cleanup tables for quoted names +DROP TABLE "Pub Schema"."Quoted Table"; + +-- cleanup tables for except +DROP TABLE testpub_ddl_except1; +DROP TABLE testpub_ddl_except2; + +-- cleanup schemas +DROP SCHEMA pub_schema_test_ddl; +DROP SCHEMA pub_schema_test_ddl_2; +DROP SCHEMA "Pub Schema"; + +-- cleanup role +RESET SESSION AUTHORIZATION; +DROP ROLE regress_publication_ddl_user; + +RESET client_min_messages; -- 2.53.0
signature.asc
Description: This is a digitally signed message part
