Skip to content

Use bitemporal_id as primary key for Rails 8+ AR::Batches#251

Merged
kymmt90 merged 1 commit intomasterfrom
ar-batches-pk
Apr 9, 2026
Merged

Use bitemporal_id as primary key for Rails 8+ AR::Batches#251
kymmt90 merged 1 commit intomasterfrom
ar-batches-pk

Conversation

@kymmt90
Copy link
Copy Markdown
Member

@kymmt90 kymmt90 commented Apr 6, 2026

Problem

Since ar-bitemporal 7.0.0 changed the effective primary key back to id, find_each, find_in_batches, and in_batches use the model's id as the cursor column in Rails 8+. This results in a mismatch between the primary key (id) and the value used in cursor conditions (bitemporal_id).

This problem may cause the same record to be read repeatedly when batching is needed.

Solution

This PR applies use_bitemporal_id_as_primary_key to the three batch methods. This ensures the cursor column resolves to bitemporal_id for the duration of each batch call.

@kymmt90 kymmt90 marked this pull request as ready for review April 8, 2026 08:40
@auto-assign auto-assign bot requested review from lighty and mkmn April 8, 2026 08:40
@kymmt90 kymmt90 removed request for lighty and mkmn April 8, 2026 08:41
@krororo
Copy link
Copy Markdown
Collaborator

krororo commented Apr 8, 2026

The value retrieved here was the value of the bitemporal_id column, not the id column.
https://github.com/rails/rails/blob/v8.0.4/activerecord/lib/active_record/relation/batches.rb#L437

Consequently, the value passed to the subsequent condition did not match the column.
https://github.com/rails/rails/blob/v8.0.4/activerecord/lib/active_record/relation/batches.rb#L484-L485

Copy link
Copy Markdown
Collaborator

@krororo krororo left a comment

Choose a reason for hiding this comment

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

LGTM

@kymmt90 kymmt90 merged commit c9db050 into master Apr 9, 2026
20 checks passed
@kymmt90 kymmt90 deleted the ar-batches-pk branch April 9, 2026 07:22
kymmt90 added a commit that referenced this pull request Apr 9, 2026
`excluding` / `without` internally calls `predicate_builder[primary_key, records]`
to build a NOT IN clause. Without the primary_key override, this generates
`WHERE id NOT IN (...)` instead of `WHERE bitemporal_id NOT IN (...)`,
causing incorrect record exclusion for bitemporal models with history.

This is the same class of issue fixed in PR #251 for AR::Batches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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