Skip to content

WIP: PG sequence bug repro + Postgres/MySQL CI matrix (#51)#52

Closed
ngan wants to merge 5 commits into
mainfrom
np-pg-sequence-repro
Closed

WIP: PG sequence bug repro + Postgres/MySQL CI matrix (#51)#52
ngan wants to merge 5 commits into
mainfrom
np-pg-sequence-repro

Conversation

@ngan
Copy link
Copy Markdown
Collaborator

@ngan ngan commented May 6, 2026

Summary

Expected CI state on this commit

  • sqlite jobs: green
  • mysql2 job: green (immune — AUTO_INCREMENT advances on explicit-id INSERTs)
  • postgresql job: red on the new spec — PG::UniqueViolation at id=1

The fix to ActiveRecordCoder#mount will land in a follow-up commit on this branch.

Refs #51

🤖 Generated with Claude Code

ngan and others added 5 commits May 6, 2026 09:57
Adds a `test_db` job covering rails_8.1 against postgresql and mysql2 with
service containers, plus the infrastructure to make the dummy app's
adapter configurable via `FIXTURE_KIT_DB`. Includes a failing integration
spec that demonstrates the bug from issue #51: cached fixtures replay
explicit-id INSERTs, but Postgres sequences don't advance, so a later
`Model.create` collides at id=1.

The spec passes on sqlite/mysql (their PK generators advance from explicit
inserts) and fails on postgres. Fix to follow.
The job-level BUNDLE_GEMFILE was being inherited into the dummy app
install step, causing bundler to look for gemfiles/rails_8.1.gemfile
relative to spec/dummy and fail with ENOENT.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ActiveRecordCoder#mount replays INSERTs that include explicit primary
key values. Postgres sequences don't observe these inserts, so a later
Model.create can call nextval and collide with an id we just inserted —
intermittent PG::UniqueViolation in test runs that mount the cache onto
a database whose sequence is at its initial value (e.g. parallel test
workers with their own DB copies).

Call reset_pk_sequence! per model after the batch executes. The method
is only defined on the Postgres adapter, so the respond_to? guard makes
this a no-op on MySQL and SQLite, whose AUTO_INCREMENT/INTEGER PK
generators already advance from explicit-id INSERTs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Group by connection_pool and wrap mount work in pool.with_connection,
  matching Rails' fixture insert flow. Behaviorally identical inside a
  test transaction, but more correct under role switching or
  programmatic use.
- Prefer the batched reset_column_sequences! when the adapter exposes it
  (Rails 8.2+); fall back to per-table reset_pk_sequence! on 8.0/8.1.
  The batched path is unit-tested but won't have CI coverage until 8.2
  ships and we add it to the appraisal matrix.
- Skip virtual/generated columns when generating cached INSERTs.
  Without this, models with t.virtual columns crashed mount with
  "cannot INSERT into generated column". Adds a computed_widgets table
  with a stored generated column to the dummy app and a regression
  spec that exercises the round-trip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add verify_foreign_keys! mirroring Rails' fixture-loading pattern.
  Calls connection.check_all_foreign_keys_valid! when
  ActiveRecord.verify_foreign_keys_for_fixtures is true (default since
  Rails 8.0 load_defaults). PG and SQLite raise on violations; MySQL
  is a no-op. Wraps the StatementInvalid in a FixtureKit::Error with
  a hint that the cache may be stale relative to the schema.
- Rename the execute_batch label from "FixtureKit Load" to
  "FixtureKit Insert" to match Rails' naming convention.
- Harden the sql.active_record subscriber: use safe_constantize and
  require the result to be a Class < ActiveRecord::Base. Without this
  the renamed label feeds back into nested-fixture generates and
  crashes when constantize hits the FixtureKit module.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ngan
Copy link
Copy Markdown
Collaborator Author

ngan commented May 6, 2026

Superseded by stacked PRs:

Closes #51 via #58.

@ngan ngan closed this May 6, 2026
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.

1 participant