| From: | Henson Choi <assam258(at)gmail(dot)com> |
|---|---|
| To: | jian he <jian(dot)universality(at)gmail(dot)com> |
| Cc: | Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com>, Andrey Borodin <x4mmm(at)yandex-team(dot)ru>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org> |
| Subject: | Re: CREATE TABLE LIKE INCLUDING TRIGGERS |
| Date: | 2026-05-07 01:38:35 |
| Message-ID: | CAAAe_zAHAjTVGE9fAuTZ9df7Y7n7Zctn8WtEkUfytAu+VKQE7w@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi Jian,
This is the line-by-line code review I promised earlier. The overall
conclusion is that the patch is in good shape. I have some minor
items below, none of which are blockers.
WHAT LOOKS GOOD
---------------
The keyword placement is correct. TRIGGERS is classified as
UNRESERVED_KEYWORD and also listed in bare_label_keyword, so existing
SQL that uses "triggers" as an identifier continues to work without
quoting. No compatibility concern here.
generateClonedTriggerStmt() is well-structured. The WHEN-clause
remapping via map_variable_attnos() and the transformed flag to prevent
re-transformation in CreateTriggerFiringOn() are correct.
pg_dump needs no changes. LIKE-copied triggers are stored as
independent pg_trigger rows, so the existing dump logic picks them up
automatically.
MINOR ISSUES
------------
1. Test: cross-file dependency on trigger_func (create_table_like.sql)
create_table_like.sql references trigger_func without creating it,
relying on triggers.sql having run first. The dependency is noted
in a comment, and parallel_schedule guarantees the correct order for
a full "make check" run. However, "make check TESTS=create_table_like"
will fail because trigger_func does not exist.
PostgreSQL convention is that each test file creates and drops the
objects it needs. Please add a local definition of trigger_func in
create_table_like.sql (and drop it at the end of the new block).
2. Test: EXCLUDING TRIGGERS not exercised
The grammar now accepts EXCLUDING TRIGGERS, but no test uses it.
The default (no option) is equivalent, but a one-line smoke test
would confirm the keyword is accepted and has the expected effect:
CREATE TABLE t_excl (LIKE source_table EXCLUDING TRIGGERS);
3. Documentation: create_table.sgml wording inconsistent with
create_foreign_table.sgml
create_foreign_table.sgml already reads:
"All non-internal triggers are copied to the new table."
create_table.sgml reads:
"All non-internal triggers on the original table will be created
on the new table."
Two problems with the latter:
a) "on the original table" is redundant; no other INCLUDING option
includes this phrase (compare INCLUDING STATISTICS: "Extended
statistics are copied to the new table.").
b) "will be created" misrepresents the action; the correct verb
is "are copied", matching the pattern used elsewhere.
Recommended wording for create_table.sgml:
"All non-internal triggers are copied to the new table."
4. Code comment: capitalisation in generateClonedTriggerStmt()
(trigger.c)
/* Reconstruct trigger function String list */
"String" should be lowercase "string".
5. Code comment: overly verbose in expandTableLikeClause()
(parse_utilcmd.c)
/* We make use of CreateTrigStmt's trigcomment option */
The code is self-explanatory. I would recommend removing it or
replacing it with something like:
/* pass comment through to CreateTrigger */
6. Commit message grammar (commit e73f551)
Several sentences contain grammatical errors:
a) "This will copy all source table's trigger to the new table."
-> "...triggers..."
b) "Internal trigger (such as foreign key associated trigger) won't
being copied to new table."
-> "Internal triggers (such as foreign-key-associated triggers)
won't be copied to the new table."
c) "However this command will fail if the source table's trigger
contain whole-row reference."
-> "However, this command will fail if the source table's triggers
contain a whole-row reference."
7. Whole-row reference restriction: implementation gap or deliberate?
Triggers whose WHEN clause contains a whole-row reference (OLD.*,
NEW.*) are rejected. Is this a deliberate decision, or a known gap
left for a follow-up? If the latter, a XXX comment at the rejection
site would help future contributors:
/*
* XXX: whole-row Vars could in principle be handled by passing the
* target table's composite type OID as to_rowtype, but
* generateClonedTriggerStmt() currently has no access to it.
*/
SUMMARY OF ITEMS TO ADDRESS
----------------------------
[1] create_table_like.sql: define and drop trigger_func locally so
the file can be run in isolation.
[2] Add a test for EXCLUDING TRIGGERS.
[3] create_table.sgml: align the INCLUDING TRIGGERS description with
create_foreign_table.sgml, which already reads correctly:
"All non-internal triggers are copied to the new table."
[4] trigger.c generateClonedTriggerStmt(): lowercase "string" in
comment "/* Reconstruct trigger function String list */".
[5] parse_utilcmd.c expandTableLikeClause(): simplify or remove the
comment "/* We make use of CreateTrigStmt's trigcomment option */".
[6] Commit message: fix grammar in items (a), (b), (c) listed above.
Items [3]-[6] are purely cosmetic. [1] and [2] are worth considering
before commit, but none of these are blockers.
Thanks for the patch.
Best regards,
Henson Choi
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Michael Paquier | 2026-05-07 01:47:32 | Re: Fix DROP PROPERTY GRAPH "unsupported object class" error |
| Previous Message | jian he | 2026-05-07 01:14:47 | Re: FOR PORTION OF does not recompute GENERATED STORED columns that depend on the range column |