I have a table, a partial index and a query, which (somewhat simplified)
are:
create table Objs (Seqnum int primary key, Status, Timeout int) without
rowid;
create index DIndex on Objs (Seqnum) where Status == 0;
select Seqnum from Objs where Status == 0 and strftime('%s','now') >=
Timeout order by Seqnum limit ?1;
The Objs table will generally have many objects with Status <> 0, and only a
handful with Status == 0, so the intention is for the select statement to
use DIndex to rapidly find the Objs with Status == 0.
By default, this does not work. It does however work correctly if I enable
SQLITE_ENABLE_STAT4, populate Objs with typical data, and then run Analyze.
After this process, EXPLAIN QUERY PLAN shows:
SEARCH TABLE Objs USING INDEX DIndex (Seqnum=?)
However, if there are zero Objs in the table with Status == 0, then this
process fails with EXPLAIN QUERY PLAN showing:
SEARCH TABLE Objs USING PRIMARY KEY (Seqnum=?)
That is the bug. If there are a small number of Objs in the table with
Status == 0, then the select uses DIndex, which is the correct behavior. In
the limit, with zero Objs in the table with Status == 0, the select should
still use DIndex, but instead, it reverts to a full table scan. The query
optimizer should be able to figure out that zero Objs with Status == 0 is
roughly the same as one Objs with Status == 0, and handle them the same.
I tested this under sqlite-amalgamation-3081002 and
sqlite-amalgamation-3081101 and simply populated Objs with 20 rows, with
either zero or one of these rows having Status == 0, and the remainder
having Status == 1.
Please cc me directly on any replies.