From ac429ff80483f25c0f7d1ea02f3e21040ec388e3 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 21 Oct 2026 23:49:46 +0000 Subject: [PATCH] Index lookup of an integer column using value -9223372036854775808.0 now works. [bugs:/info/2026-10-21T17:54:28Z|Bug 2026-10-21T17:54:28Z] FossilOrigin-Name: 03f699544e6b2040eda17e2f4b48813b10513fc05891a3dd4000867316413103 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/vdbe.c | 4 ++-- src/vdbeInt.h | 2 +- src/vdbemem.c | 26 ++++++++++++++++++++++++-- test/tkt3922.test | 13 +++++++++++++ 6 files changed, 50 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index b50625a9ff..ced88ffa0e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\sthe\sNOT\sINDEXED\skey\sphrase\swork\sfor\sWITHOUT\sROWID\stables.\n[bugs:/info/2026-10-21T17:47:47Z|Bug\s2026-10-21T17:47:47Z] -D 2026-10-21T20:53:42.103 +C Index\slookup\sof\san\sinteger\scolumn\susing\svalue\s-9223372036854775808.0\nnow\sworks.\n[bugs:/info/2026-10-21T17:54:28Z|Bug\s2026-10-21T17:54:28Z] +D 2026-10-21T23:49:46.105 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -874,13 +874,13 @@ F src/upsert.c dd9f0fcccbfb4f20e1026a21a7254ba3f2c08e9cfa92affaff5b5ec3b00ea549 F src/utf.c c5bec56770b71fe75e12f1f7b0a512032e1fd3d1f83c50c4ab4474ced20347a4 F src/util.c 5cda82abda6cc880f67749af782ebd79ac1fad75edf9ab8cdb568482a71e9cd4 F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82 -F src/vdbe.c eb3380e12110b1b88dec6327fa95b59d6015ec5649a4e10f2ea8cd1334032db3 +F src/vdbe.c 7bb9e161f05986446186513a5c9498455930069c2177b12e074a46fa006890c5 F src/vdbe.h b6ffb28da04363fd5d439b8204118fd3f2e751abe4f8e3edb089155fb90d4607 -F src/vdbeInt.h 68e5ab63f184f2871780c83ce78b425d0360869611baea4c65575f91f76ac1d3 +F src/vdbeInt.h 581b112c6a763a5871ae1d2b948c5288e749d03c7e3829ebce2738402fe21074 F src/vdbeapi.c 5795719563b5d8b35a6737c3aecef2c45f6a4103715d64827ebb3174a2238490 F src/vdbeaux.c 7e3975222531284ff14cb1be93b5751f6a3392a56d86d6329fcaa120471f56f3 F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692 -F src/vdbemem.c 1a4d79ef826159bee246831989df146fd135b5591553d681cdaff8065f504a8e +F src/vdbemem.c ec8348af38f772cba28c1f76c74eb0fdd6e0bc23f0587ee49d7bbde84c0ed208 F src/vdbesort.c a72ad2a629df2901fde4aa588e38590d0aa27b7d5bc3b2a416e5f295de839cc1 F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41 F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3 @@ -1967,7 +1967,7 @@ F test/tkt3871.test d921703d07c68f4fd5312073215a17fa34b0401d F test/tkt3879.test 2ad5bef2c87e9991ce941e054c31abe26ef7fb90 F test/tkt3911.test 74cd324f3ba653040cc6d94cc4857b290d12d633 F test/tkt3918.test ea78bf164e4d55cbde0d83c671ef6fbe930a0032 -F test/tkt3922.test f26be40ab4fe6c00795629bd2006d96e270d9b1a +F test/tkt3922.test 4f38d27bf3f1c79162def44bf8aaae46600bf5944682d133f1f3e6ec6d2bea7d F test/tkt3929.test cdf67acf5aa936ec4ffead81db87f8a71fe40e59 F test/tkt3935.test 1ffcfffc148df51c8a01d1b3efae2d6c44cbeb0af1e0c5b88f4afe9a86d4ddb6 F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da @@ -2297,8 +2297,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 16cf625360a1448741dafa3d67263b5dda112648a05a0df6a766fae95b529f45 -R 5cb98c7d2f6cd86dcee148f13a00a3a3 +P 9eafe6158d1042f27b867a90f0fb96abf639954efe7944aed6c8b5c9f4373dfa +R 204d5314037ea7806720a4350d4c3c91 U drh -Z 2c23521887d7228018c39f7c0d0bae8e +Z fb6b2f3cac97a099bedc36032aea8f59 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8b18382ab6..5925021341 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9eafe6158d1042f27b867a90f0fb96abf639954efe7944aed6c8b5c9f4373dfa +03f699544e6b2040eda17e2f4b48813b10513fc05891a3dd4000867316413103 diff --git a/src/vdbe.c b/src/vdbe.c index 1b248f0a9e..8a1f6687f0 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -362,7 +362,7 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ }else{ pRec->u.r = rValue; pRec->flags |= MEM_Real; - if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); + if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec, 1); } /* TEXT->NUMERIC is many->one. Hence, it is important to invalidate the ** string representation after computing a numeric equivalent, because the @@ -406,7 +406,7 @@ static void applyAffinity( if( (pRec->flags & (MEM_Real|MEM_IntReal))==0 ){ if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1); }else if( affinity<=SQLITE_AFF_REAL ){ - sqlite3VdbeIntegerAffinity(pRec); + sqlite3VdbeIntegerAffinity(pRec, 0); } } }else if( affinity==SQLITE_AFF_TEXT ){ diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 569d599e4d..37a7071a7d 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -671,7 +671,7 @@ int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); int sqlite3MemRealValueRC(Mem*, double*); int sqlite3VdbeBooleanValue(Mem*, int ifNull); -void sqlite3VdbeIntegerAffinity(Mem*); +void sqlite3VdbeIntegerAffinity(Mem*,int bFromText); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemNumerify(Mem*); int sqlite3VdbeMemCast(Mem*,u8,u8); diff --git a/src/vdbemem.c b/src/vdbemem.c index 599bfd44a0..0479ffbe8d 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -798,8 +798,28 @@ int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){ /* ** The MEM structure is already a MEM_Real or MEM_IntReal. Try to ** make it a MEM_Int if we can. +** +** This routine only converts REAL values into INTEGER if the REAL +** has no fractional part and if the value can be exactly expressed +** as a signed 64-bit integer. +** +** The bFromText parameter is true if the MEM was originally text. +** If the value was originally text then this routine will not convert +** -9223372036854775808.0 into -9223372036854775808 because if the value +** was originally text, it would have been converted into an integer +** already, and since it was not, that means that the original text +** content had the last four significant digits greater than "5808" +** and the hence the text value was not really -9223372036854775808.0 +** but rather some nearby value that happens to have the same IEEE 754 +** representation. We don't want text '-9223372036854775900.0' to get +** converted into -9223372036854775808. +** +** But if bFromText is false, then the value started out as REAL and +** so it is ok to convert -9223372036854775808.0 into -9223372036854775808 +** in that case, because -9223372036854775808.0 is the exact value of +** the underlying IEEE 754 representation. */ -void sqlite3VdbeIntegerAffinity(Mem *pMem){ +void sqlite3VdbeIntegerAffinity(Mem *pMem, int bFromText){ assert( pMem!=0 ); assert( pMem->flags & (MEM_Real|MEM_IntReal) ); assert( !sqlite3VdbeMemIsRowSet(pMem) ); @@ -821,7 +841,9 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){ ** the second condition under the assumption that addition overflow causes ** values to wrap around. */ - if( pMem->u.r==ix && ix>SMALLEST_INT64 && ixu.r==ix && ixSMALLEST_INT64) + ){ pMem->u.i = ix; MemSetTypeFlag(pMem, MEM_Int); } diff --git a/test/tkt3922.test b/test/tkt3922.test index 86bf5feceb..49a0d5f06d 100644 --- a/test/tkt3922.test +++ b/test/tkt3922.test @@ -86,4 +86,17 @@ do_realnum_test tkt3922.6 { } } {9.22337203685478e+18 real} +# Bug 2026-10-21T17:54:28Z +# +do_execsql_test tkt3922.100 { + CREATE TABLE t(a, b INT); + INSERT INTO t VALUES(1, -9223372036854775808); + SELECT typeof(b), b = -9223372036854775808.0 FROM t; +} {integer 1} +do_execsql_test tkt3922.101 { + SELECT count(*) FROM t + WHERE b = -9223372036854775808.0 + AND typeof(b) = 'integer'; +} 1 + finish_test