From 1934b305cdaff769d5910dc0721afc1d73f7fb99 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 24 Aug 2026 14:22:19 +0000 Subject: [PATCH] Ensure that when a large integer value (too large to be losslessly converted to double) is specified as a default value for a column with REAL affinity, the real version of the value is stored in indexes. Report [bugs:/info/2026-08-23T15:39:59Z | 2026-08-23T15:39:59Z]. FossilOrigin-Name: c494b123f52506ab57edd3f4c317b882b270e13bd5798b6c8fbdf5eebbd4ed63 --- manifest | 19 +++++++----- manifest.tags | 4 +-- manifest.uuid | 2 +- src/vdbemem.c | 25 +++++++++++++++- test/default.test | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 2a68859469..2119494c7c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sa\sharmless\sunused\svariadic\sargument\sin\ssqlite3_rsync.\sBug\sreport\s[bugs:bc49306e10e92b10|2026-08-24T01:22:51Z]. -D 2026-08-24T09:56:51.804 +C Ensure\sthat\swhen\sa\slarge\sinteger\svalue\s(too\slarge\sto\sbe\slosslessly\sconverted\sto\sdouble)\sis\sspecified\sas\sa\sdefault\svalue\sfor\sa\scolumn\swith\sREAL\saffinity,\sthe\sreal\sversion\sof\sthe\svalue\sis\sstored\sin\sindexes.\sReport\s[bugs:/info/2026-08-23T15:39:59Z\s|\s2026-08-23T15:39:59Z]. +D 2026-08-24T14:22:19.182 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/vdbeInt.h 68e5ab63f184f2871780c83ce78b425d0360869611baea4c65575f91f76ac1d3 F src/vdbeapi.c 5f5f86d4642ce1927b4b45a6b87a978ef6b11c8420e6ce440695177618fc25d0 F src/vdbeaux.c 2d4a69dade72db5844e21894b718aae38102c5545483efde3cc90a1ef9abffff F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692 -F src/vdbemem.c 025fcbeebd9a285afbed4bd3c751248c25da3a0515e0e76c9957d5d2a4226ff8 +F src/vdbemem.c 77f40b2cac350c61e1b5b83d81fc2dc0ecc4d83deea248b9151d70d60e04e442 F src/vdbesort.c a72ad2a629df2901fde4aa588e38590d0aa27b7d5bc3b2a416e5f295de839cc1 F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41 F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3 @@ -1060,7 +1060,7 @@ F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e3 F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759 F test/dbstatus2.test a36518c0f0951d8fd5a3dc36f99948ad1af93fb7fc0d2e03e5bb5a643186cf52 F test/decimal.test f1975a3fbfeb9e00c7b2024ba2282a9868e09ecba94c88dcae2aac07ae29967b -F test/default.test c7124864cded213a3f118bc7e2e26f34b7c36dfa26cf6945cc8b7f5db1191277 +F test/default.test a3f5363b334c655fcdfffe661cd01590d6c9542d2aabeac87e6e2b0612117688 F test/delete.test 2686e1c98d552ef37d79ad55b17b93fe96fad9737786917ce3839767f734c48f F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab @@ -2219,8 +2219,11 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 383e42bc1096d6fe6a2a0a147da90a1bb0bfb37c78a3288bbacaaf9bf7ac17c4 -R 7145b82991fdf84d5fa6af82d6d9e2af -U stephan -Z 8d604996da456d722c9a45ee7ec45aeb +P 5231ac428da4486d64e473e98aa72da5ca68848fba97845dbcf51fd2314debbf +R dd7d6e8ce333af6dae079f3eda3fbd47 +T *branch * bigint-defaults +T *sym-bigint-defaults * +T -sym-trunk * +U dan +Z 0889cec66487e17c64837c5879dab6d0 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.tags b/manifest.tags index bec971799f..72f3edf630 100644 --- a/manifest.tags +++ b/manifest.tags @@ -1,2 +1,2 @@ -branch trunk -tag trunk +branch bigint-defaults +tag bigint-defaults diff --git a/manifest.uuid b/manifest.uuid index 75047a1bf0..7a2e15bd0b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5231ac428da4486d64e473e98aa72da5ca68848fba97845dbcf51fd2314debbf +c494b123f52506ab57edd3f4c317b882b270e13bd5798b6c8fbdf5eebbd4ed63 diff --git a/src/vdbemem.c b/src/vdbemem.c index 923d3e7951..c63874b5a5 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -1982,7 +1982,30 @@ int sqlite3ValueFromExpr( u8 affinity, /* Affinity to use */ sqlite3_value **ppVal /* Write the new value here */ ){ - return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0; + int rc = SQLITE_OK; + sqlite3_value *pVal = 0; + if( pExpr ){ + rc = valueFromExpr(db, pExpr, enc, affinity, &pVal, 0); + if( rc==SQLITE_OK && pVal + && affinity==SQLITE_AFF_REAL + && (pVal->flags & MEM_Int) + && (u64)(pVal->u.i<0 ? pVal->u.i : pVal->u.i)>140737488355327LL + ){ + /* If the integer value is too large to fit in a 6-byte integer and + ** the affinity is REAL, convert it to a real value now. In most + ** cases an OP_RealAffinity opcode will be used to convert the + ** value to an actual real, but this opcode is omitted if the values + ** are being read directly from a table in order to create an index + ** key. It is important to get a "real" real value for the larger + ** magnitude integer values so that comparisons work correctly - + ** SQLite by default will convert real values to integers before + ** doing the comparison, which is different from converting to real + ** first. */ + sqlite3VdbeMemRealify(pVal); + } + } + *ppVal = pVal; + return rc; } #ifdef SQLITE_ENABLE_STAT4 diff --git a/test/default.test b/test/default.test index 192b3d2ff3..801fb65947 100644 --- a/test/default.test +++ b/test/default.test @@ -141,4 +141,79 @@ do_catchsql_test default-5.2 { INSERT INTO Table0 DEFAULT VALUES ; } {1 {default value of column [Col0] is not constant}} +#------------------------------------------------------------------------- +# Large integer values as defaults for columns with real affinity. Report +# +# +do_execsql_test 6.0 { + CREATE TABLE t(id INTEGER PRIMARY KEY, k INT); + INSERT INTO t VALUES(1,1),(2,2); + ALTER TABLE t ADD COLUMN c REAL DEFAULT 9223372036854775807; + CREATE INDEX ti ON t(c); + INSERT INTO t(id, k) VALUES(3,3); +} + +do_execsql_test 1.1 { + SELECT DISTINCT typeof(c), quote(c) FROM t; +} {real 9.2233720368547758e+18} + +do_execsql_test 6.2 { + SELECT (SELECT c FROM t WHERE id=1) = (SELECT c FROM t WHERE id=3); +} {1} + +do_execsql_test 6.3 { + SELECT id FROM t WHERE c = 9.2233720368547758e+18; +} {1 2 3} + +do_execsql_test 6.4 { + SELECT id FROM t NOT INDEXED WHERE c = 9.2233720368547758e+18; +} {1 2 3} + +do_execsql_test 6.5 { + PRAGMA integrity_check; +} {ok} + +do_execsql_test 6.6 { + CREATE TABLE u(id INTEGER PRIMARY KEY, k INT); + INSERT INTO u VALUES(1,1); + ALTER TABLE u ADD COLUMN c REAL DEFAULT (9223372036854775807); + CREATE UNIQUE INDEX ui ON u(c); +} + +do_catchsql_test 6.7 { + INSERT INTO u(id,k) VALUES(2,2); +} {1 {UNIQUE constraint failed: u.c}} + +do_execsql_test 6.8 { + SELECT count(*) FROM u NOT INDEXED WHERE c = (SELECT c FROM u WHERE id=1); +} {1} +do_execsql_test 6.9 { + PRAGMA integrity_check; +} {ok} + +do_execsql_test 6.10 { + CREATE TABLE c1(id INTEGER PRIMARY KEY, k INT, + c REAL DEFAULT (9223372036854775807)); + INSERT INTO c1(id,k) VALUES(1,1),(2,2),(3,3); + CREATE INDEX c1i ON c1(c); + SELECT id FROM c1 WHERE c = 9.2233720368547758e+18; +} {1 2 3} + +do_execsql_test 6.11 { + CREATE TABLE c2(id INTEGER PRIMARY KEY, k INT); + INSERT INTO c2 VALUES(1,1),(2,2); + ALTER TABLE c2 ADD COLUMN c REAL DEFAULT (1000000000000000000); + INSERT INTO c2(id,k) VALUES(3,3); + CREATE INDEX c2i ON c2(c); + SELECT id FROM c2 WHERE c = 1.0e+18; +} {1 2 3} +do_execsql_test 6.12 { + CREATE TABLE c3(id INTEGER PRIMARY KEY, k INT); + INSERT INTO c3 VALUES(1,1),(2,2); + ALTER TABLE c3 ADD COLUMN c INT DEFAULT (9223372036854775807); + INSERT INTO c3(id,k) VALUES(3,3); + CREATE INDEX c3i ON c3(c); + SELECT id FROM c3 WHERE c = 9223372036854775807; +} {1 2 3} + finish_test