Handle sequences in preprocess_pubobj_list
authorTomas Vondra <tomas.vondra@postgresql.org>
Fri, 25 Mar 2022 13:29:56 +0000 (14:29 +0100)
committerTomas Vondra <tomas.vondra@postgresql.org>
Fri, 25 Mar 2022 13:29:56 +0000 (14:29 +0100)
Commit 75b1521dae added support for logical replication of sequences,
including grammar changes, but it did not update preprocess_pubobj_list
accordingly. This can cause segfaults with "continuations", i.e. when
command specifies a list of objects:

  CREATE PUBLICATION p FOR SEQUENCE s1, s2;

Reported by Amit Kapila, patch by me.

Reported-by: Amit Kapila
Discussion: https://postgr.es/m/CAA4eK1JxDNKGBSNTyN-Xj2JRjzFo+ziSqJbjH==vuO0YF_CQrg@mail.gmail.com

src/backend/parser/gram.y
src/test/regress/expected/publication.out
src/test/regress/sql/publication.sql

index e327bc735fbc3ce1e24cd1c5527bad0a8c1d17de..f8301541c9131b22010dab61697f3c50f9fda06f 100644 (file)
@@ -17493,7 +17493,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_SEQUENCE)
        {
            /* relation name or pubtable must be set for this type of object */
            if (!pubobj->name && !pubobj->pubtable)
@@ -17537,6 +17538,30 @@ preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner)
                        errmsg("invalid schema name at or near"),
                        parser_errposition(pubobj->location));
        }
+       else if (pubobj->pubobjtype == PUBLICATIONOBJ_SEQUENCES_IN_SCHEMA ||
+                pubobj->pubobjtype == PUBLICATIONOBJ_SEQUENCES_IN_CUR_SCHEMA)
+       {
+           /* WHERE clause is not allowed on a schema object */
+           if (pubobj->pubtable && pubobj->pubtable->whereClause)
+               ereport(ERROR,
+                       errcode(ERRCODE_SYNTAX_ERROR),
+                       errmsg("WHERE clause not allowed for schema"),
+                       parser_errposition(pubobj->location));
+
+           /*
+            * We can distinguish between the different type of schema
+            * objects based on whether name and pubtable is set.
+            */
+           if (pubobj->name)
+               pubobj->pubobjtype = PUBLICATIONOBJ_SEQUENCES_IN_SCHEMA;
+           else if (!pubobj->name && !pubobj->pubtable)
+               pubobj->pubobjtype = PUBLICATIONOBJ_SEQUENCES_IN_CUR_SCHEMA;
+           else
+               ereport(ERROR,
+                       errcode(ERRCODE_SYNTAX_ERROR),
+                       errmsg("invalid schema name at or near"),
+                       parser_errposition(pubobj->location));
+       }
 
        prevobjtype = pubobj->pubobjtype;
    }
index 92f6122d40993e81903eda57a0644f2e535cffee..a5a519d6c87e3bb738f245b0f581d5ee4dafba1c 100644 (file)
@@ -319,6 +319,24 @@ Publications:
 
 DROP SEQUENCE testpub_seq0, pub_test.testpub_seq1, testpub_seq2;
 DROP PUBLICATION testpub_forallsequences, testpub_forsequence, testpub_forschema;
+-- publication testing multiple sequences at the same time
+CREATE SEQUENCE testpub_seq1;
+CREATE SEQUENCE testpub_seq2;
+SET client_min_messages = 'ERROR';
+CREATE PUBLICATION testpub_multi FOR SEQUENCE testpub_seq1, testpub_seq2;
+RESET client_min_messages;
+\dRp+ testpub_multi
+                                               Publication testpub_multi
+          Owner           | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Sequences | Via root 
+--------------------------+------------+---------------+---------+---------+---------+-----------+-----------+----------
+ regress_publication_user | f          | f             | t       | t       | t       | t         | t         | f
+Sequences:
+    "public.testpub_seq1"
+    "public.testpub_seq2"
+
+DROP PUBLICATION testpub_multi;
+DROP SEQUENCE testpub_seq1;
+DROP SEQUENCE testpub_seq2;
 -- Publication mixing tables and sequences
 SET client_min_messages = 'ERROR';
 CREATE PUBLICATION testpub_mix;
index c195e75c6f07c7d53a675099510d6c8d5ce3f0e0..151b8be14edb3d6f0362fb9958ae96d15175e8d4 100644 (file)
@@ -167,6 +167,22 @@ SELECT pubname, puballtables, puballsequences FROM pg_publication WHERE pubname
 DROP SEQUENCE testpub_seq0, pub_test.testpub_seq1, testpub_seq2;
 DROP PUBLICATION testpub_forallsequences, testpub_forsequence, testpub_forschema;
 
+
+-- publication testing multiple sequences at the same time
+CREATE SEQUENCE testpub_seq1;
+CREATE SEQUENCE testpub_seq2;
+
+SET client_min_messages = 'ERROR';
+CREATE PUBLICATION testpub_multi FOR SEQUENCE testpub_seq1, testpub_seq2;
+RESET client_min_messages;
+
+\dRp+ testpub_multi
+
+DROP PUBLICATION testpub_multi;
+DROP SEQUENCE testpub_seq1;
+DROP SEQUENCE testpub_seq2;
+
+
 -- Publication mixing tables and sequences
 SET client_min_messages = 'ERROR';
 CREATE PUBLICATION testpub_mix;