CommitFest 6482 Review — CREATE TABLE LIKE INCLUDING COMMENTS copies table-level comment

code-review · generated from canonical Markdown

Type
code-review
Source
postgresql-master
Slug
commitfest-6482-review
Tags
code-reviewcommitfest-6482coverageneeds-reviewpg-review-harnesspostgresqlreview-report-v2
Updated
2026-08-28T14:50:40.940703+00:00
Verdict / Summaryneeds-review
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):

Changed symbols: transformTableLikeClause, expandTableLikeClause

What the patch does:

  1. Adds CREATE_TABLE_LIKE_COMMENTS to the deferral-option mask in transformTableLikeClause (parse_utilcmd.c:1311-1317) so expandTableLikeClause is driven when INCLUDING COMMENTS is requested.
  2. Adds a new block in expandTableLikeClause (parse_utilcmd.c:1631-1652) that calls GetComment(RelationGetRelid(relation), RelationRelationId, 0) on the LIKE source and, if non-NULL, builds a CommentStmt with objtype = OBJECT_TABLE and object = list_make2(schemaname, relname) (or list_make1(relname)), appended to result.
  3. 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.

SeatHandoff report slug
pg-patch-reviewercommitfest-6482-review-handoff-patch-reviewer
pg-security-reviewercommitfest-6482-review-handoff-security-reviewer
pg-finding-verifiercommitfest-6482-review-handoff-verifier
pg-test-authorcommitfest-6482-review-handoff-test-author
pg-change-coverage-reviewercommitfest-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

F1

(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):

c
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).

F2

(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).

F3

(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.

F4

(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.

F5

(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.

F6

(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.

COV-1

(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

IDSeverityClassStatusMethod
F1MAJORcorrectnessverifiedrepro
F2MINORdocsverifiedstatic-check
F3MINORcorrectnesscannot-verify (design-choice)repro
F4NITmaintainabilityverifiedstatic-check
F5MINORtestsverifiedstatic-check
F6NITmaintainabilityrefuted (benign)static-check
COV-1MINORtestsverifiedverified-by-coverage

Repair Validation Summary

IDPatch statusValidation statusMethods
F1provided (sha256 a4ea779f...)passedapply-check, diff-check, compile, repro, targeted-test
F2provided (sha256 c30d8464...)passedapply-check, diff-check, doc-build
F3waived (design-choice)waived—
F4provided (sha256 a4ea779f...)passedapply-check, diff-check, compile, static-check, targeted-test
F5provided (sha256 231fe83a...)passedapply-check, diff-check, targeted-test
F6not-applicable-refutednot-applicable-refuted—
COV-1provided (sha256 231fe83a...)passedapply-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

MetricCount
Changed executable lines11
Covered changed lines10
Compiler-uncovered changed lines1
Uncovered changed lines (semantic)1
Structural uncovered changed lines0
Changed lines without coverage coordinates0
Changed branches6
Covered changed branches5
Uncovered branches1

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):

c
else
    stmt->object = (Node *)list_make1(makeString(heapRel->relname));

Uncovered branch

Line 1643 branch 1 (false outcome of if (heapRel->schemaname)):

Touched functions

FunctionLines (covered/total)Branches (covered/total)
expandTableLikeClause10/115/6
transformTableLikeClause1/12/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

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:

  1. e08cb97f-...@uni-muenster.de (2026-02-12, patch) — Original bug report + v1 patch.
  2. CAHGQGwE...@mail.gmail.com (2026-02-13, review) — Fujii Masao: multi-LIKE semantics question.
  3. 5888209c-...@uni-muenster.de (2026-02-13, author-reply) — Author proposes newline-separated concatenation; v2 patch.
  4. ceccea29-...@uni-muenster.de (2026-02-26, patch) — Rebase (v3).
  5. CAL-Pge4e...@mail.gmail.com (2026-03-24, review) — Carlos: tests OK, requests docs update, proposes concatenation wording.
  6. fda18ba2-...@uni-muenster.de (2026-03-25, author-reply) — Author confirms docs intent; asks reviewers to weigh in.
  7. tencent_D0A4135E...@qq.com (2026-07-18, review) — ZizhuanLiu: suggests skip-on-multiple.
  8. 88b16128-...@uni-muenster.de (2026-07-23, author-reply) — Author disagrees with blanket skip; open to withdrawing if concatenation impractical.

Per-finding dispositions:

Aggregated Test Plan

The proposed cf6482_like_comments regression test (proposal-only, not applied to the reviewed worktree) exercises:

Validated via make -C src/test/regress check-tests TESTS=cf6482_like_comments (All tests passed) against the patched disposable build.

Residual risk

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.*