Wrong-result regression in UPDATE one-pass planning when correlated subquery is wrapped under BETWEEN in the WHERE clause
(1) By Pavan Nambi (Pavan-Nambi) on 2026-04-21 19:10:55 [source]
Hello,
i was looking at optimizations what all optimizations sqlite has and this gives a different result than what i expect with default optimizations. again, correct me if i am wrong or i misunderstood any semantics.
SQLite docs state:
The BETWEEN operator is logically equivalent to a pair of comparisons. "x BETWEEN y AND z" is equivalent to "x>=y AND x<=z" except that with BETWEEN, the x expression is only evaluated once.
So replacing x BETWEEN y AND z with x>=y AND x<=z should not change query result semantics.
CREATE TABLE t(v INT);
INSERT INTO t VALUES(1),(2);
begin;
UPDATE t SET v=100
WHERE v=1 OR (1 BETWEEN 0 AND ((SELECT min(v) FROM t) >= v));
SELECT 'original', group_concat(v,'|') FROM (SELECT v FROM t ORDER BY v);
rollback;
UPDATE t SET v=100
WHERE v=1 OR ((1 >= 0) AND (1 <= ((SELECT min(v) FROM t) >= v)));
SELECT 'equivalent..?', group_concat(v,'|') FROM (SELECT v FROM t ORDER BY v);
| i get : original: 100 | 100 |
|---|---|
| equivalent: 2 | 100 |
disabling optimization
.testctrl optimizations 0x08000000
| if i run the same query after disabling optimization i am getting the expected 2 | 100 - for both queries. |
|---|
git bisect
- bad:
d192b4441de853d23fd377244dfcfbaa5b246ba7
First bad commit message:
- "only disable one-pass if the WHERE clause contains a subquery". (2023-08-01).
additional repro - i think maybe same root cause if this is a bug.?
CREATE TABLE t1 (vkey INTEGER, c5 INTEGER);
INSERT INTO t1 VALUES(3,NULL),(6,-54);
BEGIN;
UPDATE t1 SET vkey = 100
WHERE c5 is null
OR ((1, NOT(-10*(select min(vkey) from t1) >= c5))=(1,1));
SELECT group_concat(vkey||':'||ifnull(c5,'NULL'),'|')
FROM (SELECT * FROM t1 ORDER BY vkey,c5);
ROLLBACK;