public inbox for [email protected]
help / color / mirror / Atom feedFrom: vignesh C <[email protected]>
To: Peter Smith <[email protected]>
Cc: Amit Kapila <[email protected]>
Cc: Masahiko Sawada <[email protected]>
Cc: Hayato Kuroda (Fujitsu) <[email protected]>
Cc: shveta malik <[email protected]>
Cc: Shlok Kyal <[email protected]>
Cc: Nisha Moond <[email protected]>
Cc: Ashutosh Sharma <[email protected]>
Cc: David G. Johnston <[email protected]>
Cc: Dilip Kumar <[email protected]>
Cc: Zhijie Hou (Fujitsu) <[email protected]>
Cc: YeXiu <[email protected]>
Cc: Ian Lawrence Barwick <[email protected]>
Cc: Bharath Rupireddy <[email protected]>
Cc: PostgreSQL Hackers <[email protected]>
Subject: Re: Skipping schema changes in publication
Date: Tue, 17 Mar 2026 12:23:45 +0530
Message-ID: <CALDaNm2OOgmNOPpABUU+AXzHhfrLG9HMfSd3jfNe=t3dc-kp1Q@mail.gmail.com> (raw)
In-Reply-To: <CAHut+PsCqTR_kQu5M1TqBjnE6KM5cO22aH8boHfpMa_gSJBmWg@mail.gmail.com>
References: <CAJpy0uB20MhJJEaPJdm31t4fykJ+fChA_76jU2P9HX5knbJvAA@mail.gmail.com>
<CAD21AoCC8XuwfX62qKBSfHUAoww_XB3_84HjswgL9jxQy696yw@mail.gmail.com>
<OS9PR01MB12149EA0C749BC29C7C949E32F544A@OS9PR01MB12149.jpnprd01.prod.outlook.com>
<CAD21AoBbZEshyaK0PeiF_J4_S75EfF=Gcs=C+X-osoVoUnawuQ@mail.gmail.com>
<CAHut+PssG+sHeV+Xo0g=S7xBb9FgDPjHYDR4iSuOdYXDq-Psng@mail.gmail.com>
<CAA4eK1LaSfAG7UAuy1xpnkWKM_YtrPuhbgAxYBFY3Sp_v_KqoQ@mail.gmail.com>
<CAD21AoAb8E8krN63cY_U7RQs9v-zkqUZyKT_UVKDwKfExtvTBg@mail.gmail.com>
<CAA4eK1K1GLR7DXSABayQE+pWM=v1ODD6haPYxuDhAYwJN5gjzg@mail.gmail.com>
<CALDaNm2kvFahDDvdgCNo=Nv-COz_N5Xw8YmzQBN2bd3g=N81fQ@mail.gmail.com>
<CAHut+PsCqTR_kQu5M1TqBjnE6KM5cO22aH8boHfpMa_gSJBmWg@mail.gmail.com>
On Mon, 16 Mar 2026 at 14:08, Peter Smith <[email protected]> wrote:
>
> Hi Vignesh.
>
> Unfortunately, IMO there are some fundamental problems here due to
> there being no accounting for publications with FOR ALL SEQUENCES. So
> I am posting my review comments for just the docs part so you can see
> it from my PoV. Maybe this was already discussed earlier in the thread
> but I saw no mentions of it. AFAICT the discussion/posts were mostly
> focussed on the setting/resetting of EXCEPT TABLE but seem to be
> overlooking the bigger picture.
>
> Below review comments are for v63-0001 docs only.
>
> ======
> Commit Message
>
> 1.
> The first form replaces the current EXCEPT TABLE list with the specified
> tables. The second form clears the existing except table list. Like the
> creation syntax, only root partitioned tables can be specified in the
> exclusion list.
>
> ~
>
> IMO the second form is a long-time missing command from Postgres. For
> example, it is possible to create an "empty" publication. But without
> this "ALTER PUBLICATION name SET ALL TABLES" there was no way to
> convert that to be a "FOR ALL TABLES" publication. So really this
> feature was independently needed and should be done anyway
> irrespective of any side-effect it has for the EXCEPT TABLE list.
>
> Ideally the SET/ADD/DROP ALL TABLES can split out and done ahead of
> the EXCEPT TABLE stuff.
>
> Similarly, SET/ADD/DROP should be implemented also for FOR ALL
> SEQUENCES otherwise there is no way to manipulate those either.
>
> ======
> doc/src/sgml/ref/alter_publication.sgml
>
> 2.
> Implementing the "SET ALL TABLES" is only a start. You also need to
> have the other case:
>
> * ADD ALL TABLES
> * DROP ALL TABLES
>
> Note you might start out with something like "CREATE PUBLICATION pub
> FOR ALL TABLES, FOR ALL SEQUENCES" so you need to be able to be able
> to modify/remove the published TABLES part without overwriting
> published SEQUENCES part!!
>
> i.e The "SET" means set the publication; it doesn't mean add to the
> publication. So SET ALL TABLES obliterates any FOR ALL SEQUENCES.
>
> ~~~
>
> 3.
> +<phrase>where <replaceable
> class="parameter">publication_except_tables</replaceable> is:</phrase>
> +
> + [ EXCEPT TABLE ( [ ONLY ] <replaceable
> class="parameter">table_name</replaceable> [, ... ] ) ]
> +
>
> Hmm. Ideally, this should be part of 'publication_object' and
> publication_drop_object' because the ADD/DROP are also needed for the
> reasons given in my above review commentS.
>
> ~~~
>
> 4.
> <para>
> - The first three variants change which tables/schemas are part of the
> - publication. The <literal>SET</literal> clause will replace the list of
> - tables/schemas in the publication with the specified list; the existing
> - tables/schemas that were present in the publication will be removed. The
> + The first four variants modify which tables/schemas are included in the
> + publication, or which tables are excluded from it. The
> + <literal>SET ALL TABLES</literal> clause is used to update the
> + <literal>EXCEPT TABLE</literal> list of a <literal>FOR ALL TABLES</literal>
> + publication. If <literal>EXCEPT TABLE</literal> is specified with a list of
> + tables, the existing except table list is replaced with the
> specified tables.
> + If <literal>EXCEPT TABLE</literal> is omitted, the existing except table
> + list is cleared. The <literal>SET</literal> clause, when used with a
> + publication defined with <literal>FOR TABLE</literal> or
> + <literal>FOR TABLES IN SCHEMA</literal>, replaces the list of tables/schemas
> + in the publication with the specified list; the existing tables or schemas
> + that were present in the publication will be removed. The
>
> I find this all a bit dubious because nothing seems to be accounting
> for the possibility of "FOR ALL SEQUENCES" also in the publication...
> e.g this entire ALTER command should also have
>
> SET ALL SEQUENCES
> ADD ALL SEQUENCES
> DROP ALL SEQUENCE
>
> and
>
> SET ALL TABLES
> ADD ALL TABLES
> DROP ALL TABLES
>
> IMO, a user will need to take care when using ALTER PUBLICATION ...
> SET ALL TABLES that it does not destroy the publication of sequences
> (and vice versa)
>
> -- Start with an "empty" publication and make it a "FOR ALL TABLES"
> publication...
> CREATE PUBLICATION pub;
> ALTER PUBLICATION pub SET ALL TABLES;
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES"
>
>
> -- give some table exceptions to it
> ALTER PUBLICATION pub SET ALL TABLES EXCEPT TABLE(t1,t2);
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES
> EXCEPT TABLE(t1,t2)"
>
>
> -- add sequences to this
> ALTER PUBLICATION pub ADD ALL SEQUENCES
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES
> EXCEPT TABLE(t1,t2), FOR ALL SEQUENCES"
>
>
> -- remove the table exception
> -- here you cannot simply use SET ALL TABLES because you will lose the
> ALL SEQUENCES part of the publication!!
> -- So, instead you need to do like below
> ALTER PUBLICATION pub DROP ALL TABLES;
> ALTER PUBLICATION pub ADD ALL TABLES;
> -- result is equivalent to "CREATE PUBLICATION ... FOR ALL TABLES, FOR
> ALL SEQUENCES"
>
> ~~~
>
> 5.
> +</programlisting></para>
> +
> + <para>
> + Replace the publication's EXCEPT table list:
>
> /EXCEPT table list/EXCEPT TABLE list/
>
> ~~~
>
> 6.
> + <para>
> + Change the publication to include all tables by removing any existing
> + EXCEPT table list:
>
> The clearing of the EXCEPT TABLES is more like a side-effect, so I
> think this can be worded differently.
>
> SUGGESTION
> Reset the publication to be a FOR ALL TABLES publication with no
> excluded tables.
Thanks for the comments, the agreed comments have been addressed in
the v64 version patch attached.
Regards,
Vignesh
Attachments:
[application/octet-stream] v64-0001-Add-support-for-EXCEPT-TABLE-in-ALTER-PUBLICATIO.patch (35.7K, 2-v64-0001-Add-support-for-EXCEPT-TABLE-in-ALTER-PUBLICATIO.patch)
download | inline diff:
From e6acba791b47a7dcbbb188f7f7001266d0ce1e35 Mon Sep 17 00:00:00 2001
From: Vignesh C <[email protected]>
Date: Wed, 4 Mar 2026 16:28:32 +0530
Subject: [PATCH v64] Add support for EXCEPT TABLE in ALTER PUBLICATION.
Following commit fd366065e0, which added EXCEPT TABLE support to
CREATE PUBLICATION, this commit extends ALTER PUBLICATION to allow
modifying the exclusion list.
New Syntax:
ALTER PUBLICATION name SET publication_all_object [, ... ]
where publication_all_object is one of:
ALL TABLES [ EXCEPT TABLE ( except_table_object [, ... ] ) ]
ALL SEQUENCES
The SET ALL TABLES clause updates pg_publication.puballtables to true.
If the EXCEPT clause is provided, the existing exclusion list in
pg_publication_rel is replaced with the specified relations. If the
EXCEPT clause is omitted, any existing exclusions for the publication
are cleared. Similarly, SET ALL SEQUENCES updates
pg_publication.puballsequences to true.
Note that because this is a SET command, specifying only one object
type (e.g., SET ALL SEQUENCES) will reset the other unspecified flags
(e.g., setting puballtables to false).
Consistent with CREATE PUBLICATION, only root partitioned tables or
standard tables can be specified in the EXCEPT list. Specifying a
partition child will result in an error.
Author: vignesh C <[email protected]>
Reviewed-by: shveta malik <[email protected]>
Reviewed-by: Amit Kapila <[email protected]>
Reviewed-by: Nisha Moond <[email protected]>
Discussion: https://postgr.es/m/CALDaNm3=JrucjhiiwsYQw5-PGtBHFONa6F7hhWCXMsGvh=tamA@mail.gmail.com
---
doc/src/sgml/ref/alter_publication.sgml | 51 ++++++++++---
src/backend/catalog/pg_publication.c | 60 ++++++++++++++-
src/backend/commands/publicationcmds.c | 93 ++++++++++++++++++++---
src/backend/commands/tablecmds.c | 3 +-
src/backend/parser/gram.y | 23 ++++++
src/bin/psql/tab-complete.in.c | 13 +++-
src/include/catalog/pg_publication.h | 4 +-
src/include/nodes/parsenodes.h | 2 +
src/test/regress/expected/publication.out | 83 +++++++++++++++++++-
src/test/regress/sql/publication.sql | 51 ++++++++++++-
src/test/subscription/t/037_except.pl | 36 ++++++++-
11 files changed, 389 insertions(+), 30 deletions(-)
diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index 028770f2149..31f8600a2ae 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -22,7 +22,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
ALTER PUBLICATION <replaceable class="parameter">name</replaceable> ADD <replaceable class="parameter">publication_object</replaceable> [, ...]
-ALTER PUBLICATION <replaceable class="parameter">name</replaceable> SET <replaceable class="parameter">publication_object</replaceable> [, ...]
+ALTER PUBLICATION <replaceable class="parameter">name</replaceable> SET { <replaceable class="parameter">publication_object</replaceable> [, ...] | <replaceable class="parameter">publication_all_object</replaceable> [, ... ] }
ALTER PUBLICATION <replaceable class="parameter">name</replaceable> DROP <replaceable class="parameter">publication_drop_object</replaceable> [, ...]
ALTER PUBLICATION <replaceable class="parameter">name</replaceable> SET ( <replaceable class="parameter">publication_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )
ALTER PUBLICATION <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
@@ -33,6 +33,11 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
TABLE <replaceable class="parameter">table_and_columns</replaceable> [, ... ]
TABLES IN SCHEMA { <replaceable class="parameter">schema_name</replaceable> | CURRENT_SCHEMA } [, ... ]
+<phrase>where <replaceable class="parameter">publication_all_object</replaceable> is one of:</phrase>
+
+ ALL TABLES [ EXCEPT TABLE ( <replaceable class="parameter">except_table_object</replaceable> [, ... ] ) ]
+ ALL SEQUENCES
+
<phrase>and <replaceable class="parameter">publication_drop_object</replaceable> is one of:</phrase>
TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ... ]
@@ -41,6 +46,10 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
<phrase>and <replaceable class="parameter">table_and_columns</replaceable> is:</phrase>
[ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [ ( <replaceable class="parameter">column_name</replaceable> [, ... ] ) ] [ WHERE ( <replaceable class="parameter">expression</replaceable> ) ]
+
+<phrase>and <replaceable class="parameter">except_table_object</replaceable> is:</phrase>
+
+ [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
</synopsis>
</refsynopsisdiv>
@@ -53,14 +62,22 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
</para>
<para>
- The first three variants change which tables/schemas are part of the
- publication. The <literal>SET</literal> clause will replace the list of
- tables/schemas in the publication with the specified list; the existing
- tables/schemas that were present in the publication will be removed. The
+ The first four variants modify which tables/schemas are included in the
+ publication, or which tables are excluded from it. The
+ <literal>SET ALL TABLES</literal> clause is used to update the
+ <literal>EXCEPT TABLE</literal> list of a <literal>FOR ALL TABLES</literal>
+ publication. If <literal>EXCEPT TABLE</literal> is specified with a list of
+ tables, the existing except table list is replaced with the specified tables.
+ If <literal>EXCEPT TABLE</literal> is omitted, the existing except table
+ list is cleared. The <literal>SET</literal> clause, when used with a
+ publication defined with <literal>FOR TABLE</literal> or
+ <literal>FOR TABLES IN SCHEMA</literal>, replaces the list of tables/schemas
+ in the publication with the specified list; the existing tables or schemas
+ that were present in the publication will be removed. The
<literal>ADD</literal> and <literal>DROP</literal> clauses will add and
remove one or more tables/schemas from the publication. Note that adding
- tables/schemas to a publication that is already subscribed to will require an
- <link linkend="sql-altersubscription-params-refresh-publication">
+ tables/except tables/schemas to a publication that is already subscribed to
+ will require an <link linkend="sql-altersubscription-params-refresh-publication">
<literal>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</literal></link> action on the
subscribing side in order to become effective. Note also that
<literal>DROP TABLES IN SCHEMA</literal> will not drop any schema tables
@@ -70,7 +87,7 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
</para>
<para>
- The fourth variant of this command listed in the synopsis can change
+ The fifth variant of this command listed in the synopsis can change
all of the publication properties specified in
<xref linkend="sql-createpublication"/>. Properties not mentioned in the
command retain their previous settings.
@@ -83,8 +100,9 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
<para>
You must own the publication to use <command>ALTER PUBLICATION</command>.
Adding a table to a publication additionally requires owning that table.
- The <literal>ADD TABLES IN SCHEMA</literal> and
- <literal>SET TABLES IN SCHEMA</literal> to a publication requires the
+ The <literal>ADD TABLES IN SCHEMA</literal>,
+ <literal>SET TABLES IN SCHEMA</literal>, and
+ <literal>SET ALL TABLES</literal> to a publication requires the
invoking user to be a superuser.
To alter the owner, you must be able to <literal>SET ROLE</literal> to the
new owning role, and that role must have <literal>CREATE</literal>
@@ -222,6 +240,19 @@ ALTER PUBLICATION mypublication ADD TABLE users (user_id, firstname), department
Change the set of columns published for a table:
<programlisting>
ALTER PUBLICATION mypublication SET TABLE users (user_id, firstname, lastname), TABLE departments;
+</programlisting></para>
+
+ <para>
+ Replace the publication's EXCEPT TABLE list:
+<programlisting>
+ALTER PUBLICATION mypublication SET ALL TABLES EXCEPT TABLE (users, departments);
+</programlisting></para>
+
+ <para>
+ Reset the publication to be a FOR ALL TABLES publication with no excluded
+ tables:
+<programlisting>
+ALTER PUBLICATION mypublication SET ALL TABLES;
</programlisting></para>
<para>
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index a79157c43bf..672e70ab8d5 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -270,6 +270,48 @@ is_schema_publication(Oid pubid)
return result;
}
+/*
+ * Returns true if there is at least one relation explicitly included in the
+ * publication.
+ */
+bool
+is_include_relation_publication(Oid pubid)
+{
+ Relation pubrelsrel;
+ ScanKeyData scankey;
+ SysScanDesc scan;
+ HeapTuple tup;
+ bool result = false;
+
+ pubrelsrel = table_open(PublicationRelRelationId, AccessShareLock);
+ ScanKeyInit(&scankey,
+ Anum_pg_publication_rel_prpubid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(pubid));
+
+ scan = systable_beginscan(pubrelsrel,
+ PublicationRelPrpubidIndexId,
+ true, NULL, 1, &scankey);
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_publication_rel pubrel;
+
+ pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
+
+ /* If we find even one included relation, we are done */
+ if (!pubrel->prexcept)
+ {
+ result = true;
+ break;
+ }
+ }
+
+ systable_endscan(scan);
+ table_close(pubrelsrel, AccessShareLock);
+
+ return result;
+}
+
/*
* Returns true if the relation has column list associated with the
* publication, false otherwise.
@@ -440,7 +482,7 @@ attnumstoint2vector(Bitmapset *attrs)
*/
ObjectAddress
publication_add_relation(Oid pubid, PublicationRelInfo *pri,
- bool if_not_exists)
+ bool if_not_exists, AlterPublicationStmt *stmt)
{
Relation rel;
HeapTuple tup;
@@ -455,6 +497,14 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri,
referenced;
List *relids = NIL;
int i;
+ bool inval_except_table;
+
+ /*
+ * True if EXCEPT tables require explicit relcache invalidation. If
+ * 'puballtables' changes, global invalidation covers them.
+ */
+ inval_except_table = (stmt != NULL) &&
+ (stmt->for_all_tables == pub->alltables);
rel = table_open(PublicationRelRelationId, RowExclusiveLock);
@@ -544,10 +594,12 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri,
/*
* Relations excluded via the EXCEPT clause do not need explicit
- * invalidation as CreatePublication() function invalidates all relations
- * as part of defining a FOR ALL TABLES publication.
+ * invalidation during CREATE PUBLICATION, as CreatePublication() function
+ * invalidates all relations as part of defining a FOR ALL TABLES
+ * publication. For ALTER PUBLICATION, explicit invalidation is still
+ * required.
*/
- if (!pri->except)
+ if (!pri->except || inval_except_table)
{
/*
* Invalidate relcache so that publication info is rebuilt.
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 6a3ca4751fa..4d2ee2543c2 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -1272,15 +1272,24 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
PublicationDropTables(pubid, rels, false);
else /* AP_SetObjects */
{
- List *oldrelids = GetIncludedPublicationRelations(pubid,
- PUBLICATION_PART_ROOT);
+ bool isexcept = pubform->puballtables;
+ List *oldrelids;
List *delrels = NIL;
ListCell *oldlc;
- TransformPubWhereClauses(rels, queryString, pubform->pubviaroot);
+ if (isexcept)
+ oldrelids = GetExcludedPublicationTables(pubid,
+ PUBLICATION_PART_ROOT);
+ else
+ {
+ oldrelids = GetIncludedPublicationRelations(pubid,
+ PUBLICATION_PART_ROOT);
- CheckPubRelationColumnList(stmt->pubname, rels, publish_schema,
- pubform->pubviaroot);
+ TransformPubWhereClauses(rels, queryString, pubform->pubviaroot);
+
+ CheckPubRelationColumnList(stmt->pubname, rels, publish_schema,
+ pubform->pubviaroot);
+ }
/*
* To recreate the relation list for the publication, look for
@@ -1498,6 +1507,16 @@ CheckAlterPublication(AlterPublicationStmt *stmt, HeapTuple tup,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to add or set schemas")));
+ if (stmt->for_all_tables && !superuser())
+ ereport(ERROR,
+ errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to alter FOR ALL TABLES publication"));
+
+ if (stmt->for_all_sequences && !superuser())
+ ereport(ERROR,
+ errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to alter FOR ALL SEQUENCES publication"));
+
/*
* Check that user is allowed to manipulate the publication tables in
* schema
@@ -1546,6 +1565,24 @@ CheckAlterPublication(AlterPublicationStmt *stmt, HeapTuple tup,
NameStr(pubform->pubname)),
errdetail("Tables or sequences cannot be added to or dropped from FOR ALL SEQUENCES publications."));
}
+
+ if (stmt->for_all_tables || stmt->for_all_sequences)
+ {
+ /*
+ * If the publication already contains specific tables or schemas, we
+ * prevent switching to a ALL state unless the publication is empty.
+ */
+ if (is_include_relation_publication(pubform->oid) ||
+ is_schema_publication(pubform->oid))
+ {
+ ereport(ERROR,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ stmt->for_all_tables ?
+ errmsg("publication \"%s\" does not support ALL TABLES operations", NameStr(pubform->pubname)) :
+ errmsg("publication \"%s\" does not support ALL SEQUENCES operations", NameStr(pubform->pubname)),
+ errdetail("This operation requires the publication to be defined as FOR ALL TABLES/SEQUENCES or to be empty."));
+ }
+ }
}
/*
@@ -1591,9 +1628,6 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
&exceptrelations, &schemaidlist);
- /* EXCEPT clause is not supported with ALTER PUBLICATION */
- Assert(exceptrelations == NIL);
-
CheckAlterPublication(stmt, tup, relations, schemaidlist);
heap_freetuple(tup);
@@ -1615,9 +1649,50 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
errmsg("publication \"%s\" does not exist",
stmt->pubname));
+ relations = list_concat(relations, exceptrelations);
AlterPublicationTables(stmt, tup, relations, pstate->p_sourcetext,
schemaidlist != NIL);
AlterPublicationSchemas(stmt, tup, schemaidlist);
+
+ if (stmt->for_all_tables || stmt->for_all_sequences)
+ {
+ bool nulls[Natts_pg_publication];
+ bool replaces[Natts_pg_publication];
+ Datum values[Natts_pg_publication];
+ bool dirty = false;
+
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ if (stmt->for_all_tables != pubform->puballtables)
+ {
+ values[Anum_pg_publication_puballtables - 1] =
+ BoolGetDatum(stmt->for_all_tables);
+ replaces[Anum_pg_publication_puballtables - 1] = true;
+ dirty = true;
+ }
+
+ if (stmt->for_all_sequences != pubform->puballsequences)
+ {
+ values[Anum_pg_publication_puballsequences - 1] =
+ BoolGetDatum(stmt->for_all_sequences);
+ replaces[Anum_pg_publication_puballsequences - 1] = true;
+ dirty = true;
+ }
+
+ if (dirty)
+ {
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values,
+ nulls, replaces);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+ CommandCounterIncrement();
+
+ /* For ALL TABLES, we must invalidate all relcache entries */
+ if (replaces[Anum_pg_publication_puballtables - 1])
+ CacheInvalidateRelcacheAll();
+ }
+ }
}
/* Cleanup. */
@@ -1953,7 +2028,7 @@ PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(rel->rd_rel->relkind),
RelationGetRelationName(rel));
- obj = publication_add_relation(pubid, pub_rel, if_not_exists);
+ obj = publication_add_relation(pubid, pub_rel, if_not_exists, stmt);
if (stmt)
{
EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 8118f7aa1ef..dcaf9b1cb89 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -20620,7 +20620,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd,
list_length(exceptpuboids),
RelationGetRelationName(attachrel),
pubnames.data),
- errdetail("The publication EXCEPT clause cannot contain tables that are partitions."));
+ errdetail("The publication EXCEPT clause cannot contain tables that are partitions."),
+ errhint("Modify the publication's EXCEPT clause using ALTER PUBLICATION ... SET ALL TABLES."));
}
list_free(exceptpuboids);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c2584249603..f361517e587 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11445,11 +11445,18 @@ pub_except_obj_list: PublicationExceptObjSpec
*
* ALTER PUBLICATION name SET pub_obj [, ...]
*
+ * ALTER PUBLICATION name SET pub_all_obj_type [, ...]
+ *
* pub_obj is one of:
*
* TABLE table_name [, ...]
* TABLES IN SCHEMA schema_name [, ...]
*
+ * pub_all_obj_type is one of:
+ *
+ * ALL TABLES [ EXCEPT TABLE ( table_name [, ...] ) ]
+ * ALL SEQUENCES
+ *
*****************************************************************************/
AlterPublicationStmt:
@@ -11459,6 +11466,7 @@ AlterPublicationStmt:
n->pubname = $3;
n->options = $5;
+ n->for_all_tables = false;
$$ = (Node *) n;
}
| ALTER PUBLICATION name ADD_P pub_obj_list
@@ -11469,6 +11477,7 @@ AlterPublicationStmt:
n->pubobjects = $5;
preprocess_pubobj_list(n->pubobjects, yyscanner);
n->action = AP_AddObjects;
+ n->for_all_tables = false;
$$ = (Node *) n;
}
| ALTER PUBLICATION name SET pub_obj_list
@@ -11479,6 +11488,19 @@ AlterPublicationStmt:
n->pubobjects = $5;
preprocess_pubobj_list(n->pubobjects, yyscanner);
n->action = AP_SetObjects;
+ n->for_all_tables = false;
+ $$ = (Node *) n;
+ }
+ | ALTER PUBLICATION name SET pub_all_obj_type_list
+ {
+ AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
+
+ n->pubname = $3;
+ n->action = AP_SetObjects;
+ preprocess_pub_all_objtype_list($5, &n->pubobjects,
+ &n->for_all_tables,
+ &n->for_all_sequences,
+ yyscanner);
$$ = (Node *) n;
}
| ALTER PUBLICATION name DROP pub_obj_list
@@ -11489,6 +11511,7 @@ AlterPublicationStmt:
n->pubobjects = $5;
preprocess_pubobj_list(n->pubobjects, yyscanner);
n->action = AP_DropObjects;
+ n->for_all_tables = false;
$$ = (Node *) n;
}
;
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 5bdbf1530a2..2f674764cad 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -2329,7 +2329,18 @@ match_previous_words(int pattern_id,
COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
/* ALTER PUBLICATION <name> SET */
else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET"))
- COMPLETE_WITH("(", "TABLES IN SCHEMA", "TABLE");
+ COMPLETE_WITH("(", "ALL SEQUENCES", "ALL TABLES", "TABLES IN SCHEMA", "TABLE");
+ else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL"))
+ COMPLETE_WITH("SEQUENCES", "TABLES");
+ else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES"))
+ COMPLETE_WITH("EXCEPT TABLE (");
+ else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT"))
+ COMPLETE_WITH("TABLE (");
+ else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "TABLE"))
+ COMPLETE_WITH("(");
+ /* Complete "ALTER PUBLICATION <name> FOR TABLE" with "<table>, ..." */
+ else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "TABLE", "("))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|DROP|SET", "TABLES", "IN", "SCHEMA"))
COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
" AND nspname NOT LIKE E'pg\\\\_%%'",
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index e25228713e7..2457385144c 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -195,10 +195,12 @@ extern Oid GetTopMostAncestorInPublication(Oid puboid, List *ancestors,
extern bool is_publishable_relation(Relation rel);
extern bool is_schema_publication(Oid pubid);
+extern bool is_include_relation_publication(Oid pubid);
extern bool check_and_fetch_column_list(Publication *pub, Oid relid,
MemoryContext mcxt, Bitmapset **cols);
extern ObjectAddress publication_add_relation(Oid pubid, PublicationRelInfo *pri,
- bool if_not_exists);
+ bool if_not_exists,
+ AlterPublicationStmt *stmt);
extern Bitmapset *pub_collist_validate(Relation targetrel, List *columns);
extern ObjectAddress publication_add_schema(Oid pubid, Oid schemaid,
bool if_not_exists);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ffadd667167..bd3bf81cfbf 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -4525,6 +4525,8 @@ typedef struct AlterPublicationStmt
List *pubobjects; /* Optional list of publication objects */
AlterPublicationAction action; /* What action to perform with the given
* objects */
+ bool for_all_tables; /* True if SET ALL TABLES is specified */
+ bool for_all_sequences; /* True if SET ALL SEQUENCES is specified */
} AlterPublicationStmt;
typedef struct CreateSubscriptionStmt
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 681d2564ed5..e47ac42d636 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -126,6 +126,13 @@ ALTER PUBLICATION testpub_fortable SET TABLES IN SCHEMA pub_test;
Tables from schemas:
"pub_test"
+-- fail - SET ALL TABLES is not allowed for a 'FOR TABLE' publication
+ALTER PUBLICATION testpub_fortable SET ALL TABLES EXCEPT TABLE (testpub_tbl1);
+ERROR: publication "testpub_fortable" does not support ALL TABLES operations
+DETAIL: This operation requires the publication to be defined as FOR ALL TABLES/SEQUENCES or to be empty.
+ALTER PUBLICATION testpub_fortable SET ALL TABLES;
+ERROR: publication "testpub_fortable" does not support ALL TABLES operations
+DETAIL: This operation requires the publication to be defined as FOR ALL TABLES/SEQUENCES or to be empty.
SET client_min_messages = 'ERROR';
CREATE PUBLICATION testpub_forschema FOR TABLES IN SCHEMA pub_test;
-- should be able to create publication with schema and table of the same
@@ -213,6 +220,49 @@ Not-null constraints:
regress_publication_user | t | f | t | t | f | f | none | f |
(1 row)
+-- fail - SET ALL TABLES is not allowed for a schema publication
+ALTER PUBLICATION testpub_forschema SET ALL TABLES EXCEPT TABLE (pub_test.testpub_nopk);
+ERROR: publication "testpub_forschema" does not support ALL TABLES operations
+DETAIL: This operation requires the publication to be defined as FOR ALL TABLES/SEQUENCES or to be empty.
+ALTER PUBLICATION testpub_forschema SET ALL TABLES;
+ERROR: publication "testpub_forschema" does not support ALL TABLES operations
+DETAIL: This operation requires the publication to be defined as FOR ALL TABLES/SEQUENCES or to be empty.
+---------------------------------------------
+-- SET ALL TABLES/SEQUENCES
+---------------------------------------------
+SET client_min_messages = 'ERROR';
+CREATE PUBLICATION testpub_forall_tbls_seqs;
+-- Enable both puballtables and puballsequences
+ALTER PUBLICATION testpub_forall_tbls_seqs SET ALL TABLES, ALL SEQUENCES;
+\dRp+ testpub_forall_tbls_seqs
+ Publication testpub_forall_tbls_seqs
+ Owner | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description
+--------------------------+------------+---------------+---------+---------+---------+-----------+-------------------+----------+-------------
+ regress_publication_user | t | t | t | t | t | t | none | f |
+(1 row)
+
+-- Explicitly test that SET ALL TABLES resets puballsequences to false
+-- Result should be: puballtables = true, puballsequences = false
+ALTER PUBLICATION testpub_forall_tbls_seqs SET ALL TABLES;
+\dRp+ testpub_forall_tbls_seqs
+ Publication testpub_forall_tbls_seqs
+ Owner | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description
+--------------------------+------------+---------------+---------+---------+---------+-----------+-------------------+----------+-------------
+ regress_publication_user | t | f | t | t | t | t | none | f |
+(1 row)
+
+-- Explicitly test that SET ALL SEQUENCES resets puballtables to false
+-- Result should be: puballtables = false, puballsequences = true
+ALTER PUBLICATION testpub_forall_tbls_seqs SET ALL SEQUENCES;
+\dRp+ testpub_forall_tbls_seqs
+ Publication testpub_forall_tbls_seqs
+ Owner | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description
+--------------------------+------------+---------------+---------+---------+---------+-----------+-------------------+----------+-------------
+ regress_publication_user | f | t | t | t | t | t | none | f |
+(1 row)
+
+RESET client_min_messages;
+DROP PUBLICATION testpub_forall_tbls_seqs;
---------------------------------------------
-- EXCEPT TABLE tests for normal tables
---------------------------------------------
@@ -254,6 +304,25 @@ Except Publications:
"testpub_foralltables_excepttable"
"testpub_foralltables_excepttable1"
+-- Remove all the EXCEPT tables.
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES;
+\dRp+ testpub_foralltables_excepttable
+ Publication testpub_foralltables_excepttable
+ Owner | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description
+--------------------------+------------+---------------+---------+---------+---------+-----------+-------------------+----------+-------------
+ regress_publication_user | t | f | t | t | t | t | none | f |
+(1 row)
+
+-- Replace the publication EXCEPT table list with a specific EXCEPT table.
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES EXCEPT TABLE (testpub_tbl1);
+\dRp+ testpub_foralltables_excepttable
+ Publication testpub_foralltables_excepttable
+ Owner | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description
+--------------------------+------------+---------------+---------+---------+---------+-----------+-------------------+----------+-------------
+ regress_publication_user | t | f | t | t | t | t | none | f |
+Except tables:
+ "public.testpub_tbl1"
+
RESET client_min_messages;
DROP TABLE testpub_tbl2;
DROP PUBLICATION testpub_foralltables, testpub_fortable, testpub_forschema, testpub_for_tbl_schema, testpub_foralltables_excepttable, testpub_foralltables_excepttable1;
@@ -361,6 +430,7 @@ CREATE TABLE tab_main (a int) PARTITION BY RANGE(a);
ALTER TABLE tab_main ATTACH PARTITION testpub_root FOR VALUES FROM (0) TO (200);
ERROR: cannot attach table "testpub_root" as partition because it is referenced in publication "testpub8" EXCEPT clause
DETAIL: The publication EXCEPT clause cannot contain tables that are partitions.
+HINT: Modify the publication's EXCEPT clause using ALTER PUBLICATION ... SET ALL TABLES.
RESET client_min_messages;
DROP TABLE testpub_root, testpub_part1, tab_main;
DROP PUBLICATION testpub8;
@@ -1541,7 +1611,18 @@ ERROR: permission denied to change owner of publication "testpub4"
HINT: The owner of a FOR ALL TABLES or ALL SEQUENCES or TABLES IN SCHEMA publication must be a superuser.
ALTER PUBLICATION testpub4 owner to regress_publication_user; -- ok
SET ROLE regress_publication_user;
-DROP PUBLICATION testpub4;
+SET client_min_messages = 'ERROR';
+CREATE PUBLICATION testpub5 FOR ALL TABLES;
+RESET client_min_messages;
+ALTER PUBLICATION testpub5 OWNER TO regress_publication_user3;
+SET ROLE regress_publication_user3;
+-- fail - SET ALL TABLES on a publication requires superuser privileges
+ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT TABLE (testpub_tbl1); -- fail
+ERROR: must be superuser to alter FOR ALL TABLES publication
+ALTER PUBLICATION testpub5 SET ALL TABLES; -- fail
+ERROR: must be superuser to alter FOR ALL TABLES publication
+SET ROLE regress_publication_user;
+DROP PUBLICATION testpub4, testpub5;
DROP ROLE regress_publication_user3;
REVOKE CREATE ON DATABASE regression FROM regress_publication_user2;
DROP TABLE testpub_parted;
diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql
index 405579dad52..844b9c7cb5c 100644
--- a/src/test/regress/sql/publication.sql
+++ b/src/test/regress/sql/publication.sql
@@ -74,6 +74,10 @@ ALTER PUBLICATION testpub_fortable DROP TABLES IN SCHEMA pub_test;
ALTER PUBLICATION testpub_fortable SET TABLES IN SCHEMA pub_test;
\dRp+ testpub_fortable
+-- fail - SET ALL TABLES is not allowed for a 'FOR TABLE' publication
+ALTER PUBLICATION testpub_fortable SET ALL TABLES EXCEPT TABLE (testpub_tbl1);
+ALTER PUBLICATION testpub_fortable SET ALL TABLES;
+
SET client_min_messages = 'ERROR';
CREATE PUBLICATION testpub_forschema FOR TABLES IN SCHEMA pub_test;
-- should be able to create publication with schema and table of the same
@@ -105,6 +109,33 @@ SELECT pubname, puballtables FROM pg_publication WHERE pubname = 'testpub_forall
\d+ testpub_tbl2
\dRp+ testpub_foralltables
+-- fail - SET ALL TABLES is not allowed for a schema publication
+ALTER PUBLICATION testpub_forschema SET ALL TABLES EXCEPT TABLE (pub_test.testpub_nopk);
+ALTER PUBLICATION testpub_forschema SET ALL TABLES;
+
+---------------------------------------------
+-- SET ALL TABLES/SEQUENCES
+---------------------------------------------
+SET client_min_messages = 'ERROR';
+CREATE PUBLICATION testpub_forall_tbls_seqs;
+
+-- Enable both puballtables and puballsequences
+ALTER PUBLICATION testpub_forall_tbls_seqs SET ALL TABLES, ALL SEQUENCES;
+\dRp+ testpub_forall_tbls_seqs
+
+-- Explicitly test that SET ALL TABLES resets puballsequences to false
+-- Result should be: puballtables = true, puballsequences = false
+ALTER PUBLICATION testpub_forall_tbls_seqs SET ALL TABLES;
+\dRp+ testpub_forall_tbls_seqs
+
+-- Explicitly test that SET ALL SEQUENCES resets puballtables to false
+-- Result should be: puballtables = false, puballsequences = true
+ALTER PUBLICATION testpub_forall_tbls_seqs SET ALL SEQUENCES;
+\dRp+ testpub_forall_tbls_seqs
+
+RESET client_min_messages;
+DROP PUBLICATION testpub_forall_tbls_seqs;
+
---------------------------------------------
-- EXCEPT TABLE tests for normal tables
---------------------------------------------
@@ -119,6 +150,14 @@ CREATE PUBLICATION testpub_foralltables_excepttable1 FOR ALL TABLES EXCEPT TABLE
-- in the EXCEPT TABLE clause
\d testpub_tbl1
+-- Remove all the EXCEPT tables.
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES;
+\dRp+ testpub_foralltables_excepttable
+
+-- Replace the publication EXCEPT table list with a specific EXCEPT table.
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES EXCEPT TABLE (testpub_tbl1);
+\dRp+ testpub_foralltables_excepttable
+
RESET client_min_messages;
DROP TABLE testpub_tbl2;
DROP PUBLICATION testpub_foralltables, testpub_fortable, testpub_forschema, testpub_for_tbl_schema, testpub_foralltables_excepttable, testpub_foralltables_excepttable1;
@@ -991,7 +1030,17 @@ ALTER PUBLICATION testpub4 owner to regress_publication_user2; -- fail
ALTER PUBLICATION testpub4 owner to regress_publication_user; -- ok
SET ROLE regress_publication_user;
-DROP PUBLICATION testpub4;
+SET client_min_messages = 'ERROR';
+CREATE PUBLICATION testpub5 FOR ALL TABLES;
+RESET client_min_messages;
+ALTER PUBLICATION testpub5 OWNER TO regress_publication_user3;
+SET ROLE regress_publication_user3;
+-- fail - SET ALL TABLES on a publication requires superuser privileges
+ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT TABLE (testpub_tbl1); -- fail
+ALTER PUBLICATION testpub5 SET ALL TABLES; -- fail
+
+SET ROLE regress_publication_user;
+DROP PUBLICATION testpub4, testpub5;
DROP ROLE regress_publication_user3;
REVOKE CREATE ON DATABASE regression FROM regress_publication_user2;
diff --git a/src/test/subscription/t/037_except.pl b/src/test/subscription/t/037_except.pl
index 2729df4d5c0..cbfe42011ef 100644
--- a/src/test/subscription/t/037_except.pl
+++ b/src/test/subscription/t/037_except.pl
@@ -152,18 +152,50 @@ $result =
$node_subscriber->safe_psql('postgres', "SELECT count(*) FROM child1");
is($result, qq(10), 'check replicated inserts on subscriber');
+$node_publisher->safe_psql('postgres',
+ "CREATE TABLE tab2 AS SELECT generate_series(1,10) AS a");
+$node_subscriber->safe_psql('postgres', "CREATE TABLE tab2 (a int)");
+
+# Replace the EXCEPT TABLE list so that only tab2 is excluded.
+$node_publisher->safe_psql('postgres',
+ "ALTER PUBLICATION tab_pub SET ALL TABLES EXCEPT TABLE (tab2)");
+
+# Refresh the subscription so the subscriber picks up the updated
+# publication definition and initiates table synchronization.
+$node_subscriber->safe_psql('postgres',
+ "ALTER SUBSCRIPTION tab_sub REFRESH PUBLICATION");
+
+# Wait for initial table sync to finish
+$node_subscriber->wait_for_subscription_sync($node_publisher, 'tab_sub');
+
+# Verify that initial table synchronization does not occur for tables
+# listed in the EXCEPT TABLE clause.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM tab2");
+is($result, qq(0),
+ 'check there is no initial data copied for the tables specified in the EXCEPT TABLE clause'
+);
+
+# Verify that table synchronization occurs once tab1 is removed from the
+# EXCEPT TABLE clause via SET ALL TABLES EXCEPT TABLE.
+$result =
+ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM tab1");
+is($result, qq(20),
+ 'check that the data is copied as the tab1 is removed from EXCEPT TABLE clause'
+);
+
# cleanup
$node_subscriber->safe_psql(
'postgres', qq(
DROP SUBSCRIPTION tab_sub;
TRUNCATE TABLE tab1;
- DROP TABLE parent, parent1, child, child1;
+ DROP TABLE parent, parent1, child, child1, tab2;
));
$node_publisher->safe_psql(
'postgres', qq(
DROP PUBLICATION tab_pub;
TRUNCATE TABLE tab1;
- DROP TABLE parent, parent1, child, child1;
+ DROP TABLE parent, parent1, child, child1, tab2;
));
# ============================================
--
2.43.0
view thread (377+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
Subject: Re: Skipping schema changes in publication
In-Reply-To: <CALDaNm2OOgmNOPpABUU+AXzHhfrLG9HMfSd3jfNe=t3dc-kp1Q@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox