Skip to content

fix: guard delete detection against non-integer/large primary keys (#42) - #51

Merged
y-ken merged 1 commit into
masterfrom
fix/delete-detection-range
Jun 16, 2026
Merged

fix: guard delete detection against non-integer/large primary keys (#42)#51
y-ken merged 1 commit into
masterfrom
fix/delete-detection-range

Conversation

@y-ken

@y-ken y-ken commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the mysql_replicator: failed to execute query / bad value for range error reported in #42.

Root cause

On the first poll (no previous snapshot yet), delete detection ran:

deleted_ids = [*1...current_ids.max] - current_ids

This builds an integer Range from the primary-key values, which:

  • raises bad value for range when the primary_key is non-integer (e.g. a UUID or string id) — exactly mysql_replicator: failed to execute query.error #42;
  • for large ids, allocates a huge array ([*1...10_000_000]);
  • emits phantom delete events for ids that never existed (every integer missing between 1 and max).

Fix

Extract the logic into detect_deleted_ids(previous_ids, current_ids):

def detect_deleted_ids(previous_ids, current_ids)
  return [] if previous_ids.empty?   # first poll: baseline only
  return [] if current_ids.empty?    # don't mass-delete on an empty result
  previous_ids - current_ids
end

The first poll now only establishes a baseline (reports nothing deleted); deletions are detected on subsequent polls by diffing against the previous snapshot. All other behavior is unchanged.

Tests

Added unit regression tests (no DB needed) covering:

  • first poll with string keys → no bad value for range;
  • first poll with sparse integer ids → no phantom deletes;
  • normal delete diffed against the previous snapshot;
  • emptied result set → no mass delete.

Verified locally on Ruby 3.4 (6 tests, 11 assertions, 0 failures).

Closes #42

🤖 Generated with Claude Code

The first-poll branch built `[*1...current_ids.max]` from primary-key
values, which raised "bad value for range" for non-integer keys (e.g.
UUIDs) and, for large/sparse integer ids, allocated a huge array and
emitted phantom delete events for ids that never existed.

Extract the logic into `detect_deleted_ids`: the first poll only
establishes a baseline (reports nothing deleted), and subsequent polls
diff against the previous snapshot. Behavior is otherwise unchanged,
including not mass-deleting on an empty result set.

Add regression tests covering string keys, sparse ids, a normal delete,
and an emptied result set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@y-ken
y-ken merged commit beb9d88 into master Jun 16, 2026
9 checks passed
@y-ken
y-ken deleted the fix/delete-detection-range branch June 16, 2026 10:12
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.

mysql_replicator: failed to execute query.error

1 participant