Thread
-
Re: Support EXCEPT for TABLES IN SCHEMA publications
Nisha Moond <nisha.moond412@gmail.com> — 2026-05-19T11:14:09Z
On Fri, May 15, 2026 at 12:49 PM Peter Smith <smithpb2250@gmail.com> wrote: > > Hi Nisha. > > Some review comments for patch v5-0001. > Thanks Peter, for the review. > ====== > src/backend/catalog/pg_publication.c > > publication_add_relation: > > 2. > + HeapTuple existing; > > Not sure if this is the best name. How about "tup"? > Noticed that a "HeapTuple tup;" is already declared, so we can use the existing one. > ~~~ > > 3. > + bool is_except = existing_form->prexcept; > > This variable is used only once. Not sure if that vindicates having it. > the is_except value is being used after releasing the tuple and closing the table since the next step errors out. But I have now removed existing_form and directly extracted the value instead. > ~~~ > > 8. > + list_free(schemaRels); > + } > + else > + result = list_concat(result, schemaRels); > > Why is 'schemaRels' only being freed when there is an EXCEPT? > IIUC, In the EXCEPT case, relid is an Oid, so lfirst_oid() copies the integer value from the cell, and lappend_oid() stores that value into a new cell in result. That means result does not reference schemaRels cells after the loop, so list_free(schemaRels) is safe. In the else branch, list_concat() directly transfers schemaRels cells into result. So freeing schemaRels there would corrupt the result. > ====== > src/backend/parser/gram.y > > 14. > - | ColId opt_column_list OptWhereClause > + | ColId opt_column_list OptWhereClause opt_pub_except_clause > { > $$ = makeNode(PublicationObjSpec); > $$->pubobjtype = PUBLICATIONOBJ_CONTINUATION; > + $$->except_tables = $4; > > This seems suspicious. You cannot have an EXCEPT clause when there is > a column list or a WHERE clause, so what is this scenario? Maybe the > "$$->except_tables = $4;" needs to be moved to the 'else' block? > This handles cases where multi-schema continuation is used along with an EXCEPT clause, e.g.: create publication pub1 for tables in schema public, s1 except (table t1); -- without the above, the EXCEPT clause would be silently ignored. Now, I agree that the above case can also be handled by moving "$$->except_tables = $4;" into the else branch. But then EXCEPT would again get silently ignored for table continuations with a column-list or where clause, e.g.,: postgres=# create publication pub2 for table t1, t2 (c1) except (table t1); CREATE PUBLICATION The idea here is to collect the EXCEPT list whenever it is specified for such continuation cases, and then explicitly raise an error in preprocess_pubobj_list() if a table publication object contains an EXCEPT list. > ~~~ > > 16. > + if (pubobj->pubobjtype == PUBLICATIONOBJ_TABLES_IN_SCHEMA) > + { > + if (eobj->pubtable->relation->schemaname == NULL) > + eobj->pubtable->relation->schemaname = pubobj->name; > + else if (strcmp(eobj->pubtable->relation->schemaname, > + pubobj->name) != 0) > + ereport(ERROR, > + errcode(ERRCODE_SYNTAX_ERROR), > + errmsg("table \"%s.%s\" in EXCEPT clause does not belong to schema \"%s\"", > + eobj->pubtable->relation->schemaname, > + eobj->pubtable->relation->relname, > + pubobj->name), > + parser_errposition(eobj->location)); > > 16a. > Introducing some more variables (like 'eobj_schemaname' and > 'eobj_relname') would simplify this code quite a bit. > Done. > ~ > > 16b. > Should make use of the recently committed function that gets > fully-qualified rel names so you can use "%s" instead of "%s.%s". > We cannot use RelationGetQualifiedRelationName() in the grammar, so I used quote_qualified_identifier() instead. ~~~~ Addressed all other comments as suggested. Please find the updated v6 patches attached. Patch-0001: updated as per the above comments. Patch-0002 and Patch-0003: adjusted for the Patch-0001 changes and some code simplification in tab-complete part. -- Thanks, Nisha