]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
New sqlite3_db_config(SQLITE_DBCONFIG_FP_DIGITS) that let's the application fp-performance-v2
authordrh <>
Sat, 21 Feb 2026 19:26:58 +0000 (19:26 +0000)
committerdrh <>
Sat, 21 Feb 2026 19:26:58 +0000 (19:26 +0000)
specify the number of significant digits that double&rarr;text conversions
will attempt to preserve.

FossilOrigin-Name: 3f16985dcc47a366b54164c5024f920a79dddd76faeac5e36b4770732ed72c0a

manifest
manifest.uuid
src/main.c
src/shell.c.in
src/sqlite.h.in
src/sqliteInt.h
src/test1.c
src/vdbemem.c
test/fpconv1.test

index c3151a0aaab37af12100862356155ae3470f9ab7..2bddd7d3ad8eca5d162e84b0950e53bd568394f7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C New\stest\scases\sfor\sfloating-point\sconversions.
-D 2026-02-21T13:57:40.503
+C New\ssqlite3_db_config(SQLITE_DBCONFIG_FP_DIGITS)\sthat\slet's\sthe\sapplication\nspecify\sthe\snumber\sof\ssignificant\sdigits\sthat\sdouble&rarr;text\sconversions\nwill\sattempt\sto\spreserve.
+D 2026-02-21T19:26:58.856
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -702,7 +702,7 @@ F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
 F src/json.c 8b6341a419150b28530cc21e3951b2238c35cdc312f11b2ca29017fe4b1dedc0
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
-F src/main.c e95aa130478fc98a49181ddf094baab45f319286411129253618efe0008f0dc4
+F src/main.c 211f7721b191523b815dee6c6a1e9a5f3ebc052a0ddaaed24a75cf20bf9d4b06
 F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -739,17 +739,17 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
 F src/select.c 615d62112f5c14fb24facf9391492b42403875bfd4288db6ba10d7e6fbc22c4c
-F src/shell.c.in 15285c21cc3f1da9289b0b6c5fd0b2ca8ab2e664b4b300c404afe7634ce9876f
-F src/sqlite.h.in 8bcbaecfe2cbecf8c5c1381354fcdd7d307443e88b4953fccb222456c1267b61
+F src/shell.c.in 3e87584890a4e9797865e4771689d8d1aca3b0f824f973192784716ecfa320a2
+F src/sqlite.h.in b8a0b4dd92b1e52caa9676e39971bdaaf44eef30c4b148c9c2fa99e88ed6cf3a
 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
-F src/sqliteInt.h 347722b895995dc3015147150c1f9fed5224748c26b36d69ef405656d1603100
+F src/sqliteInt.h ffa3071dc3b9172acfe1a4edd8bc699928b0d5e02f0b8b9067676aa8e5f8f787
 F src/sqliteLimit.h 904a3f520362c7065c18165aaabd504fb13cc1b76cb411f38bd41ac219e4af1e
 F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
 F src/tclsqlite.c 85b5a20df96016e5d1d8fdc68c8a4c279c5b93e2049b77cd806c2cc50b9d8c56
 F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
-F src/test1.c 302cc00a5f0bbfa36d73b299d600c073b02ffa7f2b59fd2c81091983ccd574a8
+F src/test1.c 3e3b013f59ffcb57dce00c90d55907072d71d4e970cb0a590cb261efe11bae9c
 F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
 F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a
 F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
@@ -811,7 +811,7 @@ F src/vdbeInt.h 42488247a80cd9d300627833c6c85ace067ae5011a99e7614e2358130d62feea
 F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
 F src/vdbeaux.c 396d38a62a357b807eabae0cae441fc89d2767a57ab08026b7072bf7aa2dd00c
 F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
-F src/vdbemem.c 61b014628c6db12dd10b094b84f3e83ea0f85a1c485891bf0b5f370f3625d4ca
+F src/vdbemem.c 565c214150dbab0678bfb04db5488f1788df87aad4ec3ec71cc61e0eb3f18f38
 F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
 F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
 F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
@@ -1131,7 +1131,7 @@ F test/fordelete.test ba98f14446b310f9c9d935b97ec748753d0144a28b356ba30d1f4f6958
 F test/fork-test.c 9ac2e6423a1d38df3d6be0e8ac15608b545de21e2b19d9d876254c5931b63edb
 F test/format4.test eeae341953db8b6bda7f549044797c3278a6cc345d11ada81471671b654f8ef4
 F test/fp-speed-1.c b37de94eba034e1703668816225f54510ec60fb0685406608cc707afe6b8234d
-F test/fpconv1.test d9e1e1bdeaf22b2e800aa6847466468a930f6aea6b59eea348711f9445a043b1
+F test/fpconv1.test 63f352682fa65601a326563ad633086df6ab194e6ed5e7366786f38a525a7fd7
 F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
 F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
 F test/fts3_common.tcl dffad248f9ce090800e272017d2898005c28ee6314fc1dd5550643a02666907a
@@ -2195,8 +2195,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P 93f90eacc0c5b2ae0042ec525359298883f8473e24967208feef4029d9fa2d08
-R e68f89bae9b5fbd05cf0e0e735a13171
+P 3033fe97b14ba0531278d4aa444bc5340e044b87a72b3a4341032ddee442000f
+R 4d154d27dd2b7e6c72267982eae3c18d
 U drh
-Z 5a9c96d60317e775f664966a4b06b2ad
+Z 47c16a6580f94070b6e59ea57711afd7
 # Remove this line to create a well-formed Fossil manifest.
index f51a8bda13147e19d8e98da3d97df1fce16b9c5a..fffbbc32ca854d1ee49b5b0bec753a3be75cd6d2 100644 (file)
@@ -1 +1 @@
-3033fe97b14ba0531278d4aa444bc5340e044b87a72b3a4341032ddee442000f
+3f16985dcc47a366b54164c5024f920a79dddd76faeac5e36b4770732ed72c0a
index 37e6f237447a0cab492d665db75ab67fc9423a40..a3bfe6d137a8bf3d11f262bde4737fcb049368fc 100644 (file)
@@ -971,6 +971,14 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
       rc = setupLookaside(db, pBuf, sz, cnt);
       break;
     }
+    case SQLITE_DBCONFIG_FP_DIGITS: {
+      int nIn = va_arg(ap, int);
+      int *pOut = va_arg(ap, int*);
+      if( nIn>3 && nIn<24 ) db->nFpDigit = (u8)nIn;
+      if( pOut ) *pOut = db->nFpDigit;
+      rc = SQLITE_OK;
+      break;
+    }
     default: {
       static const struct {
         int op;      /* The opcode */
@@ -3399,6 +3407,7 @@ static int openDatabase(
   db->aDb = db->aDbStatic;
   db->lookaside.bDisable = 1;
   db->lookaside.sz = 0;
+  db->nFpDigit = 17;
 
   assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
   memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
index 05d583120124283d50cf341fc80326eba8821299..8eaa060812aeeb9dd728c5b3df7423f019cb0a28 100644 (file)
@@ -9267,6 +9267,7 @@ static int do_meta_command(const char *zLine, ShellState *p){
         { "enable_trigger",     SQLITE_DBCONFIG_ENABLE_TRIGGER        },
         { "enable_view",        SQLITE_DBCONFIG_ENABLE_VIEW           },
         { "fts3_tokenizer",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
+        { "fp_digits",          SQLITE_DBCONFIG_FP_DIGITS             },
         { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    },
         { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT    },
         { "load_extension",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
@@ -9283,11 +9284,19 @@ static int do_meta_command(const char *zLine, ShellState *p){
     for(ii=0; ii<ArraySize(aDbConfig); ii++){
       if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
       if( nArg>=3 ){
-        sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
+        if( aDbConfig[ii].op==SQLITE_DBCONFIG_FP_DIGITS ){
+          sqlite3_db_config(p->db, aDbConfig[ii].op, atoi(azArg[2]), 0);
+        }else{
+          sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
+        }
       }
       sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
-      cli_printf(p->out, "%19s %s\n",
-                      aDbConfig[ii].zName, v ? "on" : "off");
+      if( aDbConfig[ii].op==SQLITE_DBCONFIG_FP_DIGITS ){
+        cli_printf(p->out, "%19s %d\n", aDbConfig[ii].zName, v);
+      }else{
+        cli_printf(p->out, "%19s %s\n",
+                        aDbConfig[ii].zName, v ? "on" : "off");
+      }
       if( nArg>1 ) break;
     }
     if( nArg>1 && ii==ArraySize(aDbConfig) ){
index e1f478a0a9e8a2d914f7f37c8070b6387f04fd91..182f6871c8c9611a23d2bed0acd2157356bf5dcc 100644 (file)
@@ -2648,6 +2648,21 @@ struct sqlite3_mem_methods {
 ** comments are allowed in SQL text after processing the first argument.
 ** </dd>
 **
+** [[SQLITE_DBCONFIG_FP_DIGITS]]
+** <dt>SQLITE_DBCONFIG_FP_DIGITS</dt>
+** <dd>The SQLITE_DBCONFIG_FP_DIGITS option is a small integer is the number
+** of significant digits that SQLite attempts to preserve when converting
+** floating point numbers (IEEE 754 "doubles") into text.  The default value
+** (as of SQLite version 3.52.0) is 17.<p>
+** This option takes two arguments which are an integer and a pointer
+** to an integer.  The first argument is a small integer, between 3 and 20, or
+** zero.  The FP_DIGITS setting is changed to the small integer, or left
+** altered if the first argument is out of range.  The second argument is a
+** pointer to an integer.  If the pointer is not NULL, then the value of
+** the FP_DIGITS setting, after possibly being modified by the first
+** arguments, is written into the integer to which the second argument points.
+** </dd>
+**
 ** </dl>
 **
 ** [[DBCONFIG arguments]] <h3>Arguments To SQLITE_DBCONFIG Options</h3>
@@ -2692,7 +2707,8 @@ struct sqlite3_mem_methods {
 #define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE  1020 /* int int* */
 #define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE   1021 /* int int* */
 #define SQLITE_DBCONFIG_ENABLE_COMMENTS       1022 /* int int* */
-#define SQLITE_DBCONFIG_MAX                   1022 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_FP_DIGITS             1023 /* int int* */
+#define SQLITE_DBCONFIG_MAX                   1023 /* Largest DBCONFIG */
 
 /*
 ** CAPI3REF: Enable Or Disable Extended Result Codes
index 8ccb0790964e3adde0a79ec4a81cbb789b2569f4..051cb4e874467b58619850d8e778987d790abba4 100644 (file)
@@ -1692,6 +1692,7 @@ struct sqlite3 {
   u8 noSharedCache;             /* True if no shared-cache backends */
   u8 nSqlExec;                  /* Number of pending OP_SqlExec opcodes */
   u8 eOpenState;                /* Current condition of the connection */
+  u8 nFpDigit;                  /* Significant digits to keep on double->text */
   int nextPagesize;             /* Pagesize after VACUUM if >0 */
   i64 nChange;                  /* Value returned by sqlite3_changes() */
   i64 nTotalChange;             /* Value returned by sqlite3_total_changes() */
index 230034fa011eb21acfa259a7dc2fa082d9dcc922..3ca5c837a7975faff73f2f2f943cf88dda6998e8 100644 (file)
@@ -8644,6 +8644,7 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
     { "ATTACH_CREATE",      SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE },
     { "ATTACH_WRITE",       SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE },
     { "COMMENTS",           SQLITE_DBCONFIG_ENABLE_COMMENTS },
+    { "FP_DIGITS",          SQLITE_DBCONFIG_FP_DIGITS },
   };
   int i;
   int v = 0;
index 48e10146638a28e6f780301e53c9dd63861a4497..9e654858d3639835cc57252f77ecb16be71611aa 100644 (file)
@@ -107,10 +107,11 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
   StrAccum acc;
   assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) );
   assert( sz>22 );
 if( p->flags & MEM_Int ){
-#if GCC_VERSION>=7000000
if( p->flags & (MEM_Int|MEM_IntReal) ){
+#if 
     /* Work-around for GCC bug
-    ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */
+    ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270.
+    ** Bug fixed circa 2020, so this work-around removed in 2026. */
     i64 x;
     assert( (p->flags&MEM_Int)*2==sizeof(x) );
     memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2);
@@ -118,10 +119,14 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
 #else
     p->n = sqlite3Int64ToText(p->u.i, zBuf);
 #endif
+    if( p->flags & MEM_IntReal ){
+      memcpy(zBuf+p->n,".0", 3);
+      p->n += 2;
+    }
   }else{
     sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0);
-    sqlite3_str_appendf(&acc, "%!.17g", 
-         (p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r);
+    sqlite3_str_appendf(&acc, "%!.*g",
+         (p->db ? p->db->nFpDigit : 17), p->u.r);
     assert( acc.zText==zBuf && acc.mxAlloc<=0 );
     zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */
     p->n = acc.nChar;
index 597e065e8b2fb7dc1e3e92cf9938505a31962569..a93489907ee9350f13bd88f42d8d3dd6855e4d29 100644 (file)
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
 
+
+# Unusual rendering cases:
+#
+do_execsql_test fpconv1-1.0 {
+  SELECT 1.23 - 2.34;
+} {-1.1099999999999999}
+#  ^---  Not -1.11 as you would expect.  -1.11 has a different bit pattern
+
+do_execsql_test fpconv1-1.1 {
+  SELECT 1.23 * 2.34;
+} {2.8781999999999996}
+#  ^---  Not 2.8782 as you would expect.  2.8782 has a different bit pattern
+
+# Change significant digits to 15 and get a different result.
+sqlite3_db_config db FP_DIGITS 15
+do_execsql_test fpconv1-1.2 {
+  SELECT 1.23 - 2.34;
+} {-1.11}
+do_execsql_test fpconv1-1.3 {
+  SELECT 1.23 * 2.34;
+} {2.8782}
+sqlite3_db_config db FP_DIGITS 17
+
+
 if {[catch {load_static_extension db decimal} error]} {
   puts "Skipping decimal tests, hit load error: $error"
   finish_test; return
 }
 
 sqlite3_create_function db
-do_execsql_test fpconv1-1.0 {
+do_execsql_test fpconv1-2.0 {
   WITH RECURSIVE
        /* Number of random floating-point values to try.
        ** On a circa 2021 Ryzen 5950X running Mint Linux, and
@@ -49,7 +73,7 @@ do_execsql_test fpconv1-1.0 {
 
 load_static_extension db ieee754
 
-do_execsql_test fpconv1-2.0 {
+do_execsql_test fpconv1-3.0 {
   WITH RECURSIVE
     c(x,s) AS MATERIALIZED (VALUES(1,random()&0xffefffffffffffff)
                UNION ALL
@@ -71,16 +95,4 @@ do_execsql_test fpconv1-2.0 {
 } {}
 #  ^---- Values that fail to round-trip will be reported
 
-# Unusual rendering cases:
-#
-do_execsql_test fpconv1-3.0 {
-  SELECT 1.23 - 2.34;
-} {-1.1099999999999999}
-#  ^---  Not -1.11 as you would expect.  -1.11 has a different bit pattern
-
-do_execsql_test fpconv1-3.1 {
-  SELECT 1.23 * 2.34;
-} {2.8781999999999996}
-#  ^---  Not 2.8782 as you would expect.  2.8782 has a different bit pattern
-
 finish_test