CommitFest 6482 Review — CREATE TABLE LIKE INCLUDING COMMENTS copies table-level comment
code-review · generated from canonical Markdown
code-review
postgresql-master
commitfest-6482-review2026-08-28T14:50:40.940703+00:00
Front matter
schema: review-report-v2 target: CommitFest 6482 — CREATE TABLE LIKE INCLUDING COMMENTS copies table-level comment (uncommitted staged diff) head: 4d5fdb21ddda46972d7703562c5ad4076feae8b8 base: 4d5fdb21ddda46972d7703562c5ad4076feae8b8 diff_sha: d9b8108fc514bf0326770c6bf9a3058abd033fd6e7eb04d93712042f0fbf713f verdict: needs-review blocker_counts: verified: 0 unverified: 0 model: glm-5.2:cloud source: postgresql-master slug: commitfest-6482-review
CommitFest 6482 Review — CREATE TABLE LIKE INCLUDING COMMENTS copies table-level comment
Patch summary
CREATE TABLE ... LIKE ... INCLUDING COMMENTS previously copied comments on columns, check constraints, not-null constraints, indexes, and extended statistics, but not the comment on the source relation itself. This patch adds that copy.
Changed files (repo-relative):
src/backend/parser/parse_utilcmd.c— implementationsrc/test/regress/expected/create_table_like.out— regression test expectedsrc/test/regress/sql/create_table_like.sql— regression test SQL
Changed symbols: transformTableLikeClause, expandTableLikeClause
What the patch does:
- Adds
CREATE_TABLE_LIKE_COMMENTSto the deferral-option mask intransformTableLikeClause(parse_utilcmd.c:1311-1317) soexpandTableLikeClauseis driven whenINCLUDING COMMENTSis requested. - Adds a new block in
expandTableLikeClause(parse_utilcmd.c:1631-1652) that callsGetComment(RelationGetRelid(relation), RelationRelationId, 0)on the LIKE source and, if non-NULL, builds aCommentStmtwithobjtype = OBJECT_TABLEandobject = list_make2(schemaname, relname)(orlist_make1(relname)), appended toresult. - Adds a regression test:
COMMENT ON TABLE ctlt3+SELECT obj_description('ctlt13_like'::regclass, 'pg_class').
Provenance / model routes
All seats used model glm-5.2:cloud (user-fixed override). Route policy: user-fixed-model.
| Seat | Handoff report slug |
|---|---|
| pg-patch-reviewer | commitfest-6482-review-handoff-patch-reviewer |
| pg-security-reviewer | commitfest-6482-review-handoff-security-reviewer |
| pg-finding-verifier | commitfest-6482-review-handoff-verifier |
| pg-test-author | commitfest-6482-review-handoff-test-author |
| pg-change-coverage-reviewer | commitfest-6482-review-handoff-coverage |
Security review summary
No privilege/role escalation, SECURITY DEFINER/search_path, catalog write race/TOCTOU, SQL injection, crypto/TLS, or C memory-safety vulnerability is introduced by this diff. The CommentStmt targets the newly-created child relation (owned by the invoker); CommentObject re-checks ownership. The parent comment is read via GetComment under AccessShareLock (consistent with existing column/constraint/index/stat comment paths). No string SQL is built — the object name is a structured List of String nodes. The char *comment local is reused safely within the same memory context (not a leak/UAF under the PG memory-context filter).
Findings
(MAJOR, correctness, verified) — Foreign-table target wrong-object-type
Location: src/backend/parser/parse_utilcmd.c:1642
Mechanism: The new table-comment block hard-codes stmt->objtype = OBJECT_TABLE regardless of the child relation's relkind. When the child is RELKIND_FOREIGN_TABLE (CREATE FOREIGN TABLE ... LIKE ... INCLUDING COMMENTS|ALL), CommentObject → get_object_address → get_relation_by_qualified_relation (objectaddress.c:1472-1478) errors with ERRCODE_WRONG_OBJECT_TYPE and the foreign table is never created. The existing index-copy block is guarded by childrel->rd_rel->relkind != RELKIND_FOREIGN_TABLE (line 1554); the new block has no such guard. This is a functional regression: CREATE FOREIGN TABLE x (LIKE <commented-src> INCLUDING ALL) SERVER s fails where it previously succeeded.
Failure: CREATE FOREIGN TABLE ft (LIKE src INCLUDING COMMENTS) SERVER s errors with ERROR: "ft" is not a table when src carries a table-level comment; the foreign table is not created.
Verification: Reproduced against a staged-build temp instance (CREATE FOREIGN TABLE cf6482_ft (LIKE cf6482_src INCLUDING COMMENTS) SERVER dummy_srv → ERROR: "cf6482_ft" is not a table). Post-fix, the foreign table is created and ft_comment = 'source table comment'.
Repair: Replace stmt->objtype = OBJECT_TABLE; with stmt->objtype = get_relkind_objtype(childrel->rd_rel->relkind);. get_relkind_objtype is already used in this file (line 1166); childrel is in scope. This returns OBJECT_FOREIGN_TABLE for foreign tables and OBJECT_TABLE for plain/partitioned tables, preserving the feature for all relkinds.
Repair validation: Passed — apply-check, diff-check, compile (exit 0), repro (foreign-table target succeeds), targeted-test (cf6482_like_comments + create_table_like both pass via check-tests).
Suggested code (exact postimage):
CommentStmt *stmt = makeNode(CommentStmt);
stmt->objtype = get_relkind_objtype(childrel->rd_rel->relkind);
if (heapRel->schemaname)
stmt->object = (Node *) list_make2(makeString(heapRel->schemaname),
makeString(heapRel->relname));
else
stmt->object = (Node *) list_make1(makeString(heapRel->relname));Patch (unified diff, bound to HEAD 4d5fdb21ddd): F1+F4 combined (sha256 a4ea779f67a5284daa3df9f1ac1a93909f3803f42fc2ef903e55e8d36eef0cfa).
(MINOR, docs, verified) — Documentation not updated
Location: doc/src/sgml/ref/create_table.sgml:694
Mechanism: The INCLUDING COMMENTS description lists "Comments for the copied columns, check constraints, not-null constraints, indexes, and extended statistics will be copied." It does not mention the relation-level comment is now copied. Reviewer Carlos explicitly requested this on-list (2026-03-24); the author confirmed intent (2026-03-25).
Repair: Add "The comment for the relation itself (if any) is copied as well." to the paragraph.
Repair validation: Passed — apply-check, diff-check, doc-build (make -C doc check exit 0).
(MINOR, correctness, cannot-verify — design decision pending) — Multi-LIKE last-wins
Location: src/backend/parser/parse_utilcmd.c:1650
Mechanism: With multiple LIKE ... INCLUDING COMMENTS sources each carrying a table comment, CreateComments (comment.c:203-217) replaces the pg_description tuple for (child_oid, RelationRelationId, 0), so the last-applied comment wins silently. The thread intends newline-separated concatenation (Jim Jones 2026-02-13, Carlos 2026-03-24); ZizhuanLiu (2026-07-18) proposed skip-on-multiple. The staged diff implements neither — it silently does last-wins.
Verification: cannot-verify — the behavior is empirically real (reproduced: multi_comment = 'second source comment', reversed = 'source table comment'), but classifying it as a defect requires a design decision pending on the review thread. A typed design-choice safety waiver is applied to the code/patch/validation.
Test example: cf6482_like_comments pins the current last-wins behavior (multi_comment_last_wins = 'second source comment'); must be updated to the chosen contract once decided.
(NIT, maintainability, verified) — pgindent cast spacing
Location: src/backend/parser/parse_utilcmd.c:1644
Mechanism: New lines use (Node *)list_make2(...) without a space after the cast; surrounding code uses (Node *) list_make3(...). pgindent requires the space.
Repair: Add the space: (Node *) list_make2(...), (Node *) list_make1(...). Included in the F1+F4 combined patch.
Repair validation: Passed — apply-check, diff-check, compile, static-check, targeted-test.
(MINOR, tests, verified) — Test gaps
Location: src/test/regress/sql/create_table_like.sql:177
Mechanism: The staged test covers only the plain-table, single-LIKE, schema-qualified case. Missing: foreign-table target (F1), INCLUDING ALL with a commented source, multi-LIKE (F3), temp-table target (COV-1), partitioned-table target.
Repair: Add the cf6482_like_comments regression test covering all relkinds/option combinations with a no-op FDW.
Repair validation: Passed — ok 1 - cf6482_like_comments; ok 2 - create_table_like; All 2 tests passed.
(NIT, maintainability, refuted) — Deferral mask change (benign)
Location: src/backend/parser/parse_utilcmd.c:1311
The deferral-mask change is verified correct and benign — INCLUDING COMMENTS alone now opens childrel + builds attmap where it previously did not (necessary for the relation-comment copy). No repair needed; the hypothesis that there is a problem is refuted. The behavior change should be noted in the commit message.
(MINOR, tests, verified-by-coverage) — Uncovered no-schemaname branch
Location: src/backend/parser/parse_utilcmd.c:1647
Mechanism: Changed-code coverage measurement (fresh gcov epoch, create_table_like test) found line 1647 (the else branch of if (heapRel->schemaname) — the unqualified-name path via list_make1, taken when heapRel->schemaname is NULL, e.g. a temp-table target) has 0 gcov hits. Branch 1643-1 (false) is also uncovered (count 0). A temp-instance probe with CREATE TEMP TABLE cf6482_temp (LIKE cf6482_src INCLUDING COMMENTS) drove line 1647 from 0 to 1 hit, confirming coverability.
Repair: Add the cf6482_temp case to cf6482_like_comments.
Repair validation: Passed — ok 1 - cf6482_like_comments; post-test gcov line 1647 count = 1.
Verification Summary
| ID | Severity | Class | Status | Method |
|---|---|---|---|---|
| F1 | MAJOR | correctness | verified | repro |
| F2 | MINOR | docs | verified | static-check |
| F3 | MINOR | correctness | cannot-verify (design-choice) | repro |
| F4 | NIT | maintainability | verified | static-check |
| F5 | MINOR | tests | verified | static-check |
| F6 | NIT | maintainability | refuted (benign) | static-check |
| COV-1 | MINOR | tests | verified | verified-by-coverage |
- Verified: 5 (F1, F2, F4, F5, COV-1)
- Cannot-verify: 1 (F3 — design decision pending)
- Refuted: 1 (F6 — benign)
- Blockers: 0 verified / 0 unverified
Repair Validation Summary
| ID | Patch status | Validation status | Methods |
|---|---|---|---|
| F1 | provided (sha256 a4ea779f...) | passed | apply-check, diff-check, compile, repro, targeted-test |
| F2 | provided (sha256 c30d8464...) | passed | apply-check, diff-check, doc-build |
| F3 | waived (design-choice) | waived | — |
| F4 | provided (sha256 a4ea779f...) | passed | apply-check, diff-check, compile, static-check, targeted-test |
| F5 | provided (sha256 231fe83a...) | passed | apply-check, diff-check, targeted-test |
| F6 | not-applicable-refuted | not-applicable-refuted | — |
| COV-1 | provided (sha256 231fe83a...) | passed | apply-check, diff-check, targeted-test |
All candidate repairs were validated in a disposable worktree copy only; the reviewed worktree was not modified. Build/test commands executed: make -s -j4 (exit 0), make -C src/test/regress check-tests TESTS="cf6482_like_comments create_table_like" (All tests passed), make -C doc -s check (exit 0).
Changed-Code Coverage
Coverage requirement: required (changed instrumentable implementation in src/backend/parser/parse_utilcmd.c).
Lane: host-disposable (passed). Fresh disposable gcc 15.2.0 gcov build at frozen HEAD with the staged feature diff applied; --enable-coverage (-fprofile-arcs -ftest-coverage, -O0 -g); make -j4 exit 0; pg_regress create_table_like → ok 1 - create_table_like.
Counter epoch: fresh (all .gcda deleted before test run; .gcno from build). No integrity errors (no stamp/merge/profiling errors).
Test commands executed:
make -C src/test/regress check-tests TESTS=create_table_like
Coverage totals
| Metric | Count |
|---|---|
| Changed executable lines | 11 |
| Covered changed lines | 10 |
| Compiler-uncovered changed lines | 1 |
| Uncovered changed lines (semantic) | 1 |
| Structural uncovered changed lines | 0 |
| Changed lines without coverage coordinates | 0 |
| Changed branches | 6 |
| Covered changed branches | 5 |
| Uncovered branches | 1 |
Covered (10/11 lines): 1311 (mask if, 39 hits), 1312 (new COMMENTS bit), 1634 (if options & COMMENTS, 25 hits), 1636 (GetComment, 13 hits), 1638 (if comment != NULL, 13 hits), 1640 (makeNode, 1 hit), 1642 (objtype = OBJECT_TABLE, 1 hit), 1643 (if schemaname, 1 hit — line covered, branch 1 uncovered), 1644 (list_make2, 1 hit), 1648 (stmt->comment, 1 hit), 1650 (lappend, 1 hit).
Uncovered line
Line 1647 (expandTableLikeClause, src/backend/parser/parse_utilcmd.c):
else
stmt->object = (Node *)list_make1(makeString(heapRel->relname));- Coverability: coverable-now
- Reason: Else branch of
if (heapRel->schemaname)— reached when the LIKE child'sRangeVarhas no explicit schema name (temp-table target or unqualifiedCREATE TABLE). A temp-instance probe (CREATE TEMP TABLE cf6482_temp (LIKE cf6482_src INCLUDING COMMENTS)) drove line 1647 from 0 to 1 hit, confirming coverability. - Test example:
cf6482_tempcase incf6482_like_comments.
Uncovered branch
Line 1643 branch 1 (false outcome of if (heapRel->schemaname)):
- Count: 0
- Coverability: coverable-now
- Reason: Taken when
heapRel->schemaname == NULL(temp-table / unqualified target). Covered by the samecf6482_temptest case.
Touched functions
| Function | Lines (covered/total) | Branches (covered/total) |
|---|---|---|
expandTableLikeClause | 10/11 | 5/6 |
transformTableLikeClause | 1/1 | 2/2 |
Non-instrumented changes
None. The diff touches only the implementation .c (instrumented) and test .sql/.out (test files, not counted as executable implementation).
Residual limitations
- Measurement is qualified as "under the executed test set" (
create_table_likeonly); not a global suite-coverage figure. - No
cannot-measureand noinfeasible-with-reasonwaivers apply.
pgsql-hackers thread ledger
Status: reconciled Ledger report slug: commitfest-6482-review-handoff-patch-reviewer
Thread: "COMMENTS are not being copied in CREATE TABLE LIKE" (Thread-ID 636704), Jim Jones (author), Feb-Jul 2026.
Message chronology:
e08cb97f-...@uni-muenster.de(2026-02-12, patch) — Original bug report + v1 patch.CAHGQGwE...@mail.gmail.com(2026-02-13, review) — Fujii Masao: multi-LIKE semantics question.5888209c-...@uni-muenster.de(2026-02-13, author-reply) — Author proposes newline-separated concatenation; v2 patch.ceccea29-...@uni-muenster.de(2026-02-26, patch) — Rebase (v3).CAL-Pge4e...@mail.gmail.com(2026-03-24, review) — Carlos: tests OK, requests docs update, proposes concatenation wording.fda18ba2-...@uni-muenster.de(2026-03-25, author-reply) — Author confirms docs intent; asks reviewers to weigh in.tencent_D0A4135E...@qq.com(2026-07-18, review) — ZizhuanLiu: suggests skip-on-multiple.88b16128-...@uni-muenster.de(2026-07-23, author-reply) — Author disagrees with blanket skip; open to withdrawing if concatenation impractical.
Per-finding dispositions:
- F1: new (not previously raised on-list)
- F2: already-raised (Carlos 2026-03-24)
- F3: unreconciled (actively debated, no consensus)
- F4: new
- F5: new
- F6: new
- COV-1: new
Aggregated Test Plan
The proposed cf6482_like_comments regression test (proposal-only, not applied to the reviewed worktree) exercises:
- Plain-table target (
cf6482_plain) INCLUDING ALLwith a commented source (cf6482_all)- Partitioned-table target (
cf6482_part) - Temp-table target (
cf6482_temp) — covers COV-1 line 1647 - Foreign-table target (
cf6482_ft) — exposes/covers F1 after the fix - Foreign-table
INCLUDING ALL(cf6482_ft_all) - Multi-LIKE last-wins (
cf6482_multi) — pins current F3 behavior
Validated via make -C src/test/regress check-tests TESTS=cf6482_like_comments (All tests passed) against the patched disposable build.
Residual risk
- F1 is a functional regression that must be fixed before committer-ready (foreign-table LIKE target fails).
- F3 multi-LIKE semantics is unresolved on-list; the staged diff's silent last-wins may not match the committer's chosen contract.
- F2 docs gap should be addressed before commit.
- F4/F5/COV-1 are low-severity nits/test gaps addressed by the proposed repair patch.
Deterministic verdict
needs-review
No BLOCKERs. F1 is a correctness MAJOR (functional regression on foreign-table target). F3 is an unreconciled live thread objection (multi-LIKE semantics). Per the harness verdict rules: any correctness MAJOR or live thread objection => needs-review.
Blocker split: 0 verified / 0 unverified.
Maintainer CC
Author: Jim Jones (jim.jones@uni-muenster.de) Reviewer: Carlos, Fujii Masao (masao.fujii@oss.nttdata.com)
Per-commit rollup
Single uncommitted staged diff (no commit history); all changes are in the working-tree index of the review worktree. Diff SHA: d9b8108fc514bf0326770c6bf9a3058abd033fd6e7eb04d93712042f0fbf713f.
Verified-clean section
No findings were refuted as actual defects requiring repair except F6 (deferral-mask change, refuted as benign). The security review found no security vulnerabilities.
---
*Review conducted by the pg-review-harness (model glm-5.2:cloud). Artifact validated with validate_review_artifact.py (sha256 edbcb304...), exit 0. Reviewed worktree was read-only; all candidate repairs were validated in disposable scratch only.*