On Tue, Dec 21, 2021 at 2:29 PM Peter Smith <smithpb2...@gmail.com> wrote: > > Here is the v51* patch set: > > Main changes from Euler's v50* are > 1. Most of Euler's "fixes" patches are now merged back in > 2. Patches are then merged per Amit's suggestion [Amit 20/12] > 3. Some other review comments are addressed > > ~~ > > Phase 1 - Merge the Euler fixes > =============================== > > v51-0001 (main) <== v50-0001 (main 0001) + v50-0002 (fixes 0001) > - OK, accepted and merged all the "fixes" back into the 0001 > - (fixed typos) > - There is a slight disagreement with what the PG docs say about > NULLs, but I will raise a separate comment on -hackers later > (meanwhile, the current PG docs text is from the Euler patch) > > v51-0002 (validation) <== v50-0003 (validation 0002) + v50-0004 (fixes 0002) > - OK, accepted and merges all these "fixes" back into the 0002 > - (fixed typo) > > v51-0003 (new/old) <== v50-0005 (new/old 0003) > - REVERTED to the v49 version of this patch! > - Please see Ajin's explanation why the v49 code was required [Ajin 21/12] > > v51-0004 (tab-complete + dump) <== v50-0006 (tab-complete + dump 0004) > - No changes > > v51-0005 (for all tables) <== v50-0007 (for all tables 0005) + > v50-0008 (fixes 0005) > - OK, accepted and merged most of these "fixes" back into the 0005 > - (fixed typo/grammar) > - Amit requested we not use Euler's new tablesync SQL just yet [Amit 21/12] > > > Phase 2 - Merge main (Phase 1) patches per Amit suggestion > ================================================ > > v51-0001 (main) <== v51-0001 (main) + v51-0002 (validation) + v51-0005 > (for all tables) > - (also combined all the commit comments) > > v51-0002 (new/old) <== v51-0003 (new/old) > > v51-0005 (tab-complete + dump) <== v51-0004 > > > Review comments (details) > ========================= > > v51-0001 (main) > - Addressed review comments from Amit. [Amit 20/12] #1,#2,#3,#4 > > v51-0002 (new/old tuple) > - Includes a patch from Greg (provided internally) > > v51-0003 (tab, dump) > - No changes > > ------ > [Amit 20/12] > https://www.postgresql.org/message-id/CAA4eK1JJgfEPKYvQAcwGa5jjuiUiQRQZ0Pgo-HF0KFHh-jyNQQ%40mail.gmail.com > [Ajin 21/12] > https://www.postgresql.org/message-id/CAFPTHDbfpPNh3GLGjySS%3DAuRfbQPQFNvfiyG1GDQW2kz1yT7Og%40mail.gmail.com > [Amit 21/12] > https://www.postgresql.org/message-id/CAA4eK1KwoA5k8v9z9e4ZPN_X%3D1GAmQmsWyauFwZpKiSHqy6eZA%40mail.gmail.com
Few comments: 1) list_free(schemarelids) is called inside if and and outside if in break case. Can we move it above continue so that it does not gets called in the break case: + schemarelids = GetAllSchemaPublicationRelations(pub->oid, + pub->pubviaroot ? + PUBLICATION_PART_ROOT : + PUBLICATION_PART_LEAF); + if (list_member_oid(schemarelids, entry->relid)) + { + if (pub->pubactions.pubinsert) + no_filter[idx_ins] = true; + if (pub->pubactions.pubupdate) + no_filter[idx_upd] = true; + if (pub->pubactions.pubdelete) + no_filter[idx_del] = true; + + list_free(schemarelids); + + /* Quick exit loop if all pubactions have no row-filter. */ + if (no_filter[idx_ins] && no_filter[idx_upd] && no_filter[idx_del]) + break; + + continue; + } + list_free(schemarelids); 2) create_edata_for_relation also is using similar logic, can it also call this function to reduce duplicate code +static EState * +create_estate_for_relation(Relation rel) +{ + EState *estate; + RangeTblEntry *rte; + + estate = CreateExecutorState(); + + rte = makeNode(RangeTblEntry); + rte->rtekind = RTE_RELATION; + rte->relid = RelationGetRelid(rel); + rte->relkind = rel->rd_rel->relkind; + rte->rellockmode = AccessShareLock; + ExecInitRangeTable(estate, list_make1(rte)); + + estate->es_output_cid = GetCurrentCommandId(false); + + return estate; +} 3) In one place select is in lower case, it can be changed to upper case + resetStringInfo(&cmd); + appendStringInfo(&cmd, + "SELECT DISTINCT pg_get_expr(prqual, prrelid) " + " FROM pg_publication p " + " INNER JOIN pg_publication_rel pr ON (p.oid = pr.prpubid) " + " WHERE pr.prrelid = %u AND p.pubname IN ( %s ) " + " AND NOT (select bool_or(puballtables) " + " FROM pg_publication " + " WHERE pubname in ( %s )) " + " AND (SELECT count(1)=0 " + " FROM pg_publication_namespace pn, pg_class c " + " WHERE c.oid = %u AND c.relnamespace = pn.pnnspid)", + lrel->remoteid, + pub_names.data, + pub_names.data, + lrel->remoteid); 4) we could run pgindent once to fix indentation issues + /* Cache ExprState using CacheMemoryContext. */ + Assert(CurrentMemoryContext = CacheMemoryContext); + + /* Prepare expression for execution */ + exprtype = exprType(rfnode); + expr = (Expr *) coerce_to_target_type(NULL, rfnode, exprtype, BOOLOID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); + + if (expr == NULL) 5) Should we mention user should take care of deletion of row filter records after table sync is done. + ALL TABLES</literal> or <literal>FOR ALL TABLES IN SCHEMA</literal> publication, + then all other <literal>WHERE</literal> clauses (for the same publish operation) + become redundant. + If the subscriber is a <productname>PostgreSQL</productname> version before 15 + then any row filtering is ignored during the initial data synchronization phase. 6) Should this be an Assert, since this will be taken care earlier by GetTransformedWhereClause->transformWhereClause->coerce_to_boolean: + expr = (Expr *) coerce_to_target_type(NULL, rfnode, exprtype, BOOLOID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); + + if (expr == NULL) + ereport(ERROR, + (errcode(ERRCODE_CANNOT_COERCE), + errmsg("row filter returns type %s that cannot be cast to the expected type %s", + format_type_be(exprtype), + format_type_be(BOOLOID)), + errhint("You will need to rewrite the row filter."))); 7) This code is present in 3 places, can we make it a function or macro and use it: + if (pub->pubactions.pubinsert) + no_filter[idx_ins] = true; + if (pub->pubactions.pubupdate) + no_filter[idx_upd] = true; + if (pub->pubactions.pubdelete) + no_filter[idx_del] = true; + + /* Quick exit loop if all pubactions have no row-filter. */ + if (no_filter[idx_ins] && no_filter[idx_upd] && no_filter[idx_del]) + break; + + continue; 8) Can the below transformation be done just before the values[Anum_pg_publication_rel_prqual - 1] is set to reduce one of the checks: + if (pri->whereClause != NULL) + { + /* Set up a ParseState to parse with */ + pstate = make_parsestate(NULL); + + /* + * Get the transformed WHERE clause, of boolean type, with necessary + * collation information. + */ + whereclause = GetTransformedWhereClause(pstate, pri, true); + } /* Form a tuple. */ memset(values, 0, sizeof(values)); @@ -328,6 +376,12 @@ publication_add_relation(Oid pubid, PublicationRelInfo *targetrel, values[Anum_pg_publication_rel_prrelid - 1] = ObjectIdGetDatum(relid); + /* Add qualifications, if available */ + if (whereclause) + values[Anum_pg_publication_rel_prqual - 1] = CStringGetTextDatum(nodeToString(whereclause)); + else + nulls[Anum_pg_publication_rel_prqual - 1] = true; + Like: /* Add qualifications, if available */ if (pri->whereClause != NULL) { /* Set up a ParseState to parse with */ pstate = make_parsestate(NULL); /* * Get the transformed WHERE clause, of boolean type, with necessary * collation information. */ whereclause = GetTransformedWhereClause(pstate, pri, true); /* * Walk the parse-tree of this publication row filter expression and * throw an error if anything not permitted or unexpected is * encountered. */ rowfilter_walker(whereclause, targetrel); values[Anum_pg_publication_rel_prqual - 1] = CStringGetTextDatum(nodeToString(whereclause)); } else nulls[Anum_pg_publication_rel_prqual - 1] = true; Regards, Vignesh