polardb / polardb/polardbx-sql

BITMAP Index Scan Returns Wrong Results for FLOAT Column with BETWEEN Operator

Open
#294 0 comments 0 reactions 0 assignees View on GitHub

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 NULL via FORCE INDEX → 5 ✔
  • c2 <= 3.4028235E38 OR c2 IS NULL via FORCE INDEX → 5 ✔
  • c2 >= 0 AND c2 <= 3.4028235E38 via FORCE INDEX → 4 ✔ (AND excludes NULL)
  • c2 BETWEEN 0 AND 3.4028235E38 via 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.