Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nrvZu-0001eh-D4 for pgsql-hackers@arkaria.postgresql.org; Fri, 20 May 2022 05:53:34 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1nrvZt-0005Sr-90 for pgsql-hackers@arkaria.postgresql.org; Fri, 20 May 2022 05:53:33 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nrvZs-0005SZ-Pw for pgsql-hackers@lists.postgresql.org; Fri, 20 May 2022 05:53:32 +0000 Received: from mail-qk1-x733.google.com ([2607:f8b0:4864:20::733]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1nrvZq-0007fu-0E for pgsql-hackers@lists.postgresql.org; Fri, 20 May 2022 05:53:31 +0000 Received: by mail-qk1-x733.google.com with SMTP id g207so3451914qke.7 for ; Thu, 19 May 2022 22:53:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=7S8sNXpD/vFEeqJlVQlWswDTrrWfOFbnRINyTep8wY0=; b=eTP4XyatyubSF1HFTOyciq7xOpD82whWyG9OSxQrVINKDCnmQ0omahYWGTKZBjKc8+ 6DIxw5QW8DHG2AjhcCMfs1WbsmsNm2iyLPweqjf2X3WGQuOHGdZwcghaDXPf3aZS9pV9 fcECyovZiEYsYl1ZucSIYrPg+DijNNFUPVOlr8BHpU2peins5AipZTNvX097553vHqAF XAFyD3oKPUYNoUpeZ75oc/D+Vyg/avsYFOLJ4cZ4qNSrqcDY5mhYdPzgMfiRJxLOOwV3 Wh+i66EMCWp3d0QhS3Km76e4SE9mwVqC4je5VsvndHgdAvc9Yvqpl0SG8lhqMzGelJ80 +5dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=7S8sNXpD/vFEeqJlVQlWswDTrrWfOFbnRINyTep8wY0=; b=2eaR9xnl6dN2RYgQUQmMRDqn6gLqfFOvCC05vZNwMb+zpunmu0qV9H+a5h3EYCuvki tSPzWzrnhR64LEnhvTjFnA+rvpQ2OQQTI/pYQ+bmaGPrUwYYE73kY+bgvOf2WiLqKOI3 YQ4A4YTPk9vBOVOVas28LxCqTQbQVdHnO4aA218Sl06lynz5oQJWH+We3BUwNIQC+VR7 VL9Rp3iXovSGqzJkmdo+fbMrFfGShInzCNMRUcnk+3BB9OQThT4vamnKZAQ3qtEjTxDy RelqNzGvko89O77f6ThHhVPjQzTi3/vj2YEAx87J764B99pyMiAbYSBuUJlOE8V8tG+U SSow== X-Gm-Message-State: AOAM5326oTKhSkqYlGPXBqx/6QaCzMVtOQdQ4a9VTSPqG86ur5dy/c+2 a293EUFPguoPMAxAVW6oKcAeSwi7vklyIqMFawE= X-Google-Smtp-Source: ABdhPJwOq8jtIk7oQ6stYwPJM5+PAiLmlyO+V6qoSqC0It41qoNTsGFX6EAN6U9YFpSKy5aYNF3VpF+N4ky5FLSiTrM= X-Received: by 2002:a05:620a:12e8:b0:69f:82ae:ed4e with SMTP id f8-20020a05620a12e800b0069f82aeed4emr5397022qkl.260.1653026009002; Thu, 19 May 2022 22:53:29 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Peter Smith Date: Fri, 20 May 2022 15:53:12 +1000 Message-ID: Subject: Re: Skipping schema changes in publication To: vignesh C Cc: "osumi.takamichi@fujitsu.com" , Amit Kapila , Bharath Rupireddy , PostgreSQL Hackers Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Below are my review comments for v6-0002. ====== 1. Commit message. The psql \d family of commands to display excluded tables. SUGGESTION The psql \d family of commands can now display excluded tables. ~~~ 2. doc/src/sgml/ref/alter_publication.sgml @@ -22,6 +22,7 @@ PostgreSQL documentation ALTER PUBLICATION name ADD publication_object [, ...] +ALTER PUBLICATION name ADD ALL TABLES [ EXCEPT [ TABLE ] exception_object [, ... ] ] The "exception_object" font is wrong. Should look the same as "publication_object" ~~~ 3. doc/src/sgml/ref/alter_publication.sgml - Examples @@ -214,6 +220,14 @@ ALTER PUBLICATION sales_publication ADD ALL TABLES IN SCHEMA marketing, sales; + + Alter publication production_publication to publish + all tables except users and + departments tables: + +ALTER PUBLICATION production_publication ADD ALL TABLES EXCEPT TABLE users, departments; + Consider using "EXCEPT" instead of "EXCEPT TABLE" because that will show TABLE keyword is optional. ~~~ 4. doc/src/sgml/ref/create_publication.sgml An SGML tag error caused building the docs to fail. My fix was previously reported [1]. ~~~ 5. doc/src/sgml/ref/create_publication.sgml @@ -22,7 +22,7 @@ PostgreSQL documentation CREATE PUBLICATION name - [ FOR ALL TABLES + [ FOR ALL TABLES [ EXCEPT [ TABLE ] exception_object [, ... ] ] The "exception_object" font is wrong. Should look the same as "publication_object" ~~~ 6. doc/src/sgml/ref/create_publication.sgml - Examples @@ -351,6 +366,15 @@ CREATE PUBLICATION production_publication FOR TABLE users, departments, ALL TABL CREATE PUBLICATION sales_publication FOR ALL TABLES IN SCHEMA marketing, sales; + + Create a publication that publishes all changes in all the tables except for + the changes of users and + departments table: + +CREATE PUBLICATION mypublication FOR ALL TABLE EXCEPT TABLE users, departments; + + + 6a. Typo: "FOR ALL TABLE" -> "FOR ALL TABLES" 6b. Consider using "EXCEPT" instead of "EXCEPT TABLE" because that will show TABLE keyword is optional. ~~~ 7. src/backend/catalog/pg_publication.c - GetTopMostAncestorInPublication @@ -316,18 +316,25 @@ GetTopMostAncestorInPublication(Oid puboid, List *ancestors, int *ancestor_level } else { - aschemaPubids = GetSchemaPublications(get_rel_namespace(ancestor)); - if (list_member_oid(aschemaPubids, puboid)) + List *aschemapubids = NIL; + List *aexceptpubids = NIL; + + aschemapubids = GetSchemaPublications(get_rel_namespace(ancestor)); + aexceptpubids = GetRelationPublications(ancestor, true); + if (list_member_oid(aschemapubids, puboid) || + (puballtables && !list_member_oid(aexceptpubids, puboid))) { You could re-write this as multiple conditions instead of one. That could avoid always assigning the 'aexceptpubids', so it might be a more efficient way to write this logic. ~~~ 8. src/backend/catalog/pg_publication.c - CheckPublicationDefValues +/* + * Check if the publication has default values + * + * Check the following: + * Publication is having default options + * Publication is not associated with relations + * Publication is not associated with schemas + * Publication is not set with "FOR ALL TABLES" + */ +static bool +CheckPublicationDefValues(HeapTuple tup) 8a. Remove the tab. Replace with spaces. 8b. It might be better if this comment order is the same as the logic order. e.g. * Check the following: * Publication is not set with "FOR ALL TABLES" * Publication is having default options * Publication is not associated with schemas * Publication is not associated with relations ~~~ 9. src/backend/catalog/pg_publication.c - AlterPublicationSetAllTables +/* + * Reset the publication. + * + * Reset the publication options, publication relations and publication schemas. + */ +static void +AlterPublicationSetAllTables(Relation rel, HeapTuple tup) The function comment and the function name do not seem to match here; something looks like a cut/paste error ?? ~~~ 10. src/backend/catalog/pg_publication.c - AlterPublicationSetAllTables + /* set all tables option */ + values[Anum_pg_publication_puballtables - 1] = BoolGetDatum(true); + replaces[Anum_pg_publication_puballtables - 1] = true; SUGGEST (comment) /* set all ALL TABLES flag */ ~~~ 11. src/backend/catalog/pg_publication.c - AlterPublication @@ -1501,6 +1579,20 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION, stmt->pubname); + if (stmt->for_all_tables) + { + bool isdefault = CheckPublicationDefValues(tup); + + if (!isdefault) + ereport(ERROR, + errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("Setting ALL TABLES requires publication \"%s\" to have default values", + stmt->pubname), + errhint("Use ALTER PUBLICATION ... RESET to reset the publication")); The errmsg should start with a lowercase letter. ~~~ 12. src/backend/catalog/pg_publication.c - AlterPublication @@ -1501,6 +1579,20 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION, stmt->pubname); + if (stmt->for_all_tables) + { + bool isdefault = CheckPublicationDefValues(tup); + + if (!isdefault) + ereport(ERROR, + errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("Setting ALL TABLES requires publication \"%s\" to have default values", + stmt->pubname), + errhint("Use ALTER PUBLICATION ... RESET to reset the publication")); Example test: postgres=# create table t1(a int); CREATE TABLE postgres=# create publication p1 for table t1; CREATE PUBLICATION postgres=# alter publication p1 add all tables except t1; 2022-05-20 14:34:49.301 AEST [21802] ERROR: Setting ALL TABLES requires publication "p1" to have default values 2022-05-20 14:34:49.301 AEST [21802] HINT: Use ALTER PUBLICATION ... RESET to reset the publication 2022-05-20 14:34:49.301 AEST [21802] STATEMENT: alter publication p1 add all tables except t1; ERROR: Setting ALL TABLES requires publication "p1" to have default values HINT: Use ALTER PUBLICATION ... RESET to reset the publication postgres=# alter publication p1 set all tables except t1; That error message does not quite match what the user was doing. Firstly, they were adding the ALL TABLES, not setting it. Secondly, all the values of the publication were already defaults (only there was an existing table t1 in the publication). Maybe some minor changes to the message wording can be a better reflect what the user is doing here. ~~~ 13. src/backend/parser/gram.y @@ -10410,7 +10411,7 @@ AlterOwnerStmt: ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec * * CREATE PUBLICATION name [WITH options] * - * CREATE PUBLICATION FOR ALL TABLES [WITH options] + * CREATE PUBLICATION FOR ALL TABLES [EXCEPT TABLE table [, ...]] [WITH options] Comment should show the "TABLE" keyword is optional ~~~ 14. src/bin/pg_dump/pg_dump.c - dumpPublicationTable @@ -4332,6 +4380,7 @@ dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo) appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY", fmtId(pubinfo->dobj.name)); + appendPQExpBuffer(query, " %s", fmtQualifiedDumpable(tbinfo)); This additional whitespace seems unrelated to this patch ~~~ 15. src/include/nodes/parsenodes.h 15a. @@ -3999,6 +3999,7 @@ typedef struct PublicationTable RangeVar *relation; /* relation to be published */ Node *whereClause; /* qualifications */ List *columns; /* List of columns in a publication table */ + bool except; /* except relation */ } PublicationTable; Maybe the comment should be more like similar ones: /* exclude the relation */ 15b. @@ -4007,6 +4008,7 @@ typedef struct PublicationTable typedef enum PublicationObjSpecType { PUBLICATIONOBJ_TABLE, /* A table */ + PUBLICATIONOBJ_EXCEPT_TABLE, /* An Except table */ PUBLICATIONOBJ_TABLES_IN_SCHEMA, /* All tables in schema */ PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA, /* All tables in first element of Maybe the comment should be more like: /* A table to be excluded */ ~~~ 16. src/test/regress/sql/publication.sql I did not see any test cases using EXCEPT when the optional TABLE keyword is omitted. ------ [1] https://www.postgresql.org/message-id/CAHut%2BPtZDfBJ1d%3D3kSexgM5m%2BP_ok8sdsJXKimsXycaMyqXsNA%40mail.gmail.com Kind Regards, Peter Smith. Fujitsu Australia