polardb / polardb/polardbx-sql
BITMAP Index Scan Returns Wrong Results for FLOAT Column with BETWEEN Operator
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 1.7k
- Forks
- 337
- PR merge metrics
- No merged PRs in 30d
Description
1. Minimal reproduce step
DROP DATABASE IF EXISTS bug_repro;
CREATE DATABASE bug_repro;
USE bug_repro;
CREATE TABLE t (c0 INT, c2 FLOAT) ENGINE=InnoDB;
INSERT INTO t VALUES (1, 3.0E38), (2, 3.4028235E38), (3, 1.5), (4, NULL), (5, 2.0E38);
CREATE INDEX idx_c2 ON t (c2);
ANALYZE TABLE t;
-- [CORRECT] Full table scan (IGNORE INDEX)
SELECT '[CORRECT]' AS plan, COUNT(*) FROM t IGNORE INDEX(idx_c2)
WHERE c2 BETWEEN 0 AND 3.4028235E38 OR c2 IS NULL;
-- [BUG] Index scan (FORCE INDEX)
SELECT '[BUG] ' AS plan, COUNT(*) FROM t FORCE INDEX(idx_c2)
WHERE c2 BETWEEN 0 AND 3.4028235E38 OR c2 IS NULL;
2. What did you expect to see?
Both queries should return 5, since all 5 rows satisfy the condition (c2 BETWEEN 0 AND 3.4028235E38 OR c2 IS NULL):
plan COUNT(*)
[CORRECT] 5
[BUG] 5
3. What did you see instead (Required)
The FORCE INDEX query returns only 1 (only the NULL row), losing all 4 non-NULL FLOAT rows:
plan COUNT(*)
[CORRECT] 5
[BUG] 1
Further diagnosis:
Breaking down the BETWEEN into its logical equivalent c2 >= 0 AND c2 <= 3.4028235E38 via FORCE INDEX returns the correct result (4 rows, NULL excluded by AND semantics):
-- [OK] Equivalent AND condition via FORCE INDEX — correct
SELECT COUNT(*) FROM t FORCE INDEX(idx_c2)
WHERE c2 >= 0 AND c2 <= 3.4028235E38 OR c2 IS NULL;
-- Returns: 5
This confirms the bug is specific to the SQL BETWEEN operator when used via index scan on FLOAT columns. The >= AND <= equivalent works correctly, but BETWEEN does not.
Additional verification:
c2 >= 0 OR c2 IS NULLvia FORCE INDEX → 5 ✔c2 <= 3.4028235E38 OR c2 IS NULLvia FORCE INDEX → 5 ✔c2 >= 0 AND c2 <= 3.4028235E38via FORCE INDEX → 4 ✔ (AND excludes NULL)c2 BETWEEN 0 AND 3.4028235E38via FORCE INDEX → 0 !!!WRONG
The BETWEEN operator on FLOAT columns is incorrectly transformed into a range scan condition by the BITMAP index access path, causing the upper bound to be lost. INT columns are not affected.
4. What is your PolarDB-X version?
VERSION(): 5.6.29-PXC-5.4.19-20250825
Docker image: polardbx/polardb-x:v2.4.2_5.4.19
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the supplied SQL reproduction against the stated PolarDB-X version, comparing the full-table and FORCE INDEX plans. Trace the BITMAP index access path for FLOAT BETWEEN predicates and add a regression test covering the upper bound and NULL condition. Done means both queries return 5 and the standalone BETWEEN returns 4 non-NULL rows.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- sql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100