diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index 200e5f7f71e..a0298d0f2a1 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -49,6 +49,29 @@ typedef struct * table. */ } published_rel; +/* + * Double any embedded double-quote characters in str, so that it is + * safe to interpolate into a message that itself wraps the result in + * literal double quotes (e.g. errmsg("relation \"%s\" ...", ...)). + * This does NOT decide whether quoting is needed, unlike + * quote_identifier() -- the caller's message always supplies the + * surrounding quotes itself. + */ +static char * +escape_embedded_quotes(const char *str) +{ + StringInfoData buf; + + initStringInfo(&buf); + for (const char *p = str; *p; p++) + { + if (*p == '"') + appendStringInfoChar(&buf, '"'); /* double it */ + appendStringInfoChar(&buf, *p); + } + return buf.data; +} + /* * Check if relation can be in given publication and throws appropriate * error if not. @@ -67,8 +90,8 @@ check_publication_add_relation(PublicationRelInfo *pri) * encloses the whole name in double quotes. */ relname = psprintf("%s.%s", - get_namespace_name(RelationGetNamespace(targetrel)), - RelationGetRelationName(targetrel)); + escape_embedded_quotes(get_namespace_name(RelationGetNamespace(targetrel))), + escape_embedded_quotes(RelationGetRelationName(targetrel))); errormsg = gettext_noop("cannot specify relation \"%s\" in the publication EXCEPT clause"); } else diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out index 8fc5d0d7c5a..57a51ffd7dc 100644 --- a/src/test/regress/expected/publication.out +++ b/src/test/regress/expected/publication.out @@ -471,9 +471,14 @@ ERROR: cannot specify relation "public.testpub_part1" in the publication EXCEPT DETAIL: This operation is not supported for individual partitions. -- A name that needs quoting must not be quoted twice in the message. CREATE TABLE "testpub Part2" PARTITION OF testpub_root FOR VALUES FROM (100) TO (200); +CREATE SCHEMA "schema has embedded "" quotes"; +CREATE TABLE "schema has embedded "" quotes"."part has embedded "" quotes" PARTITION OF testpub_root FOR VALUES FROM (200) TO (300); CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "testpub Part2"); ERROR: cannot specify relation "public.testpub Part2" in the publication EXCEPT clause DETAIL: This operation is not supported for individual partitions. +CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "schema has embedded "" quotes"."part has embedded "" quotes"); +ERROR: cannot specify relation "schema has embedded "" quotes.part has embedded "" quotes" in the publication EXCEPT clause +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 clause. @@ -483,6 +488,7 @@ DETAIL: The publication EXCEPT clause cannot contain tables that are partitions HINT: Change the publication's EXCEPT clause using ALTER PUBLICATION ... SET ALL TABLES. RESET client_min_messages; DROP TABLE testpub_root, testpub_part1, "testpub Part2", tab_main; +DROP SCHEMA "schema has embedded "" quotes" CASCADE; DROP PUBLICATION testpub8; --- Tests for publications with SEQUENCES CREATE SEQUENCE regress_pub_seq0; diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql index 84f534c387a..11b849c9566 100644 --- a/src/test/regress/sql/publication.sql +++ b/src/test/regress/sql/publication.sql @@ -214,7 +214,10 @@ CREATE PUBLICATION testpub8 FOR ALL TABLES EXCEPT (TABLE testpub_root); CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE testpub_part1); -- A name that needs quoting must not be quoted twice in the message. CREATE TABLE "testpub Part2" PARTITION OF testpub_root FOR VALUES FROM (100) TO (200); +CREATE SCHEMA "schema has embedded "" quotes"; +CREATE TABLE "schema has embedded "" quotes"."part has embedded "" quotes" PARTITION OF testpub_root FOR VALUES FROM (200) TO (300); CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "testpub Part2"); +CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "schema has embedded "" quotes"."part has embedded "" quotes"); CREATE TABLE tab_main (a int) PARTITION BY RANGE(a); -- Attaching a partition is not allowed if the partitioned table appears in a @@ -223,6 +226,7 @@ ALTER TABLE tab_main ATTACH PARTITION testpub_root FOR VALUES FROM (0) TO (200); RESET client_min_messages; DROP TABLE testpub_root, testpub_part1, "testpub Part2", tab_main; +DROP SCHEMA "schema has embedded "" quotes" CASCADE; DROP PUBLICATION testpub8; --- Tests for publications with SEQUENCES