From 08d072806c37ffa750770ec7a811aab7b763ff16 Mon Sep 17 00:00:00 2001 From: konradh <49533343+konradh@users.noreply.github.com> Date: Sun, 5 Nov 2023 16:03:18 +0100 Subject: [PATCH] fix(sqlite): improve floating-point precision This adds support for values of type double when binding values to a query. Prior to this, doubles would be converted to a string and only be stored with 6 digits of precision in the database. Additionally, floats stored in the database were converted to strings when retrieved and therefore be reduced to 6 digits of precision, too. --- sqlite.d | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sqlite.d b/sqlite.d index 44c6ba4..191ee3f 100644 --- a/sqlite.d +++ b/sqlite.d @@ -237,6 +237,9 @@ class SqliteResult : ResultSet { foreach(c; rows[position]) { if(auto t = c.peek!(immutable(byte)[])) r.row ~= DatabaseDatum(cast(string) *t); + else if (auto d = c.peek!double) + // 17 significant decimal digits are enough to not lose precision (IEEE 754 section 5.12.2) + r.row ~= DatabaseDatum(format!"%.17s"(*d)); else r.row ~= DatabaseDatum(c.coerce!(string)); } @@ -508,6 +511,7 @@ template extract(A, T, R...){ void bind (const char[] name, const char[] value){ bind(bindNameLookUp(name), value); } void bind (const char[] name, int value){ bind(bindNameLookUp(name), value); } void bind (const char[] name, float value){ bind(bindNameLookUp(name), value); } + void bind (const char[] name, double value){ bind(bindNameLookUp(name), value); } void bind (const char[] name, const byte[] value){ bind(bindNameLookUp(name), value); } void bind (const char[] name, const ubyte[] value){ bind(bindNameLookUp(name), value); } @@ -525,6 +529,11 @@ template extract(A, T, R...){ throw new DatabaseException("bind " ~ db.error()); } + void bind(int col, double value){ + if(sqlite3_bind_double(s, col, value) != SQLITE_OK) + throw new DatabaseException("bind " ~ db.error()); + } + void bind(int col, int value){ if(sqlite3_bind_int(s, col, value) != SQLITE_OK) throw new DatabaseException("bind " ~ db.error()); @@ -572,6 +581,8 @@ template extract(A, T, R...){ bind(col, v.get!string); else if(v.peek!float) bind(col, v.get!float); + else if(v.peek!double) + bind(col, v.get!double); else if(v.peek!(byte[])) bind(col, v.get!(byte[])); else if(v.peek!(ubyte[]))