Wrong Result: Inconsistent evaluation of EXISTS and Bitwise NOT when moved from WHERE clause to a Derived Table projection.
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Bug Report
There is a logic discrepancy in TiDB where a query returns 1 row when filters are applied directly in the WHERE clause, but returns 0 rows when the same filters are projected as columns in a Derived Table and filtered in the outer query. This indicates a failure in TiDB's semantic transparency and boolean evaluation in subqueries.
Please answer these questions before submitting your issue. Thanks!
### 1. Minimal reproduce step (Required)
```sql
CREATE TABLE t0(c0 FLOAT);
CREATE VIEW v0(c0, c1, c2) AS SELECT 0, NULL, ((BIT_LENGTH((BINARY (t0.c0))))|(BIN(-2007190167))) FROM t0;
INSERT INTO t0 VALUES (0.8268);
SELECT v0.c2 FROM v0 WHERE (EXISTS (SELECT 1 WHERE true)) AND ((~ ((CASE v0.c2 WHEN ((v0.c1)NOT REGEXP(v0.c2)) THEN v0.c1 ELSE v0.c2 END ))));-- cardinality: 1
SELECT ref0 FROM (SELECT v0.c2 AS ref0, EXISTS (SELECT 1 WHERE true) AS ref1, (~ ((CASE v0.c2 WHEN ((v0.c1)NOT REGEXP(v0.c2)) THEN v0.c1 ELSE v0.c2 END ))) AS ref2 FROM v0) AS s WHERE ref1 AND ref2;-- cardinality: 0
```
### 2. What did you expect to see? (Required)
**In MySQL:**
```sql
mysql> SELECT v0.c2 FROM v0 WHERE (EXISTS (SELECT 1 WHERE true)) AND ((~ ((CASE v0.c2 WHEN ((v0.c1)NOT REGEXP(v0.c2)) THEN v0.c1 ELSE v0.c2 END ))));-- cardinality: 1
+---------------------+
| c2 |
+---------------------+
| 9223372036854775807 |
+---------------------+
1 row in set (0.00 sec)
mysql> SELECT ref0 FROM (SELECT v0.c2 AS ref0, EXISTS (SELECT 1 WHERE true) AS ref1, (~ ((CASE v0.c2 WHEN ((v0.c1)NOT REGEXP(v0.c2)) THEN v0.c1 ELSE v0.c2 END ))) AS ref2 FROM v0) AS s WHERE ref1 AND ref2;-- cardinality: 0
+---------------------+
| ref0 |
+---------------------+
| 9223372036854775807 |
+---------------------+
1 row in set (0.00 sec)
```
### 3. What did you see instead (Required)
```sql
mysql> SELECT v0.c2 FROM v0 WHERE (EXISTS (SELECT 1 WHERE true)) AND ((~ ((CASE v0.c2 WHEN ((v0.c1)NOT REGEXP(v0.c2)) THEN v0.c1 ELSE v0.c2 END ))));-- cardinality: 1
+----------------------+
| c2 |
+----------------------+
| 18446744073709551615 |
+----------------------+
1 row in set, 2 warnings (0.00 sec)
mysql> SELECT ref0 FROM (SELECT v0.c2 AS ref0, EXISTS (SELECT 1 WHERE true) AS ref1, (~ ((CASE v0.c2 WHEN ((v0.c1)NOT REGEXP(v0.c2)) THEN v0.c1 ELSE v0.c2 END ))) AS ref2 FROM v0) AS s WHERE ref1 AND ref2;-- cardinality: 0
Empty set, 1 warning (0.00 sec)
```
### 4. What is your TiDB version? (Required)
```sql
mysql> select tidb_version();
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tidb_version() |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Release Version: v8.5.5
Edition: Community
Git Commit Hash: 1fa258b833ff113883beeba40bc130be7ce66610
Git Branch: HEAD
UTC Build Time: 2026-01-14 22:20:57
GoVersion: go1.25.5
Race Enabled: false
Check Table Before Drop: false
Store: unistore |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
```
Contributor guide
Assessment
This issue has not been assessed yet.