fix: Upgrade existing publications to publish generated columns on PG18+#4045
fix: Upgrade existing publications to publish generated columns on PG18+#4045
Conversation
When Electric starts with an existing publication that was created before PostgreSQL 18 generated columns support, automatically ALTER the publication to add `publish_generated_columns = stored` if the database is PG18+. Fixes #4038 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4045 +/- ##
==========================================
+ Coverage 85.78% 88.67% +2.88%
==========================================
Files 51 25 -26
Lines 3399 2438 -961
Branches 611 609 -2
==========================================
- Hits 2916 2162 -754
+ Misses 481 274 -207
Partials 2 2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 63fa650530
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| %{ | ||
| pg_supports_generated_columns?: true, | ||
| publishes_generated_columns?: false, | ||
| can_alter_publication?: true | ||
| } = status, |
There was a problem hiding this comment.
Skip the generated-column upgrade in manual publishing mode
When ELECTRIC_MANUAL_TABLE_PUBLISHING=true, the rest of this module avoids mutating the publication via can_update_publication?/1, but this new branch bypasses that guard and will still run ALTER PUBLICATION whenever a PG18 publication reports publish_generated_columns = none. In practice, simply starting Electric against a manually managed publication can now rewrite it, which violates the manual-mode contract and creates drift from the operator-managed SQL.
Useful? React with 👍 / 👎.
| "Upgrading publication #{state.publication_name} to publish generated columns (PostgreSQL 18+ detected)" | ||
| ) | ||
|
|
||
| Configuration.alter_publication_set_generated_columns(state.db_pool, state.publication_name) |
There was a problem hiding this comment.
Don't auto-upgrade publications explicitly set to
none
This upgrade path cannot distinguish a publication that predates PG18 from one that an operator intentionally configured with publish_generated_columns = none: check_publication_status!/2 only gives us a boolean, and every false value reaches this ALTER PUBLICATION. That means a deployment relying on the existing none behavior (for example, to keep generated columns excluded and use the columns= workaround) will be silently flipped to stored on startup or the next shape addition, changing replication semantics for all tables instead of preserving the configured mode.
Useful? React with 👍 / 👎.
The test was checking that a 503 is returned when the publication doesn't publish generated columns. With the auto-upgrade fix, the configurator now automatically upgrades the publication, so the shape request succeeds with 200 instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
TEST BODY |
Claude Code ReviewSummaryThis PR fixes a real upgrade-path bug: when a publication was created on PG < 18 and the user later upgrades to PG18+, Electric now automatically issues What's Working Well
Issues FoundImportant (Should Fix)1. ALTER failure escalates to a global configuration error affecting all shapes File: Issue: The caller in Impact: A transient failure to upgrade the publication's generated-column setting would cause all shapes to fail with a configuration error until the connection subsystem restarts. Without this PR, a transient failure would leave Suggested fix: Change 2. Unquoted publication name in test setup SQL Files: The test setup uses unquoted string interpolation for the publication name. Production code uses Suggestions (Nice to Have)3. PG < 18 tests silently pass with zero assertions: All three new tests wrap their body in 4. Issue ConformanceIssue #4038 describes a user on PG18 getting a 400 error for shapes with stored generated columns. The PR correctly identifies that the user's reported 400 was likely due to running a pre-v1.2.0 Electric image, while the codebase had a separate real bug in the publication upgrade path (would produce 503s on PG18 with a pre-existing publication). The fix addresses the real bug precisely and the changeset accurately describes the scope. Issue conformance is solid. Previous Review StatusNo prior review — first iteration. Review iteration: 1 | 2026-03-23 |
Use non-bang Postgrex.query/3 for the publication upgrade so that a transient failure only affects shapes needing generated columns, rather than escalating to a global configuration error affecting all shapes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Accidentally modified - please ignore |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
publish_generated_columns = storedALTER PUBLICATION ... SET (publish_generated_columns = stored)to upgrade the publicationpg_supports_generated_columns?field topublication_statusto distinguish "PG < 18" from "PG >= 18 but publication not configured"Context
Electric only sets
publish_generated_columns = storedduringCREATE PUBLICATION(added in PR #3297). If a user was on PG < 18 when the publication was created, then upgraded to PG18, the existing publication wouldn't have this setting. This would cause shapes with generated columns to fail with a 503 error.Fixes #4038
Test plan
pg_supports_generated_columns?field incheck_publication_status!alter_publication_set_generated_columns/2function🤖 Generated with Claude Code