From 0a5f27711ffd520fbc733688f050f3c04f3b9d9b Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 4 Aug 2026 20:40:10 +0000 Subject: [PATCH] The sorter enhancement at [bdc841de10fef65b] contains a bug where it might sort 64-bit integers in the wrong order due to the limited precision of double. Fixed here. FossilOrigin-Name: 6bdfff7ddb63d0b4f28f6c174a36e81486a652056a4e21644378a22feda780fd --- manifest | 15 +++++++-------- manifest.uuid | 2 +- src/vdbesort.c | 19 +++++++++++++------ test/sort.test | 17 +++++++++++++++++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index abab43af18..6155b6a5ce 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sperformance\sin\sthe\ssorter\sby\sadding\sa\sspecial\scase\scomparison\nfunction\sfor\swhen\sthe\ssorting\sby\sfloating-point\snumbers. -D 2026-08-04T14:55:51.598 +C The\ssorter\senhancement\sat\s[bdc841de10fef65b]\scontains\sa\sbug\swhere\sit\nmight\ssort\s64-bit\sintegers\sin\sthe\swrong\sorder\sdue\sto\sthe\slimited\nprecision\sof\sdouble.\s\sFixed\shere. +D 2026-08-04T20:40:10.440 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -816,7 +816,7 @@ F src/vdbeapi.c 6ad0c841b6cb87de068f71787f385149d794e8830176bf72d09a36b9f655ac5b F src/vdbeaux.c a052c43fcf342651f655e6771003c175d49b237a9473c3c4d79d44725f494dae F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692 F src/vdbemem.c 6e7ad67507c9a8e625b46256a9c003929331d6a27b99bbe139b8f0dab636e1f2 -F src/vdbesort.c 82e4f8eab771f14d95a057c0df11c4d401b09d0c5030bfd2a5f2d29dde8441d3 +F src/vdbesort.c 2cb0f80f1ab96a905412c6e0394f67a33ef2dc498dced80e66f065b2569788f2 F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41 F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3 F src/vtab.c 1fa9e01d3da114a634a6ba1f36de8a3af6381b675cbbca399f0de64934e50ac6 @@ -1668,7 +1668,7 @@ F test/snapshot_fault.test 129234ceb9b26a0e1000e8563a16e790f5c1412354e70749cbd78 F test/snapshot_up.test 77dc7853bfb2b4fa249f76e1714cfa1e596826165d9ef22c06ac3a0b7b778d9a F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 -F test/sort.test f86751134159abb5e5fd4381a0d7038c91013638cd1e3fa1d7850901f6df6196 +F test/sort.test 7867829c576567641cefb8a3f8cfec2d56b38419d7b8241ab8e2d96414fc345d F test/sort2.test 2f8c66402a03adebe77ce7aafca129fbf32df27d6c9b8f7a9f1b958e39f56da8 F test/sort3.test 1480ed7c4c157682542224e05e3b75faf4a149e5 F test/sort4.test c7a88629aecc8eec3c919eda54b221da5cf7a1b48f0cd372e7e832188d6737d8 @@ -2218,9 +2218,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 7f380be91b75307bd7b57415cb53ca5c01894ff921f2ad23736a8faaff25b907 6cda98ee3c8fcd996fd8986269e0a046f41fc9cee19345e32c055435e1874c67 -R 28ad06f5d2b9260b88513523cb3d391f -T +closed 6cda98ee3c8fcd996fd8986269e0a046f41fc9cee19345e32c055435e1874c67 +P bdc841de10fef65b627deb8b770702c976174a66af847c96ebecf24d91798744 +R 0db8bad880544fadd75c136d6d89db37 U drh -Z 6c61579999b8b222e0db321fea2ac179 +Z c0254d132a18aeae6d54aba80ce46af2 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 0fe2f6494d..fd3459d4bf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bdc841de10fef65b627deb8b770702c976174a66af847c96ebecf24d91798744 +6bdfff7ddb63d0b4f28f6c174a36e81486a652056a4e21644378a22feda780fd diff --git a/src/vdbesort.c b/src/vdbesort.c index 984e44659e..8a565a3827 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -1035,10 +1035,17 @@ static SQLITE_NOINLINE int vdbeSorterCompareRealInt( ){ const u8 * const p1 = (const u8 * const)pKey1; const u8 * const p2 = (const u8 * const)pKey2; - double r1 = vdbeSorterGetReal(p1); - double r2 = vdbeSorterGetReal(p2); - return vdbeSorterFinishRealCompare(pTask,pbKey2Cached, - pKey1,nKey1,pKey2,nKey2,r1,r2); + if( p1[1]==6 || p2[1]==6 ){ + /* 64-bit integer values cannot be represented exactly by a double so + ** must be handled by the generalized comparison function. */ + return vdbeSorterCompare(pTask, + pbKey2Cached, pKey1,nKey1, pKey2,nKey2); + }else{ + double r1 = vdbeSorterGetReal(p1); + double r2 = vdbeSorterGetReal(p2); + return vdbeSorterFinishRealCompare(pTask,pbKey2Cached, + pKey1,nKey1,pKey2,nKey2,r1,r2); + } } /* @@ -1066,8 +1073,8 @@ static int vdbeSorterCompareReal( assert( p2[1]>0 && p2[1]<10 ); /* first field guaranteed numeric */ if( p1[1]!=7 || p2[1]!=7 ){ - /* One or both floating point values are stored as INTEGER (MEM_RealInt). - ** Handle this case separately for efficiency */ + /* One or both floating point values are stored as INTEGER. This might + ** be because of the MEM_RealInt encoding. Try to optimize that case. */ return vdbeSorterCompareRealInt(pTask, pbKey2Cached, pKey1,nKey1, pKey2,nKey2 ); diff --git a/test/sort.test b/test/sort.test index e6da6c6baf..49c49ca9ae 100644 --- a/test/sort.test +++ b/test/sort.test @@ -627,4 +627,21 @@ do_execsql_test 18.2 { } {/.*SCAN t2.*SEARCH t1.*/} # ^^^^^^^--^^^^^^^^^--- t2 should be the outer loop. +# 2026-08-04 The vdbeSorterCompareReal() enhancement. Bug in the +# initial implementation (2026-08-04T14:55:51.598Z) by jeffchen. +# +reset_db +do_execsql_test 19.1 { + CREATE TABLE t(x); + INSERT INTO t VALUES(9007199254740993),(9007199254740992.0),(0.5); + SELECT typeof(x), quote(x) FROM t ORDER BY x; + CREATE INDEX i ON t(x); +} {real 0.5 real 9007199254740992.0 integer 9007199254740993} +do_execsql_test 19.2 { + PRAGMA integrity_check; +} ok +do_execsql_test 19.3 { + SELECT typeof(x) FROM t WHERE x=9007199254740992.0; +} real + finish_test