Skip to content

feat: add support for trigger comments, trigger enabled/disabled state, and sequence comments#479

Open
ayusssmaan wants to merge 3 commits into
pgplex:mainfrom
ayusssmaan:feat/trigger-sequence-comments-and-state
Open

feat: add support for trigger comments, trigger enabled/disabled state, and sequence comments#479
ayusssmaan wants to merge 3 commits into
pgplex:mainfrom
ayusssmaan:feat/trigger-sequence-comments-and-state

Conversation

@ayusssmaan

Copy link
Copy Markdown
Contributor

Four related gaps where pgschema silently ignored real schema properties,
causing silent drift between the declared model and the live database.

What changed

1. Trigger comments

pgschema had no awareness of COMMENT ON TRIGGER. A comment declared in
the model was never applied; an unwanted comment on the live DB was never
flagged as drift.

  • ir/ir.go: add Comment string to TriggerDef
  • ir/inspector.go + ir/queries/queries.sql.go: read pg_description
    for trigger OIDs
  • internal/diff/trigger.go: diff and emit COMMENT ON TRIGGER ... ON ... IS '...'

2. Trigger enabled/disabled state

pgschema had no awareness of pg_trigger.tgenabled. A trigger disabled in
the model was never applied; a trigger enabled/disabled on the live DB was
never flagged as drift.

  • ir/ir.go: add Enabled bool to TriggerDef
  • ir/inspector.go + ir/queries/queries.sql.go: read tgenabled from
    pg_trigger
  • internal/diff/trigger.go: diff and emit ALTER TABLE ENABLE/DISABLE TRIGGER

3. Sequence comments

pgschema had no awareness of COMMENT ON SEQUENCE. A sequence comment in
the model was never applied; an unwanted comment on the live DB was never
flagged as drift.

  • ir/ir.go: add Comment string to SequenceDef
  • ir/inspector.go + ir/queries/queries.sql.go: read pg_description
    for sequence OIDs
  • internal/diff/sequence.go: diff and emit COMMENT ON SEQUENCE ... IS '...'

4. Fix: SERIAL sequence comment idempotency

When a table with BIGSERIAL/SERIAL columns was created for the first
time, pgschema correctly skipped emitting a standalone CREATE SEQUENCE
(because CREATE TABLE creates it implicitly). However, this also
accidentally skipped emitting any COMMENT ON SEQUENCE declared in the
model. On the second run the sequence existed in the live DB, the comment
diff fired, and all sequence comments were re-applied indefinitely on every
subsequent run.

  • internal/diff/diff.go: track SERIAL-owned sequences that were
    skipped from addedSequences but carry a comment into a new
    addedSerialSeqComments list; emit their COMMENT ON SEQUENCE after all
    CREATE TABLE calls complete

Verified locally: two consecutive deploys against a freshly created wiser DB
— all 14 schemas report "No changes to apply" on the second run.

Tests

Four new fixtures, all passing:

  • testdata/diff/comment/add_trigger_comment/
  • testdata/diff/comment/add_sequence_comment/
  • testdata/diff/comment/add_serial_sequence_comment_on_create/ ← idempotency fix
  • testdata/diff/create_trigger/disable_trigger/

…e, and sequence comments

- Trigger comments: inspect COMMENT ON TRIGGER via pg_description, emit COMMENT ON TRIGGER DDL on diff
- Trigger state: inspect trigger enabled flag (pg_trigger.tgenabled), emit ALTER TABLE ENABLE/DISABLE TRIGGER on diff
- Sequence comments: inspect COMMENT ON SEQUENCE via pg_description, emit COMMENT ON SEQUENCE DDL on diff
- Test fixtures: add_trigger_comment, add_sequence_comment, disable_trigger (all passing)
…CREATE TABLE

When a table with BIGSERIAL/SERIAL columns was created for the first time,
pgschema skipped the sequence from addedSequences (correctly, since CREATE TABLE
creates it implicitly), but this also skipped emitting any COMMENT ON SEQUENCE
declared in the model. On the second run, the sequence existed in the live DB
and the comment diff fired, re-applying all sequence comments indefinitely.

Fix: track skipped-but-commented SERIAL sequences in addedSerialSeqComments and
emit their COMMENT ON SEQUENCE statements after all CREATE TABLE calls complete.

Test: add_serial_sequence_comment_on_create fixture verifies COMMENT is emitted
on first deploy alongside CREATE TABLE, not deferred to a subsequent run.
@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown

Greptile Summary

This PR teaches pgschema to track more trigger and sequence metadata. The main changes are:

  • Trigger comments are inspected, stored in IR, and diffed.
  • Trigger enabled or disabled state is inspected, stored in IR, and diffed.
  • Sequence comments are inspected, stored in IR, and diffed.
  • SERIAL-owned sequence comments are emitted after implicit sequence creation.
  • New fixtures cover trigger comments, sequence comments, serial sequence comments, and disabled triggers.

Confidence Score: 2/5

This should be fixed before merging.

  • View trigger comment and enabled-state changes can be silently ignored.
  • Disabled view triggers can be created as enabled.
  • Added triggers on existing tables can miss both comments and disabled state.
  • Existing serialized trigger models that omit enabled can be treated as disabled.

internal/diff/view.go, internal/diff/trigger.go, internal/diff/table.go, and ir/ir.go need follow-up.

Important Files Changed

Filename Overview
internal/diff/view.go View trigger diff and modify paths were not updated to preserve the new trigger metadata.
internal/diff/trigger.go Table trigger creation handles comments and disabled state, but view trigger creation only handles comments.
internal/diff/table.go Modified table triggers handle metadata changes, but newly added triggers on existing tables do not.
ir/ir.go The new trigger enabled field has a zero-value default that conflicts with PostgreSQL's enabled-by-default behavior.

Comments Outside Diff (1)

  1. internal/diff/table.go, line 1360-1371 (link)

    P1 Added table trigger metadata skipped

    When a trigger is added to an existing table, this branch only collects the CREATE TRIGGER SQL. It does not emit the new COMMENT ON TRIGGER statement or the ALTER TABLE ... DISABLE TRIGGER statement for disabled triggers. A migration that adds a commented disabled trigger to an existing table will create an enabled trigger with no comment.

Reviews (1): Last reviewed commit: "fix: emit COMMENT ON SEQUENCE for SERIAL..." | Re-trigger Greptile

Comment thread internal/diff/trigger.go
Comment thread ir/ir.go Outdated
Greptile fixes:
- ir/ir.go: rename Enabled bool → Disabled bool (omitempty) so zero-value means
  enabled, matching Postgres default; avoids spurious DISABLE TRIGGER on triggers
  that omit the field
- ir/inspector.go: set Disabled=true only when tgenabled='D'
- internal/diff/trigger.go: update all !trigger.Enabled → trigger.Disabled;
  add DISABLE TRIGGER emission to view trigger create path (was missing)
- internal/diff/table.go: update Enabled → Disabled in trigger diff detection
- internal/diff/view.go: emit trigger comment and disabled state in both
  constraint-recreate and non-constraint modify paths for view triggers

CI fix:
- Add plan.sql, plan.json, plan.txt for all 4 new fixtures so TestPlanAndApply passes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds missing schema drift detection and DDL generation for trigger comments, trigger enabled/disabled state, and sequence comments, plus fixes idempotency for comments on SERIAL-owned sequences created implicitly by CREATE TABLE.

Changes:

  • Extend IR + inspector queries to load trigger comments, trigger tgenabled state, and sequence comments from PostgreSQL catalogs.
  • Diff and emit COMMENT ON TRIGGER, ALTER TABLE ENABLE/DISABLE TRIGGER, and COMMENT ON SEQUENCE statements.
  • Fix SERIAL sequence comment idempotency by emitting comments for implicitly created sequences after table creation.

Reviewed changes

Copilot reviewed 30 out of 32 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
testdata/diff/create_trigger/disable_trigger/plan.txt New fixture asserting trigger disable shows up in plan output.
testdata/diff/create_trigger/disable_trigger/plan.sql New fixture asserting ALTER TABLE ... DISABLE TRIGGER SQL output.
testdata/diff/create_trigger/disable_trigger/plan.json New fixture asserting JSON step metadata for disabling a trigger.
testdata/diff/create_trigger/disable_trigger/old.sql Fixture “before” schema for trigger disable case.
testdata/diff/create_trigger/disable_trigger/new.sql Fixture “after” schema including disabled trigger.
testdata/diff/create_trigger/disable_trigger/diff.sql Fixture expected diff SQL for disabling a trigger.
testdata/diff/comment/add_trigger_comment/plan.txt New fixture asserting trigger comment appears in plan output.
testdata/diff/comment/add_trigger_comment/plan.sql New fixture asserting COMMENT ON TRIGGER SQL output.
testdata/diff/comment/add_trigger_comment/plan.json New fixture asserting JSON step metadata for trigger comment.
testdata/diff/comment/add_trigger_comment/old.sql Fixture “before” schema for trigger comment case.
testdata/diff/comment/add_trigger_comment/new.sql Fixture “after” schema including trigger comment.
testdata/diff/comment/add_trigger_comment/diff.sql Fixture expected diff SQL for trigger comment.
testdata/diff/comment/add_serial_sequence_comment_on_create/plan.txt New fixture covering SERIAL-owned sequence comment emission on initial create.
testdata/diff/comment/add_serial_sequence_comment_on_create/plan.sql New fixture asserting comment emitted after CREATE TABLE for SERIAL sequence.
testdata/diff/comment/add_serial_sequence_comment_on_create/plan.json New fixture asserting JSON step metadata for SERIAL sequence comment.
testdata/diff/comment/add_serial_sequence_comment_on_create/old.sql Fixture “before” schema (empty) for SERIAL sequence comment case.
testdata/diff/comment/add_serial_sequence_comment_on_create/new.sql Fixture “after” schema including sequence comment on implicitly created sequence.
testdata/diff/comment/add_serial_sequence_comment_on_create/diff.sql Fixture expected diff SQL for SERIAL sequence comment on create.
testdata/diff/comment/add_sequence_comment/plan.txt New fixture asserting sequence comment drift is detected in plan output.
testdata/diff/comment/add_sequence_comment/plan.sql New fixture asserting COMMENT ON SEQUENCE SQL output.
testdata/diff/comment/add_sequence_comment/plan.json New fixture asserting JSON step metadata for sequence comment changes.
testdata/diff/comment/add_sequence_comment/old.sql Fixture “before” schema for sequence comment drift case.
testdata/diff/comment/add_sequence_comment/new.sql Fixture “after” schema including sequence comments.
testdata/diff/comment/add_sequence_comment/diff.sql Fixture expected diff SQL for sequence comments.
ir/queries/queries.sql.go Extend inspector queries/rows to include sequence comments and trigger comment/enabled fields.
ir/ir.go Add trigger disabled state to IR representation.
ir/inspector.go Populate IR with sequence comments and trigger disabled state from catalog query results.
internal/diff/view.go Emit trigger comment + enabled/disabled statements when modifying view triggers.
internal/diff/trigger.go Emit trigger comment + enabled/disabled statements when creating triggers; add helper generators.
internal/diff/table.go Treat trigger comment/disabled changes as trigger modifications and emit corresponding DDL.
internal/diff/sequence.go Emit COMMENT ON SEQUENCE on create/alter when sequence comments are present/changed.
internal/diff/diff.go Track SERIAL-owned sequences skipped from creation but needing comment emission to ensure idempotency.
Files not reviewed (1)
  • ir/queries/queries.sql.go: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/diff/table.go
Comment on lines +1434 to 1442
// Emit COMMENT ON TRIGGER for comment changes (including after structural recreate)
if commentChanged {
generateTriggerComment(triggerDiff.New, td.Table.Schema, td.Table.Name, targetSchema, DiffTypeTableTrigger, collector)
}

// Emit ENABLE/DISABLE TRIGGER for enabled state changes
if enabledChanged {
generateTriggerEnabledState(triggerDiff.New, td.Table.Schema, td.Table.Name, targetSchema, collector)
}
Comment thread internal/diff/view.go
Comment on lines +439 to +443
generateTriggerComment(triggerDiff.New, diff.New.Schema, diff.New.Name, targetSchema, DiffTypeViewTrigger, collector)
}
if triggerDiff.New.Disabled {
generateTriggerEnabledState(triggerDiff.New, diff.New.Schema, diff.New.Name, targetSchema, collector)
}
Comment thread internal/diff/view.go
Comment on lines +455 to +459
generateTriggerComment(triggerDiff.New, diff.New.Schema, diff.New.Name, targetSchema, DiffTypeViewTrigger, collector)
}
if triggerDiff.New.Disabled {
generateTriggerEnabledState(triggerDiff.New, diff.New.Schema, diff.New.Name, targetSchema, collector)
}
Comment thread internal/diff/trigger.go
Comment on lines +369 to +373
sql := fmt.Sprintf("ALTER TABLE %s %s TRIGGER %s;", tableName, state, ir.QuoteIdentifier(trigger.Name))
context := &diffContext{
Type: DiffTypeTableTrigger,
Operation: DiffOperationAlter,
Path: fmt.Sprintf("%s.%s.%s", schema, table, trigger.Name),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants