v2-0003-Support-EXCEPT-for-ALL-SEQUENCES-in-ALTER-PUBLICA.patch

application/octet-stream

Filename: v2-0003-Support-EXCEPT-for-ALL-SEQUENCES-in-ALTER-PUBLICA.patch
Type: application/octet-stream
Part: 2
Message: Re: Support EXCEPT for ALL SEQUENCES publications

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 v2-0003
Subject: Support EXCEPT for ALL SEQUENCES in ALTER PUBLICATION
File+
doc/src/sgml/ref/alter_publication.sgml 15 7
src/backend/catalog/pg_publication.c 18 9
src/backend/commands/publicationcmds.c 130 117
src/bin/psql/tab-complete.in.c 14 0
src/include/catalog/pg_publication.h 2 1
src/test/regress/expected/publication.out 16 0
src/test/regress/sql/publication.sql 5 0
From 34cb3972c075b29b13833db41e64e40e30596115 Mon Sep 17 00:00:00 2001
From: Shlok Kyal <shlok.kyal.oss@gmail.com>
Date: Sat, 11 Apr 2026 23:39:50 +0530
Subject: [PATCH v2 3/3] Support EXCEPT for ALL SEQUENCES in ALTER PUBLICATION

Extend ALTER PUBLICATION to support an EXCEPT clause when using
ALL SEQUENCES, allowing specific sequences to be excluded from the
publication.

If the EXCEPT clause is specified, the existing exclusion list for the
publication is replaced with the provided sequences. If the EXCEPT
clause is omitted, any existing exclusions for sequences are cleared.

Example:

  ALTER PUBLICATION pub1 SET ALL SEQUENCES;

This clears any existing sequence exclusions for the publication.

  ALTER PUBLICATION pub1 SET ALL SEQUENCES EXCEPT (SEQUENCE s1, s2);

This sets the exclusion list to the specified sequences.
---
 doc/src/sgml/ref/alter_publication.sgml   |  22 +-
 src/backend/catalog/pg_publication.c      |  27 ++-
 src/backend/commands/publicationcmds.c    | 247 ++++++++++++----------
 src/bin/psql/tab-complete.in.c            |  14 ++
 src/include/catalog/pg_publication.h      |   3 +-
 src/test/regress/expected/publication.out |  16 ++
 src/test/regress/sql/publication.sql      |   5 +
 7 files changed, 200 insertions(+), 134 deletions(-)

diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index aa32bb169e9..3ce1d5d1539 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -36,7 +36,7 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
 <phrase>and <replaceable class="parameter">publication_all_object</replaceable> is one of:</phrase>
 
     ALL TABLES [ EXCEPT ( <replaceable class="parameter">except_table_object</replaceable> [, ... ] ) ]
-    ALL SEQUENCES
+    ALL SEQUENCES [ EXCEPT ( <replaceable class="parameter">except_sequence_object</replaceable> [, ... ] ) ]
 
 <phrase>and <replaceable class="parameter">publication_drop_object</replaceable> is one of:</phrase>
 
@@ -54,6 +54,10 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
 <phrase>and <replaceable class="parameter">table_object</replaceable> is:</phrase>
 
    [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
+
+<phrase>and <replaceable class="parameter">except_sequence_object</replaceable> is:</phrase>
+
+    SEQUENCE <replaceable class="parameter">sequence_name</replaceable> [, ... ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -75,7 +79,7 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
    The third variant either modifies the included tables/schemas
    or marks the publication as <literal>FOR ALL SEQUENCES</literal> or
    <literal>FOR ALL TABLES</literal>, optionally using
-   <literal>EXCEPT</literal> to exclude specific tables. The
+   <literal>EXCEPT</literal> to exclude specific tables or sequences. The
    <literal>SET ALL TABLES</literal> clause can transform an empty publication,
    or one defined for <literal>ALL SEQUENCES</literal> (or both
    <literal>ALL TABLES</literal> and <literal>ALL SEQUENCES</literal>), into
@@ -86,11 +90,15 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
    publication defined for <literal>ALL SEQUENCES</literal>. In addition,
    <literal>SET ALL TABLES</literal> can be used to update the tables specified
    in the <literal>EXCEPT</literal> clause of a
-   <literal>FOR ALL TABLES</literal> publication. If <literal>EXCEPT</literal>
-   is specified with a list of tables, the existing exclusion list is replaced
-   with the specified tables. If <literal>EXCEPT</literal> is omitted, the
-   existing exclusion list is cleared. The <literal>SET</literal> clause, when
-   used with a publication defined with <literal>FOR TABLE</literal> or
+   <literal>FOR ALL TABLES</literal> publication and
+   <literal>SET ALL SEQUENCES</literal> can be used to update the sequences
+   specified in the <literal>EXCEPT</literal> clause of a
+   <literal>FOR ALL SEQUENCES</literal> publication. If
+   <literal>EXCEPT</literal> is specified with a list of tables or sequences,
+   the existing exclusion list is replaced with the specified tables or
+   sequences. If <literal>EXCEPT</literal> is omitted, the existing exclusion
+   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.
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index cbbc77592d6..013e52ddf74 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -933,7 +933,7 @@ GetRelationExcludedPublications(Oid relid)
  */
 static List *
 get_publication_relations(Oid pubid, PublicationPartOpt pub_partopt,
-						  bool except_flag)
+						  bool except_flag, char pubrelkind)
 {
 	List	   *result;
 	Relation	pubrelsrel;
@@ -960,8 +960,15 @@ get_publication_relations(Oid pubid, PublicationPartOpt pub_partopt,
 		pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
 
 		if (except_flag == pubrel->prexcept)
-			result = GetPubPartitionOptionRelations(result, pub_partopt,
-													pubrel->prrelid);
+		{
+			char		relkind = get_rel_relkind(pubrel->prrelid);
+
+			if ((pubrelkind == RELKIND_RELATION && relkind == RELKIND_RELATION) ||
+				(pubrelkind == RELKIND_RELATION && relkind == RELKIND_PARTITIONED_TABLE) ||
+				(pubrelkind == RELKIND_SEQUENCE && relkind == RELKIND_SEQUENCE))
+				result = GetPubPartitionOptionRelations(result, pub_partopt,
+														pubrel->prrelid);
+		}
 	}
 
 	systable_endscan(scan);
@@ -985,7 +992,7 @@ GetIncludedPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt)
 {
 	Assert(!GetPublication(pubid)->alltables);
 
-	return get_publication_relations(pubid, pub_partopt, false);
+	return get_publication_relations(pubid, pub_partopt, false, RELKIND_RELATION);
 }
 
 /*
@@ -995,12 +1002,13 @@ GetIncludedPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt)
  * This should only be used FOR ALL TABLES/ FOR ALL SEQUENCES publications.
  */
 List *
-GetExcludedPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt)
+GetExcludedPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt,
+								char pubrelkind)
 {
 	Assert(GetPublication(pubid)->alltables ||
 		   GetPublication(pubid)->allsequences);
 
-	return get_publication_relations(pubid, pub_partopt, true);
+	return get_publication_relations(pubid, pub_partopt, true, pubrelkind);
 }
 
 /*
@@ -1049,8 +1057,8 @@ GetAllTablesPublications(void)
  * root partitioned tables. This is not applicable to FOR ALL SEQUENCES
  * publication.
  *
- * For a FOR ALL TABLES publication, the returned list excludes tables mentioned
- * in the EXCEPT clause.
+ * For a FOR ALL TABLES/SEQUENCES publication, the returned list excludes
+ * tables/sequences mentioned in the EXCEPT clause.
  */
 List *
 GetAllPublicationRelations(Oid pubid, char relkind, bool pubviaroot)
@@ -1067,7 +1075,8 @@ GetAllPublicationRelations(Oid pubid, char relkind, bool pubviaroot)
 	/* EXCEPT filtering applies to tables and sequences */
 	exceptlist = GetExcludedPublicationRelations(pubid, pubviaroot ?
 												 PUBLICATION_PART_ROOT :
-												 PUBLICATION_PART_LEAF);
+												 PUBLICATION_PART_LEAF,
+												 relkind);
 
 	classRel = table_open(RelationRelationId, AccessShareLock);
 
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 21ac6ac99cc..4b534a45213 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -66,7 +66,7 @@ static void CloseRelationList(List *rels);
 static void LockSchemaList(List *schemalist);
 static void PublicationAddRelations(Oid pubid, List *rels, bool if_not_exists,
 									AlterPublicationStmt *stmt, char relkind);
-static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
+static void PublicationDropRelations(Oid pubid, List *rels, bool missing_ok);
 static void PublicationAddSchemas(Oid pubid, List *schemas, bool if_not_exists,
 								  AlterPublicationStmt *stmt);
 static void PublicationDropSchemas(Oid pubid, List *schemas, bool missing_ok);
@@ -1251,15 +1251,119 @@ InvalidatePublicationRels(List *relids)
 		CacheInvalidateRelcacheAll();
 }
 
+/*
+ * Recreate list of tables/sequences to be dropped from the publication.
+ * To recreate the relation list for the publication, look for existing
+ * relations that do not need to be dropped.
+ */
+static void
+get_delete_rels(Oid pubid, List *rels, List *oldrelids, List **delrels)
+{
+	foreach_oid(oldrelid, oldrelids)
+	{
+		ListCell   *newlc;
+		PublicationRelInfo *oldrel;
+		bool		found = false;
+		HeapTuple	rftuple;
+		Node	   *oldrelwhereclause = NULL;
+		Bitmapset  *oldcolumns = NULL;
+
+		/* look up the cache for the old relmap */
+		rftuple = SearchSysCache2(PUBLICATIONRELMAP,
+								  ObjectIdGetDatum(oldrelid),
+								  ObjectIdGetDatum(pubid));
+
+		/*
+		 * See if the existing relation currently has a WHERE clause or a
+		 * column list. We need to compare those too.
+		 */
+		if (HeapTupleIsValid(rftuple))
+		{
+			bool		isnull = true;
+			Datum		whereClauseDatum;
+			Datum		columnListDatum;
+
+			/* Load the WHERE clause for this table. */
+			whereClauseDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
+											   Anum_pg_publication_rel_prqual,
+											   &isnull);
+			if (!isnull)
+				oldrelwhereclause = stringToNode(TextDatumGetCString(whereClauseDatum));
+
+			/* Transform the int2vector column list to a bitmap. */
+			columnListDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
+											  Anum_pg_publication_rel_prattrs,
+											  &isnull);
+
+			if (!isnull)
+				oldcolumns = pub_collist_to_bitmapset(NULL, columnListDatum, NULL);
+
+			ReleaseSysCache(rftuple);
+		}
+
+		foreach(newlc, rels)
+		{
+			PublicationRelInfo *newpubrel;
+			Oid			newrelid;
+			Bitmapset  *newcolumns = NULL;
+
+			newpubrel = (PublicationRelInfo *) lfirst(newlc);
+			newrelid = RelationGetRelid(newpubrel->relation);
+
+			/*
+			 * Validate the column list.  If the column list or WHERE clause
+			 * changes, then the validation done here will be duplicated
+			 * inside PublicationAddRelations().  The validation is cheap
+			 * enough that that seems harmless.
+			 */
+			newcolumns = pub_collist_validate(newpubrel->relation,
+											  newpubrel->columns);
+
+			/*
+			 * Check if any of the new set of relations matches with the
+			 * existing relations in the publication. Additionally, if the
+			 * relation has an associated WHERE clause, check the WHERE
+			 * expressions also match. Same for the column list. Drop the
+			 * rest.
+			 */
+			if (newrelid == oldrelid)
+			{
+				if (equal(oldrelwhereclause, newpubrel->whereClause) &&
+					bms_equal(oldcolumns, newcolumns))
+				{
+					found = true;
+					break;
+				}
+			}
+		}
+
+		/*
+		 * Add the non-matched relations to a list so that they can be
+		 * dropped.
+		 */
+		if (!found)
+		{
+			oldrel = palloc_object(PublicationRelInfo);
+			oldrel->whereClause = NULL;
+			oldrel->columns = NIL;
+			oldrel->except = false;
+			oldrel->relation = table_open(oldrelid,
+										  ShareUpdateExclusiveLock);
+			*delrels = lappend(*delrels, oldrel);
+		}
+	}
+}
+
 /*
  * Add or remove table to/from publication.
  */
 static void
 AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
-					   List *tables, const char *queryString,
+					   List *tables, List *sequences, const char *queryString,
 					   bool publish_schema)
 {
 	List	   *rels = NIL;
+	List	   *seqs = NIL;
 	Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
 	Oid			pubid = pubform->oid;
 
@@ -1272,6 +1376,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
 		return;
 
 	rels = OpenRelationList(tables);
+	seqs = OpenRelationList(sequences);
 
 	if (stmt->action == AP_AddObjects)
 	{
@@ -1285,29 +1390,33 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
 		PublicationAddRelations(pubid, rels, false, stmt, RELKIND_RELATION);
 	}
 	else if (stmt->action == AP_DropObjects)
-		PublicationDropTables(pubid, rels, false);
+		PublicationDropRelations(pubid, rels, false);
 	else						/* AP_SetObjects */
 	{
 		List	   *oldrelids = NIL;
+		List	   *oldseqids = NIL;
 		List	   *delrels = NIL;
-		ListCell   *oldlc;
 
 		if (stmt->for_all_tables || stmt->for_all_sequences)
 		{
 			/*
-			 * In FOR ALL TABLES mode, relations are tracked as exclusions
-			 * (EXCEPT clause). Fetch the current excluded relations so they
-			 * can be reconciled with the specified EXCEPT list.
+			 * In FOR ALL TABLES/ SEQUENCES mode, relations are tracked as
+			 * exclusions (EXCEPT clause). Fetch the current excluded
+			 * relations so they can be reconciled with the specified EXCEPT
+			 * list.
 			 *
 			 * This applies only if the existing publication is already
-			 * defined as FOR ALL TABLES; otherwise, there are no exclusion
-			 * entries to process.
+			 * defined as FOR ALL TABLES/ FOR ALL SEQUENCES; otherwise, there
+			 * are no exclusion entries to process.
 			 */
 			if (pubform->puballtables)
-			{
 				oldrelids = GetExcludedPublicationRelations(pubid,
-															PUBLICATION_PART_ROOT);
-			}
+															PUBLICATION_PART_ROOT,
+															RELKIND_RELATION);
+			if (pubform->puballsequences)
+				oldseqids = GetExcludedPublicationRelations(pubid,
+															PUBLICATION_PART_ROOT,
+															RELKIND_SEQUENCE);
 		}
 		else
 		{
@@ -1320,117 +1429,24 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
 									   pubform->pubviaroot);
 		}
 
-		/*
-		 * To recreate the relation list for the publication, look for
-		 * existing relations that do not need to be dropped.
-		 */
-		foreach(oldlc, oldrelids)
-		{
-			Oid			oldrelid = lfirst_oid(oldlc);
-			ListCell   *newlc;
-			PublicationRelInfo *oldrel;
-			bool		found = false;
-			HeapTuple	rftuple;
-			Node	   *oldrelwhereclause = NULL;
-			Bitmapset  *oldcolumns = NULL;
-
-			/* look up the cache for the old relmap */
-			rftuple = SearchSysCache2(PUBLICATIONRELMAP,
-									  ObjectIdGetDatum(oldrelid),
-									  ObjectIdGetDatum(pubid));
-
-			/*
-			 * See if the existing relation currently has a WHERE clause or a
-			 * column list. We need to compare those too.
-			 */
-			if (HeapTupleIsValid(rftuple))
-			{
-				bool		isnull = true;
-				Datum		whereClauseDatum;
-				Datum		columnListDatum;
-
-				/* Load the WHERE clause for this table. */
-				whereClauseDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
-												   Anum_pg_publication_rel_prqual,
-												   &isnull);
-				if (!isnull)
-					oldrelwhereclause = stringToNode(TextDatumGetCString(whereClauseDatum));
-
-				/* Transform the int2vector column list to a bitmap. */
-				columnListDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
-												  Anum_pg_publication_rel_prattrs,
-												  &isnull);
-
-				if (!isnull)
-					oldcolumns = pub_collist_to_bitmapset(NULL, columnListDatum, NULL);
-
-				ReleaseSysCache(rftuple);
-			}
-
-			foreach(newlc, rels)
-			{
-				PublicationRelInfo *newpubrel;
-				Oid			newrelid;
-				Bitmapset  *newcolumns = NULL;
-
-				newpubrel = (PublicationRelInfo *) lfirst(newlc);
-				newrelid = RelationGetRelid(newpubrel->relation);
-
-				/*
-				 * Validate the column list.  If the column list or WHERE
-				 * clause changes, then the validation done here will be
-				 * duplicated inside PublicationAddRelations().  The
-				 * validation is cheap enough that that seems harmless.
-				 */
-				newcolumns = pub_collist_validate(newpubrel->relation,
-												  newpubrel->columns);
-
-				/*
-				 * Check if any of the new set of relations matches with the
-				 * existing relations in the publication. Additionally, if the
-				 * relation has an associated WHERE clause, check the WHERE
-				 * expressions also match. Same for the column list. Drop the
-				 * rest.
-				 */
-				if (newrelid == oldrelid)
-				{
-					if (equal(oldrelwhereclause, newpubrel->whereClause) &&
-						bms_equal(oldcolumns, newcolumns))
-					{
-						found = true;
-						break;
-					}
-				}
-			}
-
-			/*
-			 * Add the non-matched relations to a list so that they can be
-			 * dropped.
-			 */
-			if (!found)
-			{
-				oldrel = palloc_object(PublicationRelInfo);
-				oldrel->whereClause = NULL;
-				oldrel->columns = NIL;
-				oldrel->except = false;
-				oldrel->relation = table_open(oldrelid,
-											  ShareUpdateExclusiveLock);
-				delrels = lappend(delrels, oldrel);
-			}
-		}
+		/* Get tables and sequences to be dropped */
+		get_delete_rels(pubid, rels, oldrelids, &delrels);
+		get_delete_rels(pubid, seqs, oldseqids, &delrels);
 
 		/* And drop them. */
-		PublicationDropTables(pubid, delrels, true);
+		PublicationDropRelations(pubid, delrels, true);
 
 		/*
 		 * Don't bother calculating the difference for adding, we'll catch and
 		 * skip existing ones when doing catalog update.
 		 */
 		PublicationAddRelations(pubid, rels, true, stmt, RELKIND_RELATION);
+		PublicationAddRelations(pubid, seqs, true, stmt, RELKIND_SEQUENCE);
 
 		CloseRelationList(delrels);
 	}
 
+	CloseRelationList(seqs);
 	CloseRelationList(rels);
 }
 
@@ -1707,9 +1723,6 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
 		ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
 								   &excepttbls, &exceptseqs, &schemaidlist);
 
-		/* EXCEPT clause is not supported with ALTER PUBLICATION */
-		Assert(exceptseqs == NIL);
-
 		CheckAlterPublication(stmt, tup, relations, schemaidlist);
 
 		heap_freetuple(tup);
@@ -1732,8 +1745,8 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
 						   stmt->pubname));
 
 		relations = list_concat(relations, excepttbls);
-		AlterPublicationTables(stmt, tup, relations, pstate->p_sourcetext,
-							   schemaidlist != NIL);
+		AlterPublicationTables(stmt, tup, relations, exceptseqs,
+							   pstate->p_sourcetext, schemaidlist != NIL);
 		AlterPublicationSchemas(stmt, tup, schemaidlist);
 		AlterPublicationAllFlags(stmt, rel, tup);
 	}
@@ -2087,7 +2100,7 @@ PublicationAddRelations(Oid pubid, List *rels, bool if_not_exists,
  * Remove listed tables from the publication.
  */
 static void
-PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
+PublicationDropRelations(Oid pubid, List *rels, bool missing_ok)
 {
 	ObjectAddress obj;
 	ListCell   *lc;
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index b4e78ee9f3a..90080e9bc7c 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -2350,6 +2350,20 @@ match_previous_words(int pattern_id,
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
 	else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && !ends_with(prev_wd, ','))
 		COMPLETE_WITH(")");
+	else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "SEQUENCES", "EXCEPT", "("))
+		COMPLETE_WITH("SEQUENCE");
+	else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "SEQUENCES"))
+		COMPLETE_WITH("EXCEPT ( SEQUENCE");
+	else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "SEQUENCES", "EXCEPT"))
+		COMPLETE_WITH("( SEQUENCE");
+	else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "SEQUENCES", "EXCEPT", "("))
+		COMPLETE_WITH("SEQUENCE");
+	else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "SEQUENCES", "EXCEPT", "(", "SEQUENCE"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
+	else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "SEQUENCES", "EXCEPT", "(", "SEQUENCE", MatchAnyN) && ends_with(prev_wd, ','))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
+	else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "SEQUENCES", "EXCEPT", "(", "SEQUENCE", MatchAnyN) && !ends_with(prev_wd, ','))
+		COMPLETE_WITH(")");
 	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 49c29a87630..e8e6baa6c40 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -178,7 +178,8 @@ typedef enum PublicationPartOpt
 extern List *GetIncludedPublicationRelations(Oid pubid,
 											 PublicationPartOpt pub_partopt);
 extern List *GetExcludedPublicationRelations(Oid pubid,
-											 PublicationPartOpt pub_partopt);
+											 PublicationPartOpt pub_partopt,
+											 char pubrelkind);
 extern List *GetAllTablesPublications(void);
 extern List *GetAllPublicationRelations(Oid pubid, char relkind, bool pubviaroot);
 extern List *GetPublicationSchemas(Oid pubid);
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index e93a3e39796..fd7293db609 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -553,16 +553,32 @@ Publications:
 Except Publications:
     "regress_pub_forallsequences3"
 
+-- Modify the sequence list in the EXCEPT clause
+ALTER PUBLICATION regress_pub_forallsequences3 SET ALL SEQUENCES EXCEPT (SEQUENCE regress_pub_seq0);
+\dRp+ regress_pub_forallsequences3
+                                                   Publication regress_pub_forallsequences3
+          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        | 
+Except sequences:
+    "public.regress_pub_seq0"
+
 RESET client_min_messages;
 -- Throw error as sequence is specified in EXCEPT table list
 CREATE PUBLICATION regress_pub_forallsequences4 FOR ALL TABLES EXCEPT (TABLE regress_pub_seq0);
 ERROR:  cannot specify relation "regress_pub_seq0" in the publication EXCEPT clause
 DETAIL:  This operation is not supported for sequences.
+ALTER PUBLICATION regress_pub_forallsequences3 SET ALL TABLES EXCEPT (TABLE regress_pub_seq0);
+ERROR:  cannot specify relation "regress_pub_seq0" in the publication EXCEPT clause
+DETAIL:  This operation is not supported for sequences.
 -- Throw error as table is specified in EXCEPT sequence list
 CREATE TABLE tab_seq(a int);
 CREATE PUBLICATION regress_pub_forallsequences4 FOR ALL SEQUENCES EXCEPT (SEQUENCE tab_seq);
 ERROR:  cannot specify relation "tab_seq" in the publication EXCEPT clause
 DETAIL:  This operation is not supported for tables.
+ALTER PUBLICATION regress_pub_forallsequences3 SET ALL SEQUENCES EXCEPT (SEQUENCE tab_seq);
+ERROR:  cannot specify relation "tab_seq" in the publication EXCEPT clause
+DETAIL:  This operation is not supported for tables.
 DROP SEQUENCE regress_pub_seq0, pub_test.regress_pub_seq1, regress_pub_seq2;
 DROP PUBLICATION regress_pub_forallsequences1;
 DROP PUBLICATION regress_pub_forallsequences2;
diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql
index 90ed959830a..f411b1662d7 100644
--- a/src/test/regress/sql/publication.sql
+++ b/src/test/regress/sql/publication.sql
@@ -259,14 +259,19 @@ CREATE PUBLICATION regress_pub_forallsequences3 FOR ALL SEQUENCES EXCEPT (SEQUEN
 -- Check that the sequence description shows the publications where it is listed
 -- in the EXCEPT clause
 \d+ regress_pub_seq0
+-- Modify the sequence list in the EXCEPT clause
+ALTER PUBLICATION regress_pub_forallsequences3 SET ALL SEQUENCES EXCEPT (SEQUENCE regress_pub_seq0);
+\dRp+ regress_pub_forallsequences3
 RESET client_min_messages;
 
 -- Throw error as sequence is specified in EXCEPT table list
 CREATE PUBLICATION regress_pub_forallsequences4 FOR ALL TABLES EXCEPT (TABLE regress_pub_seq0);
+ALTER PUBLICATION regress_pub_forallsequences3 SET ALL TABLES EXCEPT (TABLE regress_pub_seq0);
 
 -- Throw error as table is specified in EXCEPT sequence list
 CREATE TABLE tab_seq(a int);
 CREATE PUBLICATION regress_pub_forallsequences4 FOR ALL SEQUENCES EXCEPT (SEQUENCE tab_seq);
+ALTER PUBLICATION regress_pub_forallsequences3 SET ALL SEQUENCES EXCEPT (SEQUENCE tab_seq);
 
 DROP SEQUENCE regress_pub_seq0, pub_test.regress_pub_seq1, regress_pub_seq2;
 DROP PUBLICATION regress_pub_forallsequences1;
-- 
2.34.1