create table like including storage parameter

First seen: 2025-09-29 00:00:00+00:00 · Messages: 35 · Participants: 9

Latest Update

2026-06-04 · claude-opus-4-6

New in this round: Lakshmi Krishnamurthy responds to Zsolt's review with design clarification

Author's response (2026-06-04)

Lakshmi (jian.universality@gmail.com) responds to Zsolt Parragi's two findings from the previous round with concrete design decisions:

1. View triggers: escalated from "skip INSTEAD OF" to "skip ALL view triggers"

Lakshmi agrees with Zsolt's silent-skip approach but goes further than just INSTEAD OF triggers. The new position is: all triggers on a source view should be skipped entirely when cloning to a regular table. The rationale cites the documentation that statement-level triggers on views only fire when handled by row-level INSTEAD OF triggers — since INSTEAD OF triggers cannot exist on tables, the entire trigger ecosystem of a view is semantically meaningless on a regular table. This is a meaningful scope expansion beyond the previous discussion which focused only on INSTEAD OF triggers specifically.

2. Foreign table trigger restrictions documented

Lakshmi also identifies an additional edge case: foreign tables do not support constraint triggers or triggers with transition tables. The patch will silently ignore these incompatible triggers during CREATE FOREIGN TABLE ... LIKE, extending the same "skip what doesn't apply" philosophy.

3. stmt->transformed — acknowledged as unnecessary

Lakshmi confirms Zsolt's finding: "You are right, we don't actually transform the stmt->whenClause." This validates the dead-code removal suggestion and implies the next patch version will drop the unnecessary transformed = true assignment and associated signature changes.

Technical significance

The key design evolution is the broadening from "skip INSTEAD OF triggers when target is a table" to "skip all triggers when source is a view." This is architecturally cleaner (one simple relkind check rather than per-trigger-type filtering) and avoids subtle issues where statement-level view triggers would be copied but never fire correctly on the target table.

History (2 prior analyses)
2026-06-01 · claude-opus-4-6

CREATE TABLE LIKE: INCLUDING PARAMETERS and INCLUDING TRIGGERS — May 2026 Summary

Overview

This thread advances two patches extending CREATE TABLE ... (LIKE source INCLUDING ...) to cover two previously unsupported attribute categories: table-level storage parameters (reloptions like fillfactor, autovacuum_*, toast.*) and triggers. Both patches reached near-commit-readiness by month's end, with architectural debates settled and only polish items remaining.

Key Developments

INCLUDING PARAMETERS — Syntax and Semantics Settled

The syntax for copying table-level reloptions was finalized as INCLUDING PARAMETERS (not INCLUDING STORAGE PARAMETER), after David G. Johnston argued the qualifier "STORAGE" was too narrow for what might eventually include planner-related options. PARAMETERS was added as an unreserved bare-label keyword with no backward-compatibility risk.

Semantic boundaries were established:

  • Foreign tables: silently ignored (no traditional reloptions)
  • Views: rejected — view reloptions (check_option, security_barrier) have a disjoint namespace
  • Column-level attribute options (e.g., n_distinct): explicitly excluded — these are data-derived planner hints inappropriate for empty clone tables

Implementation reuses the existing untransformRelOptions() function for catalog decompilation, per Euler Taveira's review.

INCLUDING TRIGGERS — Architecture Debate Resolved

The most significant architectural discussion concerned whether to inject Oid fields into CreateTrigStmt for efficient cloning (avoiding name re-resolution). Robert Haas settled the debate decisively: maintain consistency with the existing catalog round-trip pattern (OID → name → parse node → re-execute), even though it's "incredibly ugly," because fragmenting the pattern makes future system-wide cleanup impossible.

Trigger cloning semantics were refined:

  • Internal triggers (FK-associated): skipped — they're owned by constraints
  • INSTEAD OF triggers: rejected on non-view targets
  • Whole-row WHEN clause references: rejected (rowtype safety)
  • tgenabled state: preserved (matching constraint precedent)
  • Trigger comments: copied only when INCLUDING COMMENTS specified
  • Partition triggers: not recursively cloned

A transformed boolean flag on CreateTrigStmt signals that the whenClause is already a transformed expression tree (from pg_trigger.tgqual), preventing redundant and incorrect re-parse-analysis.

Final Review Round — Converging on Commit

Henson Choi's detailed review confirmed the patch is "in good shape" with no blockers, but identified:

  • A test isolation bug: create_table_like.sql depends on trigger_func from triggers.sql — breaks standalone test runs
  • Missing EXCLUDING TRIGGERS test coverage
  • The whole-row WHEN restriction may be liftable in future via composite-type OID remapping (suggests XXX comment)
  • Minor documentation wording inconsistencies and commit message grammar

No new architectural objections were raised. The RangeVar-vs-Oid debate, INCLUDING PARAMETERS naming, and map_variable_attnos() approach were all endorsed by the reviewer.

Current Status

Both patches appear commit-ready pending minor polish (test self-containment fix, documentation alignment, cosmetic cleanups). The thread has converged on all design decisions.


2026-06-01 · claude-opus-4-6

New in this round: Zsolt Parragi's late review and Lakshmi's status update

Two new messages since the last analysis.

Lakshmi's message (2026-05-27)

From the email address (lakshmigcdac@gmail.com), this appears to be a brief status/acknowledgment message. No substantive technical content is visible beyond the metadata.

Zsolt Parragi's review (2026-05-27) — Two substantive findings

Zsolt Parragi returns after missing several patch iterations and raises two concrete issues:

1. INSTEAD OF triggers not properly skipped (bug report)

Zsolt provides a complete reproducer: creating an INSTEAD OF trigger on a view, then doing CREATE TABLE t_all (LIKE v_instead INCLUDING ALL) causes an error:

ERROR:  "t_all" is a table
DETAIL:  Tables cannot have INSTEAD OF triggers.

This was already identified in prior analysis as a design decision (INSTEAD OF triggers on views should be rejected when cloning onto a plain table), but Zsolt's point is that the error should be silently skipped rather than producing a hard failure. The distinction is important: INCLUDING ALL should not blow up when the source is a view that happens to have view-specific triggers. The user's intent with INCLUDING ALL is "copy everything that makes sense for the target relkind," not "fail if anything is incompatible." This mirrors how INCLUDING PARAMETERS is silently ignored for foreign tables.

2. Unnecessary stmt->transformed = true assignment (code simplification)

Zsolt identifies dead code in the CreateTrigger refactoring. When the else branch executes (i.e., the statement was NOT already transformed), it sets stmt->transformed = true at the end — but this assignment is pointless because:

  • The statement is not reused after this point
  • The flag is never checked again downstream
  • The transformation operates on a copy anyway

Zsolt confirms "everything seems to work fine if I remove this assignment" and notes that removing it eliminates the need for const-related function signature changes that were introduced solely to support this flag mutation. This is a genuine simplification opportunity that reduces the patch's footprint.

Technical significance

The INSTEAD OF trigger issue refines the earlier design discussion — it's not about whether to reject them (that was settled), but about the UX of how (silent skip vs. hard error, especially under INCLUDING ALL). The stmt->transformed observation is a clean code-reduction that simplifies the patch without behavioral change.