Странное поведение SQLite - в некоторых случаях значения NULL вычисляемого столбца - PullRequest
1 голос
/ 09 июня 2010

Я только что обнаружил очень странное поведение 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.

1 Ответ

0 голосов
/ 11 апреля 2017

(Опубликовано от имени ОП) .

Похоже, что в самой последней версии SQLite (3.6.23.1) эта ошибка уже исправлена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...