v53-0002-Support-SET-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch
application/octet-stream
Filename: v53-0002-Support-SET-EXCEPT-TABLE-in-ALTER-PUBLICATION.patch
Type: application/octet-stream
Part: 2
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v53-0002
Subject: Support SET EXCEPT TABLE in ALTER PUBLICATION
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/alter_publication.sgml | 21 | 8 |
| src/backend/catalog/pg_publication.c | 6 | 4 |
| src/backend/commands/publicationcmds.c | 28 | 11 |
| src/backend/commands/tablecmds.c | 2 | 1 |
| src/backend/parser/gram.y | 64 | 13 |
| src/bin/psql/tab-complete.in.c | 4 | 2 |
| src/include/catalog/pg_publication.h | 2 | 1 |
| src/test/regress/expected/publication.out | 37 | 0 |
| src/test/regress/sql/publication.sql | 24 | 0 |
From 7df6aa8158313de71fdde409d41ef704e5e88b37 Mon Sep 17 00:00:00 2001
From: Vignesh C <vignesh21@gmail.com>
Date: Sat, 28 Feb 2026 12:12:38 +0530
Subject: [PATCH v53 2/3] Support SET EXCEPT TABLE in ALTER PUBLICATION
Extend ALTER PUBLICATION to support SET EXCEPT TABLE for
publications defined with FOR ALL TABLES.
---
doc/src/sgml/ref/alter_publication.sgml | 29 ++++++---
src/backend/catalog/pg_publication.c | 10 +--
src/backend/commands/publicationcmds.c | 39 ++++++++----
src/backend/commands/tablecmds.c | 3 +-
src/backend/parser/gram.y | 77 +++++++++++++++++++----
src/bin/psql/tab-complete.in.c | 6 +-
src/include/catalog/pg_publication.h | 3 +-
src/test/regress/expected/publication.out | 37 +++++++++++
src/test/regress/sql/publication.sql | 24 +++++++
9 files changed, 188 insertions(+), 40 deletions(-)
diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index 028770f2149..7c28391033e 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -21,18 +21,24 @@ 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> ADD <replaceable class="parameter">publication_add_object</replaceable> [, ...]
+ALTER PUBLICATION <replaceable class="parameter">name</replaceable> SET <replaceable class="parameter">publication_set_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 }
ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
-<phrase>where <replaceable class="parameter">publication_object</replaceable> is one of:</phrase>
+<phrase>where <replaceable class="parameter">publication_add_object</replaceable> is one of:</phrase>
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_set_object</replaceable> is one of:</phrase>
+
+ EXCEPT TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [, ... ]
+ TABLE <replaceable class="parameter">table_and_columns</replaceable> [, ... ]
+ TABLES IN SCHEMA { <replaceable class="parameter">schema_name</replaceable> | CURRENT_SCHEMA } [, ... ]
+
<phrase>and <replaceable class="parameter">publication_drop_object</replaceable> is one of:</phrase>
TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ... ]
@@ -55,11 +61,12 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
<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
- <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
+ except tables/tables/schemas in the publication with the specified list; the
+ existing except tables/tables/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">
<literal>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</literal></link> action on the
subscribing side in order to become effective. Note also that
@@ -222,6 +229,12 @@ 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 EXCEPT TABLE users, departments;
</programlisting></para>
<para>
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index e1b1532c464..48570fcff82 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -441,7 +441,7 @@ attnumstoint2vector(Bitmapset *attrs)
*/
ObjectAddress
publication_add_relation(Oid pubid, PublicationRelInfo *pri,
- bool if_not_exists)
+ bool if_not_exists, bool is_alter)
{
Relation rel;
HeapTuple tup;
@@ -545,10 +545,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 || is_alter)
{
/*
* Invalidate relcache so that publication info is rebuilt.
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 6a3ca4751fa..166fe3b0c3d 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
@@ -1488,7 +1497,7 @@ AlterPublicationSchemas(AlterPublicationStmt *stmt,
*/
static void
CheckAlterPublication(AlterPublicationStmt *stmt, HeapTuple tup,
- List *tables, List *schemaidlist)
+ List *tables, List *excepttables, List *schemaidlist)
{
Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
@@ -1546,6 +1555,14 @@ CheckAlterPublication(AlterPublicationStmt *stmt, HeapTuple tup,
NameStr(pubform->pubname)),
errdetail("Tables or sequences cannot be added to or dropped from FOR ALL SEQUENCES publications."));
}
+
+ /* Check that user is allowed to manipulate the publication tables. */
+ if (excepttables && !pubform->puballtables)
+ ereport(ERROR,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("publication \"%s\" is not defined as FOR ALL TABLES",
+ NameStr(pubform->pubname)),
+ errdetail("EXCEPT Tables cannot be added to publications that are not defined as FOR ALL TABLES."));
}
/*
@@ -1591,10 +1608,8 @@ 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);
+ CheckAlterPublication(stmt, tup, relations, exceptrelations,
+ schemaidlist);
heap_freetuple(tup);
@@ -1615,6 +1630,7 @@ 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);
@@ -1953,7 +1969,8 @@ 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 != NULL));
if (stmt)
{
EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index c0104f084fb..cedbdd38570 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -20394,7 +20394,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 EXCEPT TABLE before attaching the table."));
}
list_free(exceptpuboids);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index f4d49b6018d..0544908fcb9 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -207,7 +207,7 @@ static void preprocess_pub_all_objtype_list(List *all_objects_list,
bool *all_tables,
bool *all_sequences,
core_yyscan_t yyscanner);
-static void preprocess_pubobj_list(List *pubobjspec_list,
+static bool preprocess_pubobj_list(List *pubobjspec_list,
core_yyscan_t yyscanner);
static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
@@ -581,7 +581,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
Bit ConstBit BitWithLength BitWithoutLength
%type <str> character
%type <str> extract_arg
-%type <boolean> opt_varying opt_timezone opt_no_inherit
+%type <boolean> opt_varying opt_timezone opt_no_inherit opt_except
%type <ival> Iconst SignedIconst
%type <str> Sconst comment_text notify_payload
@@ -10830,16 +10830,28 @@ CreatePublicationStmt:
}
| CREATE PUBLICATION name FOR pub_obj_list opt_definition
{
+ bool has_except_table;
CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
n->pubname = $3;
n->options = $6;
n->pubobjects = (List *) $5;
- preprocess_pubobj_list(n->pubobjects, yyscanner);
+ has_except_table = preprocess_pubobj_list(n->pubobjects,
+ yyscanner);
+ if (has_except_table)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("EXCEPT TABLE clause allowed only for ALL TABLES PUBLICATION"));
+
$$ = (Node *) n;
}
;
+opt_except:
+ EXCEPT { $$ = true; }
+ | /*EMPTY*/ { $$ = false; }
+ ;
+
/*
* FOR TABLE and FOR TABLES IN SCHEMA specifications
*
@@ -10854,14 +10866,14 @@ CreatePublicationStmt:
* relation_expr here.
*/
PublicationObjSpec:
- TABLE relation_expr opt_column_list OptWhereClause
+ opt_except TABLE relation_expr opt_column_list OptWhereClause
{
$$ = makeNode(PublicationObjSpec);
- $$->pubobjtype = PUBLICATIONOBJ_TABLE;
+ $$->pubobjtype = ($1) ? PUBLICATIONOBJ_EXCEPT_TABLE : PUBLICATIONOBJ_TABLE;
$$->pubtable = makeNode(PublicationTable);
- $$->pubtable->relation = $2;
- $$->pubtable->columns = $3;
- $$->pubtable->whereClause = $4;
+ $$->pubtable->relation = $3;
+ $$->pubtable->columns = $4;
+ $$->pubtable->whereClause = $5;
}
| TABLES IN_P SCHEMA ColId
{
@@ -11010,11 +11022,18 @@ AlterPublicationStmt:
}
| ALTER PUBLICATION name ADD_P pub_obj_list
{
+ bool has_except_table = false;
AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
n->pubname = $3;
n->pubobjects = $5;
- preprocess_pubobj_list(n->pubobjects, yyscanner);
+ has_except_table = preprocess_pubobj_list(n->pubobjects,
+ yyscanner);
+ if (has_except_table)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("EXCEPT TABLE clause allowed only for SET clause"));
+
n->action = AP_AddObjects;
$$ = (Node *) n;
}
@@ -11030,11 +11049,18 @@ AlterPublicationStmt:
}
| ALTER PUBLICATION name DROP pub_obj_list
{
+ bool has_except_table = false;
AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
n->pubname = $3;
n->pubobjects = $5;
- preprocess_pubobj_list(n->pubobjects, yyscanner);
+ has_except_table = preprocess_pubobj_list(n->pubobjects,
+ yyscanner);
+ if (has_except_table)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("EXCEPT TABLE clause allowed only for SET clause"));
+
n->action = AP_DropObjects;
$$ = (Node *) n;
}
@@ -19880,16 +19906,19 @@ preprocess_pub_all_objtype_list(List *all_objects_list, List **pubobjects,
/*
* Process pubobjspec_list to check for errors in any of the objects and
* convert PUBLICATIONOBJ_CONTINUATION into appropriate PublicationObjSpecType.
+ *
+ * Return true if an EXCEPT table is found.
*/
-static void
+static bool
preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner)
{
ListCell *cell;
PublicationObjSpec *pubobj;
PublicationObjSpecType prevobjtype = PUBLICATIONOBJ_CONTINUATION;
+ bool foundexcepttable = false;
if (!pubobjspec_list)
- return;
+ return false;
pubobj = (PublicationObjSpec *) linitial(pubobjspec_list);
if (pubobj->pubobjtype == PUBLICATIONOBJ_CONTINUATION)
@@ -19906,7 +19935,8 @@ preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner)
if (pubobj->pubobjtype == PUBLICATIONOBJ_CONTINUATION)
pubobj->pubobjtype = prevobjtype;
- if (pubobj->pubobjtype == PUBLICATIONOBJ_TABLE)
+ if (pubobj->pubobjtype == PUBLICATIONOBJ_TABLE ||
+ pubobj->pubobjtype == PUBLICATIONOBJ_EXCEPT_TABLE)
{
/* relation name or pubtable must be set for this type of object */
if (!pubobj->name && !pubobj->pubtable)
@@ -19925,6 +19955,25 @@ preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner)
pubobj->pubtable = pubtable;
pubobj->name = NULL;
}
+
+ if (pubobj->pubobjtype == PUBLICATIONOBJ_EXCEPT_TABLE)
+ {
+ foundexcepttable = true;
+
+ /* WHERE clause is not allowed on an except table */
+ if (pubobj->pubtable->whereClause)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("WHERE clause not allowed for except table"),
+ parser_errposition(pubobj->location));
+
+ /* Column list is not allowed on a except table */
+ if (pubobj->pubtable && pubobj->pubtable->columns)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("column specification not allowed for except table"),
+ parser_errposition(pubobj->location));
+ }
}
else if (pubobj->pubobjtype == PUBLICATIONOBJ_TABLES_IN_SCHEMA ||
pubobj->pubobjtype == PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA)
@@ -19960,6 +20009,8 @@ preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner)
prevobjtype = pubobj->pubobjtype;
}
+
+ return foundexcepttable;
}
/*----------
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 8927f7e6f22..f45f3b76523 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -2318,9 +2318,11 @@ match_previous_words(int pattern_id,
/* ALTER PUBLICATION <name> DROP */
else if (Matches("ALTER", "PUBLICATION", MatchAny, "DROP"))
COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
- /* ALTER PUBLICATION <name> SET */
+ /* ALTER PUBLICATION <name> SET */
else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET"))
- COMPLETE_WITH("(", "TABLES IN SCHEMA", "TABLE");
+ COMPLETE_WITH("(", "EXCEPT", "TABLES IN SCHEMA", "TABLE");
+ else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "EXCEPT"))
+ COMPLETE_WITH("TABLE");
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 a9f89e89006..b012e753b64 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -199,7 +199,8 @@ extern bool publication_has_any_except_table(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,
+ bool is_alter);
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/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 85da81a1f27..3c70c51ddec 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -126,6 +126,16 @@ ALTER PUBLICATION testpub_fortable SET TABLES IN SCHEMA pub_test;
Tables from schemas:
"pub_test"
+-- fail - can't add an EXCEPT TABLE to 'FOR TABLE' publication
+ALTER PUBLICATION testpub_fortable ADD EXCEPT TABLE testpub_tbl1;
+ERROR: EXCEPT TABLE clause allowed only for SET clause
+-- fail - can't drop an EXCEPT TABLE from 'FOR TABLE' publication
+ALTER PUBLICATION testpub_fortable DROP EXCEPT TABLE testpub_tbl1;
+ERROR: EXCEPT TABLE clause allowed only for SET clause
+-- fail - can't set an EXCEPT TABLE to 'FOR TABLE' publication
+ALTER PUBLICATION testpub_fortable SET EXCEPT TABLE testpub_tbl1;
+ERROR: publication "testpub_fortable" is not defined as FOR ALL TABLES
+DETAIL: EXCEPT Tables cannot be added to publications that are not defined as FOR 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
@@ -213,6 +223,16 @@ Not-null constraints:
regress_publication_user | t | f | t | t | f | f | none | f
(1 row)
+-- fail - can't add an EXCEPT TABLE to schema publication
+ALTER PUBLICATION testpub_forschema ADD EXCEPT TABLE pub_test.testpub_nopk;
+ERROR: EXCEPT TABLE clause allowed only for SET clause
+-- fail - can't drop an EXCEPT TABLE from schema publication
+ALTER PUBLICATION testpub_forschema DROP EXCEPT TABLE pub_test.testpub_nopk;
+ERROR: EXCEPT TABLE clause allowed only for SET clause
+-- fail - can't set an EXCEPT TABLE to schema publication
+ALTER PUBLICATION testpub_forschema SET EXCEPT TABLE pub_test.testpub_nopk;
+ERROR: publication "testpub_forschema" is not defined as FOR ALL TABLES
+DETAIL: EXCEPT Tables cannot be added to publications that are not defined as FOR ALL TABLES.
---------------------------------------------
-- EXCEPT TABLE tests for normal tables
---------------------------------------------
@@ -255,6 +275,22 @@ Except Publications:
"testpub_foralltables_excepttable"
"testpub_foralltables_excepttable1"
+-- Replace the publication EXCEPT table list with a specific EXCEPT table.
+ALTER PUBLICATION testpub_foralltables_excepttable SET 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
+--------------------------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
+ regress_publication_user | t | f | t | t | t | t | none | f
+Except tables:
+ "public.testpub_tbl1"
+
+-- fail - Dropping EXCEPT table is not supported.
+ALTER PUBLICATION testpub_foralltables_excepttable DROP EXCEPT TABLE testpub_tbl1;
+ERROR: EXCEPT TABLE clause allowed only for SET clause
+-- fail - Adding EXCEPT table is not supported.
+ALTER PUBLICATION testpub_foralltables_excepttable ADD EXCEPT TABLE testpub_tbl1;
+ERROR: EXCEPT TABLE clause allowed only for SET clause
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;
@@ -344,6 +380,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 EXCEPT TABLE before attaching the table.
RESET client_min_messages;
DROP TABLE testpub_root, testpub_part1, testpub_part2, tab_main;
DROP PUBLICATION testpub8;
diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql
index 507028bed32..957b2d183f9 100644
--- a/src/test/regress/sql/publication.sql
+++ b/src/test/regress/sql/publication.sql
@@ -74,6 +74,13 @@ ALTER PUBLICATION testpub_fortable DROP TABLES IN SCHEMA pub_test;
ALTER PUBLICATION testpub_fortable SET TABLES IN SCHEMA pub_test;
\dRp+ testpub_fortable
+-- fail - can't add an EXCEPT TABLE to 'FOR TABLE' publication
+ALTER PUBLICATION testpub_fortable ADD EXCEPT TABLE testpub_tbl1;
+-- fail - can't drop an EXCEPT TABLE from 'FOR TABLE' publication
+ALTER PUBLICATION testpub_fortable DROP EXCEPT TABLE testpub_tbl1;
+-- fail - can't set an EXCEPT TABLE to 'FOR TABLE' publication
+ALTER PUBLICATION testpub_fortable SET EXCEPT TABLE testpub_tbl1;
+
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 +112,13 @@ SELECT pubname, puballtables FROM pg_publication WHERE pubname = 'testpub_forall
\d+ testpub_tbl2
\dRp+ testpub_foralltables
+-- fail - can't add an EXCEPT TABLE to schema publication
+ALTER PUBLICATION testpub_forschema ADD EXCEPT TABLE pub_test.testpub_nopk;
+-- fail - can't drop an EXCEPT TABLE from schema publication
+ALTER PUBLICATION testpub_forschema DROP EXCEPT TABLE pub_test.testpub_nopk;
+-- fail - can't set an EXCEPT TABLE to schema publication
+ALTER PUBLICATION testpub_forschema SET EXCEPT TABLE pub_test.testpub_nopk;
+
---------------------------------------------
-- EXCEPT TABLE tests for normal tables
---------------------------------------------
@@ -120,6 +134,16 @@ CREATE PUBLICATION testpub_foralltables_excepttable1 FOR ALL TABLES EXCEPT TABLE
-- in the EXCEPT clause
\d testpub_tbl1
+-- Replace the publication EXCEPT table list with a specific EXCEPT table.
+ALTER PUBLICATION testpub_foralltables_excepttable SET EXCEPT TABLE testpub_tbl1;
+\dRp+ testpub_foralltables_excepttable
+
+-- fail - Dropping EXCEPT table is not supported.
+ALTER PUBLICATION testpub_foralltables_excepttable DROP EXCEPT TABLE testpub_tbl1;
+
+-- fail - Adding EXCEPT table is not supported.
+ALTER PUBLICATION testpub_foralltables_excepttable ADD EXCEPT TABLE 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;
--
2.43.0