Reputation: 1715
I'm using SQLite 3.25.2 on Windows, downloaded the latest precompiled binaries from the official page https://sqlite.org/download.html
Executing the following code
DROP TABLE IF EXISTS TestReal;
CREATE TABLE TestReal(A REAL UNIQUE);
INSERT INTO TestReal values (9223372036854775807.0);
INSERT INTO TestReal values (9223372036854775807.0 - 1);
INSERT INTO TestReal values (9223372036854775807.0 - 2);
INSERT INTO TestReal values (9223372036854775807.0 - 3);
fails as expected, since 9223372036854775807.0 is 2^63, these numbers are way out of the range where all integers are exactly representable as doubles. I mean
sqlite> select 9223372036854775807.0 = 9223372036854775807.0 - 1;
1
sqlite> select 9223372036854775807.0 = 9223372036854775807.0 - 512;
1
And column A is unique, so it makes perfect sense to print a 'UNIQUE constraint failed: TestReal.A' message. But there seems to be an unintended workaround
DROP TABLE IF EXISTS TestReal;
CREATE TABLE TestReal(A REAL UNIQUE);
INSERT INTO TestReal values (9223372036854775807);
INSERT INTO TestReal values (9223372036854775807 - 1);
INSERT INTO TestReal values (9223372036854775807 - 2);
INSERT INTO TestReal values (9223372036854775807 - 3);
runs without any problems. The following queries confirm that the table now has exactly 4 values inserted, but only one distinct value, despite of having a unique constraint
sqlite> SELECT * FROM TestReal;
9.22337203685478e+18
9.22337203685478e+18
9.22337203685478e+18
9.22337203685478e+18
sqlite> SELECT DISTINCT(A) FROM TestReal;
9.22337203685478e+18
sqlite> .schema
CREATE TABLE TestReal(A REAL UNIQUE);
So my question is: is this a bug in SQLite? Or do I not understand correctly what 'unique' actually means?
Upvotes: 3
Views: 109
Reputation: 1715
With the release of SQLite 3.29.0 it's settled, this was never the intended behavior, but a bug. The error is still present in 3.28.0, but not in 3.29.0, in the newest versions both of my code snippets fail as expected.
This is the commit containing the fix: https://www.sqlite.org/src/info/9b0915272f4d4052
I confirmed it by manually applying this commit on 3.28.0 source code, and replacing MEM_IntReal
with (MEM_Int | MEM_Real)
.
The error ticket was opened after the possible error was reported here on the official SQLite mailing list: https://www.mail-archive.com/[email protected]/msg115214.html
I also reported it, in fact a bit earlier but my report didn't garner that much attention: https://www.mail-archive.com/[email protected]/msg112655.html
Upvotes: 1