SQLite Forum

Possible Bug in 3.38.1
Login

Possible Bug in 3.38.1

(1) By Dieter Schmeer (dschmeer) on 2022-03-24 22:57:17 [source]

I think I found a bug in 3.38.1 that was not present in 3.37.2, maybe caused by the Bloom filter.

I simplified the problem to these two tables:

CREATE TABLE VersicherungenXX_tb
(
    Versicherungsnummer INTEGER PRIMARY KEY NOT NULL,
    Adressnummer INT
);

CREATE TABLE AdressenXX_tb
(
    Adressnummer INTEGER PRIMARY KEY NOT NULL,
    Geburtsdatum DATE
);

In my case, there is an Adressnummer in AdressenXX_tb for every Adressnummer in VersicherungenXX_tb, and Geburtsdatum is always '1900-01-01' and never NULL.

So the following statement should return an empty result set:

SELECT ve.Versicherungsnummer 
FROM VersicherungenXX_tb AS ve 
LEFT JOIN AdressenXX_tb AS ad ON ad.Adressnummer=ve.Adressnummer 
WHERE ad.Geburtsdatum IS NULL 
ORDER BY ve.Versicherungsnummer;

In 3.37.2, it actually returns an empty set, but in 3.38.1, it returns all rows of VersicherungenXX_tb.

Unfortunately, this is only the case if there are many rows in the tables, so I prepared a database that has the necessary entries:

https://www.pirmasoft.de/bugtest.zip

Can anybody please have a look at this and confirm if this is a bug?

Thanks a lot

Dieter Schmeer

(2) By Richard Hipp (drh) on 2022-03-24 23:37:34 in reply to 1 [link] [source]

Confirmed. The following is a simplified test case:

CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
CREATE TABLE t2(c INTEGER PRIMARY KEY, d INT);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b) SELECT x, 1000*x FROM c;
INSERT INTO t2(c,d) SELECT b*2, 1000000*a FROM t1;
ANALYZE;
DELETE FROM sqlite_stat1;
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES
  ('t1',NULL,150105),('t2',NULL,98747);
ANALYZE sqlite_schema;
.eqp on
SELECT count(*) FROM t1 LEFT JOIN t2 ON c=b WHERE c IS NULL;
SELECT count(*) FROM t1 LEFT JOIN t2 ON +c=+b WHERE +c IS NULL;
.testctrl optimizations 0x80000
SELECT count(*) FROM t1 LEFT JOIN t2 ON c=b WHERE c IS NULL;

Copy/paste the above into the CLI and see that the first query gets the wrong answer whereas the second and third get the correct answer. The ".eqp on" line turns on automatic EXPLAIN QUERY PLAN, which shows that the first query is using the new Bloom filter optimization. The ".testctrl" line turns off the Bloom filter optimization and consequently gets the correct answer. The second query gets the correct answer because the extra "+" operators disable the use of indexes.

(3) By Richard Hipp (drh) on 2022-03-25 00:04:46 in reply to 2 [link] [source]

The problem appears to be that the "c IS NULL" expression in the WHERE clause is being used to restrict the entries in the Bloom filter. But that is not correct. Because the Bloom filter is for the right-hand table of a LEFT JOIN, only expressions in the ON clause can be used to restrict the Bloom filter.

The expression "c IS NULL" is always false. So the Bloom filter is empty. The algorithm uses the Bloom filter to help evaluate "c=b" and because the Bloom filter is empty, it thinks that "c=b" is always false, which is incorrect. Because the algorithm thinks that "c=b" is always false, it always substitutes the value "(NULL,NULL)" for the right-hand table. That value for the right-hand table satisfies the WHERE clause, and so every row in the left-hand table is output.

(4.1) By Richard Hipp (drh) on 2022-03-25 11:04:14 edited from 4.0 in reply to 1 [link] [source]

Thanks for the bug report. Please try the fix at check-in 1a6328f2a5b49730 and confirm that it fixes your problem.

(5) By Dieter Schmeer (dschmeer) on 2022-03-25 16:16:39 in reply to 4.1 [link] [source]

Thanks for the fix. I tested it with our original problem and I can confirm that it works.