]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Change syntax of EXCEPT TABLE clause in publication commands.
authorAmit Kapila <akapila@postgresql.org>
Tue, 31 Mar 2026 04:10:51 +0000 (09:40 +0530)
committerAmit Kapila <akapila@postgresql.org>
Tue, 31 Mar 2026 04:10:51 +0000 (09:40 +0530)
Adjust the syntax of the EXCEPT clause in CREATE/ALTER PUBLICATION
added in commits fd366065e0 and 493f8c6439 to move the TABLE keyword
inside the relation list.

Old syntax:
CREATE PUBLICATION ... FOR ALL TABLES EXCEPT TABLE (t1, ...);
ALTER PUBLICATION  ... SET ALL TABLES EXCEPT TABLE (t1, ...);

New syntax:
CREATE PUBLICATION ... FOR ALL TABLES EXCEPT (TABLE t1, ...);
ALTER PUBLICATION  ... SET ALL TABLES EXCEPT (TABLE t1, ...);

This is to ensure that inclusion and exclusion list can be specified in
a same way. Previously, the exclusion table list can be specified as
TABLE (t1, t2, t3) and inclusion list can be specified as TABLE t1, t2,
t3, or TABLE t1, TABLE t2, TABLE t3.

This change is purely syntactic and does not alter behavior.

Reported-by: Masahiko Sawada <sawada.mshk@gmail.com>
Author: vignesh C <vignesh21@gmail.com>
Author: Shlok Kyal <shlok.kyal.oss@gmail.com>
Reviewed-by: shveta malik <shveta.malik@gmail.com>
Reviewed-by: Peter Smith <smithpb2250@gmail.com>
Reviewed-by: Zhijie Hou <houzj.fnst@fujitsu.com>
Reviewed-by: Dilip Kumar <dilipbalaut@gmail.com>
Reviewed-by: SATYANARAYANA NARLAPURAM <satyanarlapuram@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/CAD21AoCC8XuwfX62qKBSfHUAoww_XB3_84HjswgL9jxQy696yw@mail.gmail.com
Discussion: https://postgr.es/m/CALDaNm3=JrucjhiiwsYQw5-PGtBHFONa6F7hhWCXMsGvh=tamA@mail.gmail.com

14 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/logical-replication.sgml
doc/src/sgml/ref/alter_publication.sgml
doc/src/sgml/ref/create_publication.sgml
src/backend/catalog/pg_publication.c
src/backend/commands/publicationcmds.c
src/backend/parser/gram.y
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/t/002_pg_dump.pl
src/bin/psql/describe.c
src/bin/psql/tab-complete.in.c
src/test/regress/expected/publication.out
src/test/regress/sql/publication.sql
src/test/subscription/t/037_except.pl

index 61ffe804ee8bc3f67693c5da1f97f7d6b829b77a..92d179b5ee034096c4ae61ecdad4ab30477c63c4 100644 (file)
@@ -7096,7 +7096,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
       </para>
       <para>
        True if the table is excluded from the publication. See
-       <link linkend="sql-createpublication-params-for-except-table"><literal>EXCEPT TABLE</literal></link>.
+       <link linkend="sql-createpublication-params-for-except-table"><literal>EXCEPT</literal></link>.
       </para></entry>
      </row>
 
index 72c8d3d59bd28b2fb1f155df4126edf22ad64105..23b268273b90babbbddc0a4dc5a52a960115e084 100644 (file)
    <xref linkend="logical-replication-sequences"/>. When a publication is
    created with <literal>FOR ALL TABLES</literal>, a table or set of tables can
    be explicitly excluded from publication using the
-   <link linkend="sql-createpublication-params-for-except-table"><literal>EXCEPT TABLE</literal></link>
+   <link linkend="sql-createpublication-params-for-except-table"><literal>EXCEPT</literal></link>
    clause.
   </para>
 
index 7f0e46380cc2882f3960ed48a82b0b280fc705e5..59b34dd0a38b065319d68eaf591de87e2c241b3f 100644 (file)
@@ -35,7 +35,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 TABLE ( <replaceable class="parameter">except_table_object</replaceable> [, ... ] ) ]
+    ALL TABLES [ EXCEPT ( <replaceable class="parameter">except_table_object</replaceable> [, ... ] ) ]
     ALL SEQUENCES
 
 <phrase>and <replaceable class="parameter">publication_drop_object</replaceable> is one of:</phrase>
@@ -49,7 +49,11 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
 
 <phrase>and <replaceable class="parameter">except_table_object</replaceable> is:</phrase>
 
-    [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
+    TABLE <replaceable class="parameter">table_object</replaceable> [, ... ]
+
+<phrase>and <replaceable class="parameter">table_object</replaceable> is:</phrase>
+
+   [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -71,7 +75,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 TABLE</literal> to exclude specific tables. The
+   <literal>EXCEPT</literal> to exclude specific tables. 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
@@ -80,13 +84,13 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
    one defined for <literal>ALL TABLES</literal> (or both
    <literal>ALL TABLES</literal> and <literal>ALL SEQUENCES</literal>), into a
    publication defined for <literal>ALL SEQUENCES</literal>. In addition,
-   <literal>SET ALL TABLES</literal> can be 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 exclusion list is replaced with the specified tables.
-   If <literal>EXCEPT TABLE</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>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 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.
@@ -263,9 +267,9 @@ ALTER PUBLICATION mypublication SET TABLE users (user_id, firstname, lastname),
 </programlisting></para>
 
   <para>
-   Replace the publication's EXCEPT TABLE list:
+   Replace the table list in the publication's EXCEPT clause:
 <programlisting>
-ALTER PUBLICATION mypublication SET ALL TABLES EXCEPT TABLE (users, departments);
+ALTER PUBLICATION mypublication SET ALL TABLES EXCEPT (TABLE users, departments);
 </programlisting></para>
 
   <para>
index 77066ef680b5647a6977f920864f4e656b227793..99b08aefea519d5ca99e100c05251c59208e276e 100644 (file)
@@ -32,7 +32,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
 
 <phrase>and <replaceable class="parameter">publication_all_object</replaceable> is one of:</phrase>
 
-    ALL TABLES [ EXCEPT TABLE ( <replaceable class="parameter">except_table_object</replaceable> [, ... ] ) ]
+    ALL TABLES [ EXCEPT ( <replaceable class="parameter">except_table_object</replaceable> [, ... ] ) ]
     ALL SEQUENCES
 
 <phrase>and <replaceable class="parameter">table_and_columns</replaceable> is:</phrase>
@@ -41,7 +41,11 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
 
 <phrase>and <replaceable class="parameter">except_table_object</replaceable> is:</phrase>
 
-    [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
+    TABLE <replaceable class="parameter">table_object</replaceable> [, ... ]
+
+<phrase>and <replaceable class="parameter">table_object</replaceable> is:</phrase>
+
+   [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -169,7 +173,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
      <para>
       Marks the publication as one that replicates changes for all tables in
       the database, including tables created in the future. Tables listed in
-      EXCEPT TABLE are excluded from the publication.
+      <literal>EXCEPT</literal> clause are excluded from the publication.
      </para>
     </listitem>
    </varlistentry>
@@ -190,7 +194,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
    </varlistentry>
 
    <varlistentry id="sql-createpublication-params-for-except-table">
-    <term><literal>EXCEPT TABLE</literal></term>
+    <term><literal>EXCEPT</literal></term>
     <listitem>
      <para>
       This clause specifies a list of tables to be excluded from the
@@ -206,7 +210,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
      </para>
      <para>
       For partitioned tables, only the root partitioned table may be specified
-      in <literal>EXCEPT TABLE</literal>. Doing so excludes the root table and
+      in <literal>EXCEPT</literal>. Doing so excludes the root table and
       all of its partitions from replication. The optional
       <literal>ONLY</literal> and <literal>*</literal> has no effect for
       partitioned tables.
@@ -214,7 +218,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
      <para>
       There can be a case where a subscription includes multiple publications.
       In such a case, a table or partition that is included in one publication
-      and listed in the <literal>EXCEPT TABLE</literal> clause of another is
+      and listed in the <literal>EXCEPT</literal> clause of another is
       considered included for replication.
      </para>
     </listitem>
@@ -532,7 +536,7 @@ CREATE PUBLICATION all_tables_sequences FOR ALL TABLES, ALL SEQUENCES;
    Create a publication that publishes all changes in all tables except
    <structname>users</structname> and <structname>departments</structname>:
 <programlisting>
-CREATE PUBLICATION all_tables_except FOR ALL TABLES EXCEPT TABLE (users, departments);
+CREATE PUBLICATION all_tables_except FOR ALL TABLES EXCEPT (TABLE users, departments);
 </programlisting>
   </para>
 
@@ -541,7 +545,7 @@ CREATE PUBLICATION all_tables_except FOR ALL TABLES EXCEPT TABLE (users, departm
    all changes in all tables except <structname>users</structname> and
    <structname>departments</structname>:
 <programlisting>
-CREATE PUBLICATION all_sequences_tables_except FOR ALL SEQUENCES, ALL TABLES EXCEPT TABLE (users, departments);
+CREATE PUBLICATION all_sequences_tables_except FOR ALL SEQUENCES, ALL TABLES EXCEPT (TABLE users, departments);
 </programlisting>
   </para>
  </refsect1>
index c92ff3f51c38c5aacd2dc614373ad62e29d93300..a3192f19d35629d1fc599c448ea2cc97f26b8556 100644 (file)
@@ -831,7 +831,7 @@ publication_add_schema(Oid pubid, Oid schemaid, bool if_not_exists)
  * Internal function to get the list of publication oids for a relation.
  *
  * If except_flag is true, returns the list of publication that specified the
- * relation in EXCEPT clause; otherwise, returns the list of publications
+ * relation in the EXCEPT clause; otherwise, returns the list of publications
  * in which relation is included.
  */
 static List *
@@ -868,7 +868,7 @@ GetRelationIncludedPublications(Oid relid)
 }
 
 /*
- * Gets list of publication oids which has relation in EXCEPT clause.
+ * Gets list of publication oids which has relation in the EXCEPT clause.
  */
 List *
 GetRelationExcludedPublications(Oid relid)
@@ -1001,7 +1001,7 @@ GetAllTablesPublications(void)
  * publication.
  *
  * For a FOR ALL TABLES publication, the returned list excludes tables mentioned
- * in EXCEPT TABLE clause.
+ * in the EXCEPT clause.
  */
 List *
 GetAllPublicationRelations(Oid pubid, char relkind, bool pubviaroot)
index 9fb80fdff08e06088b01d072258c97bdc9c19f80..440adb356ad43dc5617020e01fee723a75c92a95 100644 (file)
@@ -1280,7 +1280,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
                {
                        /*
                         * In FOR ALL TABLES mode, relations are tracked as exclusions
-                        * (EXCEPT TABLES). Fetch the current excluded relations so they
+                        * (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
index 0fea726cdd5b41bcc561ad0633cb83471630f9aa..9e86596dc05c85f1e4b31f221c160484b3c2317f 100644 (file)
@@ -11256,7 +11256,7 @@ AlterOwnerStmt: ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec
  *
  * pub_all_obj_type is one of:
  *
- *             TABLES [EXCEPT TABLE ( table [, ...] )]
+ *             TABLES [EXCEPT (TABLE table [, ...] )]
  *             SEQUENCES
  *
  * CREATE PUBLICATION FOR pub_obj [, ...] [WITH options]
@@ -11399,7 +11399,7 @@ pub_obj_list:   PublicationObjSpec
        ;
 
 opt_pub_except_clause:
-                       EXCEPT TABLE '(' pub_except_obj_list ')'        { $$ = $4; }
+                       EXCEPT '(' TABLE pub_except_obj_list ')'        { $$ = $4; }
                        | /*EMPTY*/                                                                     { $$ = NIL; }
                ;
 
@@ -11439,8 +11439,8 @@ PublicationExceptObjSpec:
 
 pub_except_obj_list: PublicationExceptObjSpec
                                        { $$ = list_make1($1); }
-                       | pub_except_obj_list ',' PublicationExceptObjSpec
-                                       { $$ = lappend($1, $3); }
+                       | pub_except_obj_list ',' opt_table PublicationExceptObjSpec
+                                       { $$ = lappend($1, $4); }
        ;
 
 /*****************************************************************************
@@ -11462,7 +11462,7 @@ pub_except_obj_list: PublicationExceptObjSpec
  *
  * pub_all_obj_type is one of:
  *
- *             ALL TABLES [ EXCEPT TABLE ( table_name [, ...] ) ]
+ *             ALL TABLES [ EXCEPT ( TABLE table_name [, ...] ) ]
  *             ALL SEQUENCES
  *
  *****************************************************************************/
index 5d1f7682f117c38ffddd84df8caa1be7214e55d1..d34240073bb1831da54980716d54c33b13be47a7 100644 (file)
@@ -4625,14 +4625,14 @@ getPublications(Archive *fout)
                 * Get the list of tables for publications specified in the EXCEPT
                 * TABLE clause.
                 *
-                * Although individual EXCEPT TABLE entries could be stored in
+                * Although individual table entries in EXCEPT list could be stored in
                 * PublicationRelInfo, dumpPublicationTable cannot be used to emit
                 * them, because there is no ALTER PUBLICATION ... ADD command to add
-                * individual table entries to the EXCEPT TABLE list.
+                * individual table entries to the EXCEPT list.
                 *
-                * Therefore, the approach is to dump the complete EXCEPT TABLE list
-                * in a single CREATE PUBLICATION statement. PublicationInfo is used
-                * to collect this information, which is then emitted by
+                * Therefore, the approach is to dump the complete EXCEPT list in a
+                * single CREATE PUBLICATION statement. PublicationInfo is used to
+                * collect this information, which is then emitted by
                 * dumpPublication().
                 */
                if (fout->remoteVersion >= 190000)
@@ -4708,16 +4708,16 @@ dumpPublication(Archive *fout, const PublicationInfo *pubinfo)
 
                appendPQExpBufferStr(query, " FOR ALL TABLES");
 
-               /* Include EXCEPT TABLE clause if there are except_tables. */
+               /* Include EXCEPT (TABLE) clause if there are except_tables. */
                for (SimplePtrListCell *cell = pubinfo->except_tables.head; cell; cell = cell->next)
                {
                        TableInfo  *tbinfo = (TableInfo *) cell->ptr;
 
                        if (++n_except == 1)
-                               appendPQExpBufferStr(query, " EXCEPT TABLE (");
+                               appendPQExpBufferStr(query, " EXCEPT (");
                        else
                                appendPQExpBufferStr(query, ", ");
-                       appendPQExpBuffer(query, "ONLY %s", fmtQualifiedDumpable(tbinfo));
+                       appendPQExpBuffer(query, "TABLE ONLY %s", fmtQualifiedDumpable(tbinfo));
                }
                if (n_except > 0)
                        appendPQExpBufferStr(query, ")");
index 051a3d8ea3db198fcbb07bb2aea8f0e278289859..3bc8e51561d3dbc6fd2e79617248c0a157102627 100644 (file)
@@ -3215,9 +3215,9 @@ my %tests = (
        'CREATE PUBLICATION pub8' => {
                create_order => 50,
                create_sql =>
-                 'CREATE PUBLICATION pub8 FOR ALL TABLES EXCEPT TABLE (dump_test.test_table);',
+                 'CREATE PUBLICATION pub8 FOR ALL TABLES EXCEPT (TABLE dump_test.test_table);',
                regexp => qr/^
-                       \QCREATE PUBLICATION pub8 FOR ALL TABLES EXCEPT TABLE (ONLY dump_test.test_table) WITH (publish = 'insert, update, delete, truncate');\E
+                       \QCREATE PUBLICATION pub8 FOR ALL TABLES EXCEPT (TABLE ONLY dump_test.test_table) WITH (publish = 'insert, update, delete, truncate');\E
                        /xm,
                like => { %full_runs, section_post_data => 1, },
        },
@@ -3225,9 +3225,9 @@ my %tests = (
        'CREATE PUBLICATION pub9' => {
                create_order => 50,
                create_sql =>
-                 'CREATE PUBLICATION pub9 FOR ALL TABLES EXCEPT TABLE (dump_test.test_table, dump_test.test_second_table);',
+                 'CREATE PUBLICATION pub9 FOR ALL TABLES EXCEPT (TABLE dump_test.test_table, dump_test.test_second_table);',
                regexp => qr/^
-                       \QCREATE PUBLICATION pub9 FOR ALL TABLES EXCEPT TABLE (ONLY dump_test.test_table, ONLY dump_test.test_second_table) WITH (publish = 'insert, update, delete, truncate');\E
+                       \QCREATE PUBLICATION pub9 FOR ALL TABLES EXCEPT (TABLE ONLY dump_test.test_table, TABLE ONLY dump_test.test_second_table) WITH (publish = 'insert, update, delete, truncate');\E
                        /xm,
                like => { %full_runs, section_post_data => 1, },
        },
@@ -3235,9 +3235,9 @@ my %tests = (
        'CREATE PUBLICATION pub10' => {
                create_order => 92,
                create_sql =>
-                 'CREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT TABLE (dump_test.test_inheritance_parent);',
+                 'CREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT (TABLE dump_test.test_inheritance_parent);',
                regexp => qr/^
-                       \QCREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT TABLE (ONLY dump_test.test_inheritance_parent, ONLY dump_test.test_inheritance_child) WITH (publish = 'insert, update, delete, truncate');\E
+                       \QCREATE PUBLICATION pub10 FOR ALL TABLES EXCEPT (TABLE ONLY dump_test.test_inheritance_parent, TABLE ONLY dump_test.test_inheritance_child) WITH (publish = 'insert, update, delete, truncate');\E
                        /xm,
                like => { %full_runs, section_post_data => 1, },
        },
index d755d25dcf02637c31f04421596b6ea9df76ada2..4e8ff00394a977ee94cc6180c72ef9cd3f6da3c3 100644 (file)
@@ -3206,7 +3206,7 @@ describeOneTableDetails(const char *schemaname,
                                {
                                        /*
                                         * Skip entries where this relation appears in the
-                                        * publication's EXCEPT TABLE list.
+                                        * publication's EXCEPT list.
                                         */
                                        appendPQExpBuffer(&buf,
                                                                          " AND NOT pr.prexcept\n"
index adcff1f6ffb57870cbbe083bcf5f3695409ae3c8..53bf1e21721d4c2fee509d375a2d9e6dde4cf77a 100644 (file)
@@ -2333,14 +2333,18 @@ match_previous_words(int pattern_id,
        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 (");
+               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_WITH("( TABLE");
+       else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "("))
+               COMPLETE_WITH("TABLE");
        /* Complete "ALTER PUBLICATION <name> FOR TABLE" with "<table>, ..." */
-       else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "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, "SET", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && ends_with(prev_wd, ','))
                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, "ADD|DROP|SET", "TABLES", "IN", "SCHEMA"))
                COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
                                                                 " AND nspname NOT LIKE E'pg\\\\_%%'",
@@ -3738,16 +3742,16 @@ match_previous_words(int pattern_id,
        else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL"))
                COMPLETE_WITH("TABLES", "SEQUENCES");
        else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES"))
-               COMPLETE_WITH("EXCEPT TABLE (", "WITH (");
+               COMPLETE_WITH("EXCEPT ( TABLE", "WITH (");
        else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT"))
-               COMPLETE_WITH("TABLE (");
-       else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "TABLE"))
-               COMPLETE_WITH("(");
-       else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "TABLE", "("))
+               COMPLETE_WITH("( TABLE");
+       else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "("))
+               COMPLETE_WITH("TABLE");
+       else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE"))
                COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
-       else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "TABLE", "(", MatchAnyN) && ends_with(prev_wd, ','))
+       else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && ends_with(prev_wd, ','))
                COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
-       else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "TABLE", "(", MatchAnyN) && !ends_with(prev_wd, ','))
+       else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && !ends_with(prev_wd, ','))
                COMPLETE_WITH(")");
        else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES"))
                COMPLETE_WITH("IN SCHEMA");
index a220f48b285b95406ff51efcaf95ad0b8caef4e6..91332e75eeb286a3b094eaa3422ebbf499b55bf0 100644 (file)
@@ -214,11 +214,12 @@ Not-null constraints:
 (1 row)
 
 ---------------------------------------------
--- EXCEPT TABLE tests for normal tables
+-- EXCEPT clause tests for normal tables
 ---------------------------------------------
 SET client_min_messages = 'ERROR';
--- Specify table list in the EXCEPT TABLE clause of a FOR ALL TABLES publication
-CREATE PUBLICATION testpub_foralltables_excepttable FOR ALL TABLES EXCEPT TABLE (testpub_tbl1, testpub_tbl2);
+CREATE TABLE testpub_tbl3 (id serial primary key, data text);
+-- Specify table list in the EXCEPT clause of a FOR ALL TABLES publication
+CREATE PUBLICATION testpub_foralltables_excepttable FOR ALL TABLES EXCEPT (TABLE testpub_tbl1, testpub_tbl2, TABLE testpub_tbl3);
 \dRp+ testpub_foralltables_excepttable
                                                  Publication testpub_foralltables_excepttable
           Owner           | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description 
@@ -227,9 +228,10 @@ CREATE PUBLICATION testpub_foralltables_excepttable FOR ALL TABLES EXCEPT TABLE
 Except tables:
     "public.testpub_tbl1"
     "public.testpub_tbl2"
+    "public.testpub_tbl3"
 
--- Specify table in the EXCEPT TABLE clause of a FOR ALL TABLES publication
-CREATE PUBLICATION testpub_foralltables_excepttable1 FOR ALL TABLES EXCEPT TABLE (testpub_tbl1);
+-- Specify table in the EXCEPT clause of a FOR ALL TABLES publication
+CREATE PUBLICATION testpub_foralltables_excepttable1 FOR ALL TABLES EXCEPT (TABLE testpub_tbl1);
 \dRp+ testpub_foralltables_excepttable1
                                                 Publication testpub_foralltables_excepttable1
           Owner           | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description 
@@ -239,7 +241,7 @@ Except tables:
     "public.testpub_tbl1"
 
 -- Check that the table description shows the publications where it is listed
--- in the EXCEPT TABLE clause
+-- in the EXCEPT clause
 \d testpub_tbl1
                             Table "public.testpub_tbl1"
  Column |  Type   | Collation | Nullable |                 Default                  
@@ -254,21 +256,40 @@ Except Publications:
     "testpub_foralltables_excepttable"
     "testpub_foralltables_excepttable1"
 
+-- fail - first table in the EXCEPT list should use TABLE keyword
+CREATE PUBLICATION testpub_foralltables_excepttable2 FOR ALL TABLES EXCEPT (testpub_tbl1, testpub_tbl2);
+ERROR:  syntax error at or near "testpub_tbl1"
+LINE 1: ..._foralltables_excepttable2 FOR ALL TABLES EXCEPT (testpub_tb...
+                                                             ^
 ---------------------------------------------
 -- SET ALL TABLES/SEQUENCES
 ---------------------------------------------
--- Replace the existing EXCEPT TABLE list (testpub_tbl1) with a new
--- EXCEPT TABLE list containing only (testpub_tbl2).
-ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES EXCEPT TABLE (testpub_tbl2);
+-- Replace the existing table list in the EXCEPT clause (testpub_tbl1,
+-- testpub_tbl2, testpub_tbl3) with table (testpub_tbl2).
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES EXCEPT (TABLE testpub_tbl2);
+\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_tbl2"
+
+-- Replace the existing table list in the EXCEPT clause (testpub_tbl2) with a
+-- table list containing (testpub_tbl1, testpub_tbl2, testpub_tbl3).
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES EXCEPT (TABLE testpub_tbl1, testpub_tbl2, TABLE testpub_tbl3);
 \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"
     "public.testpub_tbl2"
+    "public.testpub_tbl3"
 
--- Clear the EXCEPT TABLE list, making the publication include all tables.
+-- Clear the table list in the EXCEPT clause, making the publication include all
+-- tables.
 ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES;
 \dRp+ testpub_foralltables_excepttable
                                                  Publication testpub_foralltables_excepttable
@@ -309,7 +330,7 @@ ALTER PUBLICATION testpub_forall_tbls_seqs SET ALL SEQUENCES;
 (1 row)
 
 -- fail - SET ALL TABLES/SEQUENCES 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 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;
@@ -319,7 +340,7 @@ ALTER PUBLICATION testpub_fortable SET ALL SEQUENCES;
 ERROR:  publication "testpub_fortable" does not support ALL SEQUENCES operations
 DETAIL:  This operation requires the publication to be defined as FOR ALL TABLES/SEQUENCES or to be empty.
 -- fail - SET ALL TABLES/SEQUENCES 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 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;
@@ -329,12 +350,12 @@ ALTER PUBLICATION testpub_forschema SET ALL SEQUENCES;
 ERROR:  publication "testpub_forschema" does not support ALL SEQUENCES operations
 DETAIL:  This operation requires the publication to be defined as FOR ALL TABLES/SEQUENCES or to be empty.
 RESET client_min_messages;
-DROP TABLE testpub_tbl2;
+DROP TABLE testpub_tbl2, testpub_tbl3;
 DROP PUBLICATION testpub_foralltables, testpub_fortable, testpub_forschema, testpub_for_tbl_schema;
 DROP PUBLICATION testpub_forall_tbls_seqs, testpub_foralltables_excepttable, testpub_foralltables_excepttable1;
 ---------------------------------------------
 -- Tests for inherited tables, and
--- EXCEPT TABLE tests for inherited tables
+-- EXCEPT clause tests for inherited tables
 ---------------------------------------------
 SET client_min_messages = 'ERROR';
 CREATE TABLE testpub_tbl_parent (a int);
@@ -358,8 +379,8 @@ CREATE PUBLICATION testpub4 FOR TABLE ONLY testpub_tbl_parent;
 Tables:
     "public.testpub_tbl_parent"
 
--- List the parent table in the EXCEPT TABLE clause (without ONLY or '*')
-CREATE PUBLICATION testpub5 FOR ALL TABLES EXCEPT TABLE (testpub_tbl_parent);
+-- List the parent table in the EXCEPT clause (without ONLY or '*')
+CREATE PUBLICATION testpub5 FOR ALL TABLES EXCEPT (TABLE testpub_tbl_parent);
 \dRp+ testpub5
                                                              Publication testpub5
           Owner           | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description 
@@ -369,8 +390,8 @@ Except tables:
     "public.testpub_tbl_child"
     "public.testpub_tbl_parent"
 
--- EXCEPT with '*': list the table and all its descendants in the EXCEPT TABLE clause
-CREATE PUBLICATION testpub6 FOR ALL TABLES EXCEPT TABLE (testpub_tbl_parent *);
+-- EXCEPT with '*': list the table and all its descendants in the EXCEPT clause
+CREATE PUBLICATION testpub6 FOR ALL TABLES EXCEPT (TABLE testpub_tbl_parent *);
 \dRp+ testpub6
                                                              Publication testpub6
           Owner           | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description 
@@ -380,8 +401,8 @@ Except tables:
     "public.testpub_tbl_child"
     "public.testpub_tbl_parent"
 
--- EXCEPT with ONLY: list the table in the EXCEPT TABLE clause, but not its descendants
-CREATE PUBLICATION testpub7 FOR ALL TABLES EXCEPT TABLE (ONLY testpub_tbl_parent);
+-- EXCEPT with ONLY: list the table in the EXCEPT clause, but not its descendants
+CREATE PUBLICATION testpub7 FOR ALL TABLES EXCEPT (TABLE ONLY testpub_tbl_parent);
 \dRp+ testpub7
                                                              Publication testpub7
           Owner           | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description 
@@ -394,12 +415,12 @@ RESET client_min_messages;
 DROP TABLE testpub_tbl_parent, testpub_tbl_child;
 DROP PUBLICATION testpub3, testpub4, testpub5, testpub6, testpub7;
 ---------------------------------------------
--- EXCEPT TABLE tests for partitioned tables
+-- EXCEPT clause tests for partitioned tables
 ---------------------------------------------
 SET client_min_messages = 'ERROR';
 CREATE TABLE testpub_root(a int) PARTITION BY RANGE(a);
 CREATE TABLE testpub_part1 PARTITION OF testpub_root FOR VALUES FROM (0) TO (100);
-CREATE PUBLICATION testpub8 FOR ALL TABLES EXCEPT TABLE (testpub_root);
+CREATE PUBLICATION testpub8 FOR ALL TABLES EXCEPT (TABLE testpub_root);
 \dRp+ testpub8;
                                                              Publication testpub8
           Owner           | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description 
@@ -427,12 +448,12 @@ Except Publications:
     "testpub8"
 Number of partitions: 1 (Use \d+ to list them.)
 
-CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT TABLE (testpub_part1);
+CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE testpub_part1);
 ERROR:  cannot use publication EXCEPT clause for relation "testpub_part1"
 DETAIL:  This operation is not supported for individual partitions.
 CREATE TABLE tab_main (a int) PARTITION BY RANGE(a);
 -- Attaching a partition is not allowed if the partitioned table appears in a
--- publication's EXCEPT TABLE clause.
+-- publication's EXCEPT clause.
 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.
@@ -1623,7 +1644,7 @@ RESET client_min_messages;
 ALTER PUBLICATION testpub5 OWNER TO regress_publication_user3;
 SET ROLE regress_publication_user3;
 -- fail - SET ALL TABLES/SEQUENCES on a publication requires superuser privileges
-ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT TABLE (testpub_tbl1); -- fail
+ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT (TABLE testpub_tbl1); -- fail
 ERROR:  must be superuser to set ALL TABLES
 ALTER PUBLICATION testpub5 SET ALL TABLES; -- fail
 ERROR:  must be superuser to set ALL TABLES
index 22e0a30b5c7694c755cf023f8bc82c8f60de27ab..6bafad27571195e90912583677e3e8700e884a8b 100644 (file)
@@ -106,28 +106,37 @@ SELECT pubname, puballtables FROM pg_publication WHERE pubname = 'testpub_forall
 \dRp+ testpub_foralltables
 
 ---------------------------------------------
--- EXCEPT TABLE tests for normal tables
+-- EXCEPT clause tests for normal tables
 ---------------------------------------------
 SET client_min_messages = 'ERROR';
--- Specify table list in the EXCEPT TABLE clause of a FOR ALL TABLES publication
-CREATE PUBLICATION testpub_foralltables_excepttable FOR ALL TABLES EXCEPT TABLE (testpub_tbl1, testpub_tbl2);
+CREATE TABLE testpub_tbl3 (id serial primary key, data text);
+-- Specify table list in the EXCEPT clause of a FOR ALL TABLES publication
+CREATE PUBLICATION testpub_foralltables_excepttable FOR ALL TABLES EXCEPT (TABLE testpub_tbl1, testpub_tbl2, TABLE testpub_tbl3);
 \dRp+ testpub_foralltables_excepttable
--- Specify table in the EXCEPT TABLE clause of a FOR ALL TABLES publication
-CREATE PUBLICATION testpub_foralltables_excepttable1 FOR ALL TABLES EXCEPT TABLE (testpub_tbl1);
+-- Specify table in the EXCEPT clause of a FOR ALL TABLES publication
+CREATE PUBLICATION testpub_foralltables_excepttable1 FOR ALL TABLES EXCEPT (TABLE testpub_tbl1);
 \dRp+ testpub_foralltables_excepttable1
 -- Check that the table description shows the publications where it is listed
--- in the EXCEPT TABLE clause
+-- in the EXCEPT clause
 \d testpub_tbl1
+-- fail - first table in the EXCEPT list should use TABLE keyword
+CREATE PUBLICATION testpub_foralltables_excepttable2 FOR ALL TABLES EXCEPT (testpub_tbl1, testpub_tbl2);
 
 ---------------------------------------------
 -- SET ALL TABLES/SEQUENCES
 ---------------------------------------------
--- Replace the existing EXCEPT TABLE list (testpub_tbl1) with a new
--- EXCEPT TABLE list containing only (testpub_tbl2).
-ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES EXCEPT TABLE (testpub_tbl2);
+-- Replace the existing table list in the EXCEPT clause (testpub_tbl1,
+-- testpub_tbl2, testpub_tbl3) with table (testpub_tbl2).
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES EXCEPT (TABLE testpub_tbl2);
 \dRp+ testpub_foralltables_excepttable
 
--- Clear the EXCEPT TABLE list, making the publication include all tables.
+-- Replace the existing table list in the EXCEPT clause (testpub_tbl2) with a
+-- table list containing (testpub_tbl1, testpub_tbl2, testpub_tbl3).
+ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES EXCEPT (TABLE testpub_tbl1, testpub_tbl2, TABLE testpub_tbl3);
+\dRp+ testpub_foralltables_excepttable
+
+-- Clear the table list in the EXCEPT clause, making the publication include all
+-- tables.
 ALTER PUBLICATION testpub_foralltables_excepttable SET ALL TABLES;
 \dRp+ testpub_foralltables_excepttable
 
@@ -149,23 +158,23 @@ ALTER PUBLICATION testpub_forall_tbls_seqs SET ALL SEQUENCES;
 \dRp+ testpub_forall_tbls_seqs
 
 -- fail - SET ALL TABLES/SEQUENCES 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 EXCEPT (TABLE testpub_tbl1);
 ALTER PUBLICATION testpub_fortable SET ALL TABLES;
 ALTER PUBLICATION testpub_fortable SET ALL SEQUENCES;
 
 -- fail - SET ALL TABLES/SEQUENCES 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 EXCEPT (TABLE pub_test.testpub_nopk);
 ALTER PUBLICATION testpub_forschema SET ALL TABLES;
 ALTER PUBLICATION testpub_forschema SET ALL SEQUENCES;
 
 RESET client_min_messages;
-DROP TABLE testpub_tbl2;
+DROP TABLE testpub_tbl2, testpub_tbl3;
 DROP PUBLICATION testpub_foralltables, testpub_fortable, testpub_forschema, testpub_for_tbl_schema;
 DROP PUBLICATION testpub_forall_tbls_seqs, testpub_foralltables_excepttable, testpub_foralltables_excepttable1;
 
 ---------------------------------------------
 -- Tests for inherited tables, and
--- EXCEPT TABLE tests for inherited tables
+-- EXCEPT clause tests for inherited tables
 ---------------------------------------------
 SET client_min_messages = 'ERROR';
 CREATE TABLE testpub_tbl_parent (a int);
@@ -174,14 +183,14 @@ CREATE PUBLICATION testpub3 FOR TABLE testpub_tbl_parent;
 \dRp+ testpub3
 CREATE PUBLICATION testpub4 FOR TABLE ONLY testpub_tbl_parent;
 \dRp+ testpub4
--- List the parent table in the EXCEPT TABLE clause (without ONLY or '*')
-CREATE PUBLICATION testpub5 FOR ALL TABLES EXCEPT TABLE (testpub_tbl_parent);
+-- List the parent table in the EXCEPT clause (without ONLY or '*')
+CREATE PUBLICATION testpub5 FOR ALL TABLES EXCEPT (TABLE testpub_tbl_parent);
 \dRp+ testpub5
--- EXCEPT with '*': list the table and all its descendants in the EXCEPT TABLE clause
-CREATE PUBLICATION testpub6 FOR ALL TABLES EXCEPT TABLE (testpub_tbl_parent *);
+-- EXCEPT with '*': list the table and all its descendants in the EXCEPT clause
+CREATE PUBLICATION testpub6 FOR ALL TABLES EXCEPT (TABLE testpub_tbl_parent *);
 \dRp+ testpub6
--- EXCEPT with ONLY: list the table in the EXCEPT TABLE clause, but not its descendants
-CREATE PUBLICATION testpub7 FOR ALL TABLES EXCEPT TABLE (ONLY testpub_tbl_parent);
+-- EXCEPT with ONLY: list the table in the EXCEPT clause, but not its descendants
+CREATE PUBLICATION testpub7 FOR ALL TABLES EXCEPT (TABLE ONLY testpub_tbl_parent);
 \dRp+ testpub7
 
 RESET client_min_messages;
@@ -189,20 +198,20 @@ DROP TABLE testpub_tbl_parent, testpub_tbl_child;
 DROP PUBLICATION testpub3, testpub4, testpub5, testpub6, testpub7;
 
 ---------------------------------------------
--- EXCEPT TABLE tests for partitioned tables
+-- EXCEPT clause tests for partitioned tables
 ---------------------------------------------
 SET client_min_messages = 'ERROR';
 CREATE TABLE testpub_root(a int) PARTITION BY RANGE(a);
 CREATE TABLE testpub_part1 PARTITION OF testpub_root FOR VALUES FROM (0) TO (100);
-CREATE PUBLICATION testpub8 FOR ALL TABLES EXCEPT TABLE (testpub_root);
+CREATE PUBLICATION testpub8 FOR ALL TABLES EXCEPT (TABLE testpub_root);
 \dRp+ testpub8;
 \d testpub_part1
 \d testpub_root
-CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT TABLE (testpub_part1);
+CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE testpub_part1);
 
 CREATE TABLE tab_main (a int) PARTITION BY RANGE(a);
 -- Attaching a partition is not allowed if the partitioned table appears in a
--- publication's EXCEPT TABLE clause.
+-- publication's EXCEPT clause.
 ALTER TABLE tab_main ATTACH PARTITION testpub_root FOR VALUES FROM (0) TO (200);
 
 RESET client_min_messages;
@@ -1037,7 +1046,7 @@ RESET client_min_messages;
 ALTER PUBLICATION testpub5 OWNER TO regress_publication_user3;
 SET ROLE regress_publication_user3;
 -- fail - SET ALL TABLES/SEQUENCES on a publication requires superuser privileges
-ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT TABLE (testpub_tbl1); -- fail
+ALTER PUBLICATION testpub5 SET ALL TABLES EXCEPT (TABLE testpub_tbl1); -- fail
 ALTER PUBLICATION testpub5 SET ALL TABLES; -- fail
 ALTER PUBLICATION testpub5 SET ALL SEQUENCES; -- fail
 
index 13b99eda25898ba0d2c13d80a1c4b880fada02ac..c841f7d25606e4b3698caf39d80775a904ea2330 100644 (file)
@@ -1,7 +1,7 @@
 
 # Copyright (c) 2026, PostgreSQL Global Development Group
 
-# Logical replication tests for EXCEPT TABLE publications
+# Logical replication tests for publications with EXCEPT clause
 use strict;
 use warnings;
 use PostgreSQL::Test::Cluster;
@@ -26,12 +26,12 @@ sub test_except_root_partition
 {
        my ($pubviaroot) = @_;
 
-       # If the root partitioned table is in the EXCEPT TABLE clause, all its
+       # If the root partitioned table is in the EXCEPT clause, all its
        # partitions are excluded from publication, regardless of the
        # publish_via_partition_root setting.
        $node_publisher->safe_psql(
                'postgres', qq(
-               CREATE PUBLICATION tap_pub_part FOR ALL TABLES EXCEPT TABLE (root1) WITH (publish_via_partition_root = $pubviaroot);
+               CREATE PUBLICATION tap_pub_part FOR ALL TABLES EXCEPT (TABLE root1) WITH (publish_via_partition_root = $pubviaroot);
                INSERT INTO root1 VALUES (1), (101);
        ));
        $node_subscriber->safe_psql('postgres',
@@ -48,7 +48,7 @@ sub test_except_root_partition
                "INSERT INTO root1 VALUES (2), (102)");
 
        # Verify that data inserted into the partitioned table is not published when
-       # it is in the EXCEPT TABLE clause.
+       # it is in the EXCEPT clause.
        $result = $node_publisher->safe_psql('postgres',
                "SELECT count(*) = 0 FROM pg_logical_slot_get_binary_changes('test_slot', NULL, NULL, 'proto_version', '1', 'publication_names', 'tap_pub_part')"
        );
@@ -67,7 +67,7 @@ sub test_except_root_partition
 }
 
 # ============================================
-# EXCEPT TABLE test cases for non-partitioned tables and inherited tables.
+# EXCEPT clause test cases for non-partitioned tables and inherited tables.
 # ============================================
 
 # Create schemas and tables on publisher
@@ -92,9 +92,9 @@ $node_subscriber->safe_psql(
 
 # Exclude tab1 (non-inheritance case), and also exclude parent and ONLY parent1
 # to verify exclusion behavior for inherited tables, including the effect of
-# ONLY in the EXCEPT TABLE clause.
+# ONLY in the EXCEPT clause.
 $node_publisher->safe_psql('postgres',
-       "CREATE PUBLICATION tab_pub FOR ALL TABLES EXCEPT TABLE (tab1, parent, only parent1)"
+       "CREATE PUBLICATION tab_pub FOR ALL TABLES EXCEPT (TABLE tab1, parent, only parent1)"
 );
 
 # Create a logical replication slot to help with later tests.
@@ -108,38 +108,38 @@ $node_subscriber->safe_psql('postgres',
 # Wait for initial table sync to finish
 $node_subscriber->wait_for_subscription_sync($node_publisher, 'tab_sub');
 
-# Check the table data does not sync for the tables specified in EXCEPT TABLE
+# Check the table data does not sync for the tables specified in the EXCEPT
 # clause.
 $result =
   $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM tab1");
 is($result, qq(0),
-       'check there is no initial data copied for the tables specified in the EXCEPT TABLE clause'
+       'check there is no initial data copied for the tables specified in the EXCEPT clause'
 );
 
-# Insert some data into the table listed in the EXCEPT TABLE clause
+# Insert some data into the table listed in the EXCEPT clause
 $node_publisher->safe_psql(
        'postgres', qq(
        INSERT INTO tab1 VALUES(generate_series(11,20));
        INSERT INTO child VALUES(generate_series(11,20), generate_series(11,20));
 ));
 
-# Verify that data inserted into a table listed in the EXCEPT TABLE clause is
+# Verify that data inserted into a table listed in the EXCEPT clause is
 # not published.
 $result = $node_publisher->safe_psql('postgres',
        "SELECT count(*) = 0 FROM pg_logical_slot_get_binary_changes('test_slot', NULL, NULL, 'proto_version', '1', 'publication_names', 'tab_pub')"
 );
 is($result, qq(t),
-       'verify no changes for table listed in the EXCEPT TABLE clause are present in the replication slot'
+       'verify no changes for table listed in the EXCEPT clause are present in the replication slot'
 );
 
 # This should be published because ONLY parent1 was specified in the
-# EXCEPT TABLE clause, so the exclusion applies only to the parent table and not
+# EXCEPT clause, so the exclusion applies only to the parent table and not
 # to its child.
 $node_publisher->safe_psql('postgres',
        "INSERT INTO child1 VALUES(generate_series(11,20), generate_series(11,20))"
 );
 
-# Verify that data inserted into a table listed in the EXCEPT TABLE clause is
+# Verify that data inserted into a table listed in the EXCEPT clause is
 # not replicated.
 $node_publisher->wait_for_catchup('tab_sub');
 $result =
@@ -156,9 +156,9 @@ $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.
+# Replace the table list in the EXCEPT clause so that only tab2 is excluded.
 $node_publisher->safe_psql('postgres',
-       "ALTER PUBLICATION tab_pub SET ALL TABLES EXCEPT TABLE (tab2)");
+       "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.
@@ -169,19 +169,19 @@ $node_subscriber->safe_psql('postgres',
 $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.
+# listed in the EXCEPT 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'
+       'check there is no initial data copied for the tables specified in the EXCEPT clause'
 );
 
 # Verify that table synchronization now happens for tab1. Table tab1 is
-# included now since the EXCEPT TABLE list is only (tab2).
+# included now since the table list of EXCEPT clause is only (tab2).
 $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'
+       'check that the data is copied as the tab1 is removed from EXCEPT clause'
 );
 
 # cleanup
@@ -199,7 +199,7 @@ $node_publisher->safe_psql(
 ));
 
 # ============================================
-# EXCEPT TABLE test cases for partitioned tables
+# EXCEPT clause test cases for partitioned tables
 # ============================================
 # Setup partitioned table and partitions on the publisher that map to normal
 # tables on the subscriber.
@@ -227,11 +227,11 @@ test_except_root_partition('true');
 # Test when a subscription is subscribing to multiple publications
 # ============================================
 
-# OK when a table is excluded by pub1 EXCEPT TABLE, but it is included by pub2
+# OK when a table is excluded by pub1 EXCEPT clause, but it is included by pub2
 # FOR TABLE.
 $node_publisher->safe_psql(
        'postgres', qq(
-       CREATE PUBLICATION tap_pub1 FOR ALL TABLES EXCEPT TABLE (tab1);
+       CREATE PUBLICATION tap_pub1 FOR ALL TABLES EXCEPT (TABLE tab1);
        CREATE PUBLICATION tap_pub2 FOR TABLE tab1;
        INSERT INTO tab1 VALUES(1);
 ));
@@ -247,7 +247,7 @@ $result =
   $node_publisher->safe_psql('postgres', "SELECT * FROM tab1 ORDER BY a");
 is( $result, qq(1
 2),
-       "check replication of a table in the EXCEPT TABLE clause of one publication but included by another"
+       "check replication of a table in the EXCEPT clause of one publication but included by another"
 );
 $node_publisher->safe_psql(
        'postgres', qq(
@@ -256,7 +256,7 @@ $node_publisher->safe_psql(
 ));
 $node_subscriber->safe_psql('postgres', qq(TRUNCATE tab1));
 
-# OK when a table is excluded by pub1 EXCEPT TABLE, but it is included by pub2
+# OK when a table is excluded by pub1 EXCEPT clause, but it is included by pub2
 # FOR ALL TABLES.
 $node_publisher->safe_psql(
        'postgres', qq(
@@ -275,7 +275,7 @@ $result =
   $node_publisher->safe_psql('postgres', "SELECT * FROM tab1 ORDER BY a");
 is( $result, qq(1
 2),
-       "check replication of a table in the EXCEPT TABLE clause of one publication but included by another"
+       "check replication of a table in the EXCEPT clause of one publication but included by another"
 );
 
 $node_subscriber->safe_psql('postgres', 'DROP SUBSCRIPTION tap_sub');