Skip to content

fix(migrations): coerce COUNT result to Number before comparison#415

Merged
luislhl merged 1 commit into
masterfrom
fix/migration-count-bigint-string-comparison
May 6, 2026
Merged

fix(migrations): coerce COUNT result to Number before comparison#415
luislhl merged 1 commit into
masterfrom
fix/migration-count-bigint-string-comparison

Conversation

@luislhl
Copy link
Copy Markdown
Collaborator

@luislhl luislhl commented May 6, 2026

Summary

  • db/config.js sets bigNumberStrings: true for all environments, causing mysql2 to return COUNT() values as strings ("0") instead of JavaScript numbers (0)
  • Four index-creation migrations used strict equality (=== 0 / > 0) against that string value — "0" === 0 is false in JS, so the CREATE INDEX block was always skipped
  • Migrations completed without error and were recorded in SequelizeMeta, but the indexes were never actually created

Affected migrations

Migration Index
20251201104138-add-tx-output-utxo-lookup-index idx_tx_output_utxo_lookup
20260108100000-add-tx-output-locked-heightlock-index idx_tx_output_locked_heightlock
20260108100001-add-tx-output-locked-timelock-index idx_tx_output_locked_timelock
20260108100002-add-address-tx-history-addr-voided-token-index idx_address_tx_history_addr_voided_token

Fix

Wrap the COUNT() result with Number() before comparing, so both string and numeric returns work correctly:

- if (indexes[0].count === 0) {
+ if (Number(indexes[0].count) === 0) {

Manual remediation required for existing databases

Since these migrations have already run and won't execute again, the missing indexes must be created manually on any affected database (staging, production, etc.):

CREATE INDEX idx_tx_output_utxo_lookup
  ON tx_output (address, token_id, spent_by, voided, locked, authorities);

CREATE INDEX idx_tx_output_locked_heightlock
  ON tx_output (locked, heightlock);

CREATE INDEX idx_tx_output_locked_timelock
  ON tx_output (locked, timelock);

CREATE INDEX idx_address_tx_history_addr_voided_token
  ON address_tx_history (address, voided, token_id);

Test plan

  • Apply the manual SQL above to any existing affected database and confirm all 4 indexes appear
  • Spin up a fresh database and run all migrations — confirm all 4 indexes are created
  • Run the existing test suite to confirm no regressions

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Improved database index handling logic for enhanced stability and type consistency across migrations.

db/config.js sets bigNumberStrings: true for all environments, which
causes mysql2 to return COUNT() values as strings ("0") instead of
numbers (0). Four index-creation migrations used strict equality
(=== 0 / > 0) against that string, so the condition was always false
and the CREATE INDEX statements were silently skipped — migrations
completed and were recorded in SequelizeMeta but created no indexes.

Affected migrations:
- 20251201104138-add-tx-output-utxo-lookup-index
- 20260108100000-add-tx-output-locked-heightlock-index
- 20260108100001-add-tx-output-locked-timelock-index
- 20260108100002-add-address-tx-history-addr-voided-token-index

Fix: wrap the count value with Number() before comparing, so both
string and numeric returns are handled correctly.

Note: databases that already ran these migrations will not get the
indexes automatically (migrations won't re-run). The missing indexes
must be created manually:

  CREATE INDEX idx_tx_output_utxo_lookup
    ON tx_output (address, token_id, spent_by, voided, locked, authorities);
  CREATE INDEX idx_tx_output_locked_heightlock
    ON tx_output (locked, heightlock);
  CREATE INDEX idx_tx_output_locked_timelock
    ON tx_output (locked, timelock);
  CREATE INDEX idx_address_tx_history_addr_voided_token
    ON address_tx_history (address, voided, token_id);

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 6, 2026 18:44
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6576a78b-9e34-4454-9fca-d97b8ff004a2

📥 Commits

Reviewing files that changed from the base of the PR and between c0fe986 and 36c95da.

📒 Files selected for processing (4)
  • db/migrations/20251201104138-add-tx-output-utxo-lookup-index.js
  • db/migrations/20260108100000-add-tx-output-locked-heightlock-index.js
  • db/migrations/20260108100001-add-tx-output-locked-timelock-index.js
  • db/migrations/20260108100002-add-address-tx-history-addr-voided-token-index.js

📝 Walkthrough

Walkthrough

Four database migration files receive type-coercion fixes: index count results from SQL queries are wrapped with Number() before comparison checks in both up() and down() paths, ensuring numeric comparison logic instead of string comparisons.

Changes

Database Index Migration Type Coercion

Layer / File(s) Summary
Type-Coercion Fixes
db/migrations/20251201104138-add-tx-output-utxo-lookup-index.js, db/migrations/20260108100000-add-tx-output-locked-heightlock-index.js, db/migrations/20260108100001-add-tx-output-locked-timelock-index.js, db/migrations/20260108100002-add-address-tx-history-addr-voided-token-index.js
Index count results from information_schema queries are wrapped with Number() before comparison checks in all up and down migration paths to ensure numeric rather than string comparisons.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

Poem

🐰 Four migrations, one fix so bright,
Cast the counts to numbers right!
No more strings that lurk and hide,
Numeric truth on every side.
Hops through the database with delight! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: coercing COUNT results to Number in migration comparisons to fix a type-related bug.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/migration-count-bigint-string-comparison

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes several MySQL index-creation migrations that were incorrectly skipping CREATE INDEX due to COUNT() values being returned as strings (because mysql2 is configured with bigNumberStrings: true).

Changes:

  • Coerce COUNT() results via Number(indexes[0].count) before doing strict numeric comparisons in four migrations.
  • Ensures up creates indexes when missing and down drops them when present, regardless of whether the driver returns counts as strings or numbers.

Reviewed changes

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

File Description
db/migrations/20251201104138-add-tx-output-utxo-lookup-index.js Coerces index existence COUNT() to a number before comparing in up/down.
db/migrations/20260108100000-add-tx-output-locked-heightlock-index.js Coerces index existence COUNT() to a number before comparing in up/down.
db/migrations/20260108100001-add-tx-output-locked-timelock-index.js Coerces index existence COUNT() to a number before comparing in up/down.
db/migrations/20260108100002-add-address-tx-history-addr-voided-token-index.js Coerces index existence COUNT() to a number before comparing in up/down.

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

@luislhl luislhl self-assigned this May 6, 2026
@luislhl luislhl moved this from Todo to In Progress (Done) in Hathor Network May 6, 2026
@luislhl luislhl moved this from In Progress (Done) to In Review (WIP) in Hathor Network May 6, 2026
@luislhl luislhl moved this from In Review (WIP) to In Review (Done) in Hathor Network May 6, 2026
@luislhl luislhl merged commit 0654434 into master May 6, 2026
7 checks passed
@github-project-automation github-project-automation Bot moved this from In Review (Done) to Waiting to be deployed in Hathor Network May 6, 2026
tuliomir pushed a commit that referenced this pull request May 8, 2026
db/config.js sets bigNumberStrings: true for all environments, which
causes mysql2 to return COUNT() values as strings ("0") instead of
numbers (0). Four index-creation migrations used strict equality
(=== 0 / > 0) against that string, so the condition was always false
and the CREATE INDEX statements were silently skipped — migrations
completed and were recorded in SequelizeMeta but created no indexes.

Affected migrations:
- 20251201104138-add-tx-output-utxo-lookup-index
- 20260108100000-add-tx-output-locked-heightlock-index
- 20260108100001-add-tx-output-locked-timelock-index
- 20260108100002-add-address-tx-history-addr-voided-token-index

Fix: wrap the count value with Number() before comparing, so both
string and numeric returns are handled correctly.

Note: databases that already ran these migrations will not get the
indexes automatically (migrations won't re-run). The missing indexes
must be created manually:

  CREATE INDEX idx_tx_output_utxo_lookup
    ON tx_output (address, token_id, spent_by, voided, locked, authorities);
  CREATE INDEX idx_tx_output_locked_heightlock
    ON tx_output (locked, heightlock);
  CREATE INDEX idx_tx_output_locked_timelock
    ON tx_output (locked, timelock);
  CREATE INDEX idx_address_tx_history_addr_voided_token
    ON address_tx_history (address, voided, token_id);

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@luislhl luislhl mentioned this pull request May 11, 2026
2 tasks
@luislhl luislhl moved this from Waiting to be deployed to Done in Hathor Network May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants