SQLite-浮点粒度打破唯一约束?

时间:2018-10-31 13:13:45

标签: sqlite floating-point

我在Windows上使用SQLite 3.25.2,从官方页面https://sqlite.org/download.html下载了最新的预编译二进制文件

执行以下代码

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);

失败,因为9223372036854775807.0是2 ^ 63,所以这些数字超出了所有整数都可以精确表示为双精度的范围。我的意思是

sqlite> select 9223372036854775807.0 = 9223372036854775807.0 - 1;
1
sqlite> select 9223372036854775807.0 = 9223372036854775807.0 - 512;
1

并且列A是唯一的,因此打印“唯一约束失败:TestReal.A”消息非常有意义。但是似乎有一个意外的解决方法

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);

运行没有任何问题。以下查询确认该表现在已插入正好4个值,但尽管有唯一约束,但仅插入了一个不同的值

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);

所以我的问题是:这是SQLite中的错误吗?还是我不正确理解“独特”的实际含义?

1 个答案:

答案 0 :(得分:0)

随着SQLite 3.29.0的发布,它已解决,这绝不是预期的行为,而是一个bug。在最新版本中,错误仍然存​​在于3.28.0中,但在3.29.0中却没有,我的两个代码片段均按预期失败。

这是包含修复程序的提交: https://www.sqlite.org/src/info/9b0915272f4d4052

我通过在3.28.0源代码上手动应用此提交并将ReactDOM.render(<LoginContainer />, document.getElementById("root")); 替换为MEM_IntReal来确认这一点。

在官方SQLite邮件列表上报告了可能的错误之后,打开了错误票证: https://www.mail-archive.com/sqlite-users@mailinglists.sqlite.org/msg115214.html

我也报告了它,实际上早一点,但是我的报告并没有引起太多关注: https://www.mail-archive.com/sqlite-users@mailinglists.sqlite.org/msg112655.html