Я только что обнаружил очень странное поведение SQLite. Я надеюсь, что что-то здесь упущено, и это не ошибка в реализации.
Проблема в том, что:
a) если запрос включает в себя вычисляемый столбец, который принимает в качестве входных данных другой реальный столбец, И
b) вычисляемый столбец используется в предложении where И
в) реальный столбец индексируется
... иногда это приводит к тому, что возвращаемое значение вычисляемого столбца равно NULL, а не тому значению, которое оно должно иметь.
Вот пример SQL для воспроизведения и иллюстрации проблемы:
CREATE TABLE records (
record_id INTEGER PRIMARY KEY,
record_type INTEGER
);
CREATE INDEX records_record_type_index ON records (record_type);
INSERT INTO records (record_id, record_type) VALUES (101, 0);
INSERT INTO records (record_id, record_type) VALUES (102, 1);
INSERT INTO records (record_id, record_type) VALUES (103, 0);
INSERT INTO records (record_id, record_type) VALUES (104, 1);
INSERT INTO records (record_id, record_type) VALUES (105, 0);
.headers on
-- 1st select
SELECT * FROM records;
-- 2nd select
SELECT record_id, record_type, (record_type * 5) AS zzzA FROM records WHERE ((record_id > 0) OR ((record_type = 2) AND (1 == zzzA)));
-- 3rd select
SELECT record_id, record_type, (record_type * 5) AS zzzB FROM records WHERE ((record_id > 0) OR ((+record_type = 2) AND (1 == zzzB)));
-- 4th select
SELECT record_id, record_type, (record_type * 5) AS zzzA FROM records WHERE ((record_id > 0) OR ((record_type = 2) AND (1 == zzzA)));
DROP INDEX records_record_type_index;
-- 5th select
SELECT record_id, record_type, (record_type * 5) AS zzzC FROM records WHERE ((record_id > 0) OR ((record_type = 2) AND (1 == zzzC)));
CREATE INDEX records_record_type_index ON records (record_type);
-- 6th select
SELECT record_id, record_type, (record_type * 5) AS zzzA FROM records WHERE ((record_id > 0) OR ((record_type = 2) AND (1 == zzzA)));
INSERT INTO records (record_id, record_type) VALUES (106, 2);
-- 7th select
SELECT record_id, record_type, (record_type * 5) AS zzzD FROM records WHERE ((record_id > 0) OR ((record_type = 2) AND (1 == zzzD)));
И вывод:
record_id|record_type
101|0
102|1
103|0
104|1
105|0
record_id|record_type|zzzA
101|0|
102|1|
103|0|
104|1|
105|0|
record_id|record_type|zzzB
101|0|0
102|1|5
103|0|0
104|1|5
105|0|0
record_id|record_type|zzzA
101|0|
102|1|
103|0|
104|1|
105|0|
record_id|record_type|zzzC
101|0|0
102|1|5
103|0|0
104|1|5
105|0|0
record_id|record_type|zzzA
101|0|
102|1|
103|0|
104|1|
105|0|
record_id|record_type|zzzD
101|0|10
102|1|10
103|0|10
104|1|10
105|0|10
106|2|10
Как видите,
a) при втором выборе вычисленные значения столбца zzzA равны NULL;
б) если индекс record_type явно запрещен (3-й выбор) или отброшен (5-й выбор), все работает как положено;
c) если мы добавим запись со значением record_type, для которой проверяется одна из частей предложения where, все снова работает (выбор 7-й).
Это происходит с SQLite 3.6.12.