[json] JSON integer/DOUBLE comparison can silently delete a different large ID
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Bug Report
### 1. Minimal reproduce step (Required)
**Environment**
TiDB 05b396fb66; TiKV 91ccfb2126; default config
**Steps**
Create four rows with JSON integer 2^53, integer 2^53+1, JSON DOUBLE 2^53, and sentinel 2^53+2. DELETE WHERE entity_id=CAST('9007199254740992.0' AS JSON). TiDB affects 3 and leaves only sentinel.
### 2. What did you expect to see? (Required)
Match and delete only IDs 1 and 3; preserve integer 9007199254740993 and sentinel.
### 3. What did you see instead? (Required)
Selection runs in cop[tikv], matches IDs 1,2,3, DELETE returns affected_rows=3, and persists only sentinel. MySQL 8.0.46 affects 2 and preserves IDs 2,4.
### 4. What is your TiDB version? (Required)
TiDB 05b396fb66; TiKV 91ccfb2126; default config
Likely root cause and fix direction
**Likely root cause**
TiDB CompareBinaryJSON and TiKV JsonRef PartialOrd compare JSON I64/U64 with DOUBLE by first converting the exact integer to float64. Above 2^53, distinct integers alias the same DOUBLE.
**Fix direction**
Implement exact bounded I64/U64 versus DOUBLE comparison without first narrowing the integer; share 2^53 and signed/unsigned endpoint tests across TiDB and TiKV.
Contributor guide
Research direction
Start by tracing TiDB's CompareBinaryJSON and TiKV's JsonRef PartialOrd implementations, then run the supplied JSON integer/DOUBLE DELETE reproduction in the coprocessor path. Done means distinct integers above 2^53 compare correctly, the DELETE preserves 2^53+1 and the sentinel, and shared signed/unsigned endpoint tests cover both TiDB and TiKV.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, sql
- Domain
- databases, distributed-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100