From: drh <> Date: Sat, 16 May 2026 17:09:12 +0000 (+0000) Subject: Have window functions sum(), total() and avg() correctly handle the obscure case... X-Git-Tag: release~56 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=af24f5e21e7cb94fe40b799734bea3cb8a9013e0;p=thirdparty%2Fsqlite.git Have window functions sum(), total() and avg() correctly handle the obscure case where integer overflow occurs as part of the same step that adds the first real value to the running total. Fix for forum post [forum:ec538b04ce | ec538b04ce]. FossilOrigin-Name: eb95d18aee8ffb9a2550aadbecccaf43c0a5778973386da1196a46f645e04286 --- diff --git a/manifest b/manifest index 8e2f7f005a..784521b702 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Have\sthe\ssqlite_dbpage\smodule\scorrectly\shandle\sconstraints\sof\sthe\sform\s"WHERE\spgno=$pgno"\swhen\s$pgno\sis\san\sinteger\sthat\scannot\sbe\srepresented\sas\sa\ssigned,\s32-bit\svalue. -D 2026-05-16T16:08:03.458 +C Have\swindow\sfunctions\ssum(),\stotal()\sand\savg()\scorrectly\shandle\sthe\sobscure\scase\swhere\sinteger\soverflow\soccurs\sas\spart\sof\sthe\ssame\sstep\sthat\sadds\sthe\sfirst\sreal\svalue\sto\sthe\srunning\stotal.\sFix\sfor\sforum\spost\s[forum:ec538b04ce\s|\sec538b04ce]. +D 2026-05-16T17:09:12.577 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -689,7 +689,7 @@ F src/delete.c 1f2268d6fe3c78fc1bf794ba65d7026498b78e2342ffaf85825dedae546e6fde F src/expr.c 51e9c77ff5d9a21439e611fe6571a3cd50387e526e13c5614fd407e5b8571930 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08 -F src/func.c 706ac012bf87d8ad7416a56a1d2b1f19e5dea03506a4606a01aa9d3bacf392c7 +F src/func.c ff7ac757da8ef84e8e2d6d060496678c7095291057ee0005efb3524a7ceda561 F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf @@ -2077,7 +2077,7 @@ F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af F test/windowB.test aad7c31739999f68a98a813cfd78390918fc70f56d2d925317a1523cab548ecf F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2 F test/windowD.test 65cf5a765fb8072450e8a0de2979ce7f09a38d87724fe1280c6444073e3da49b -F test/windowE.test d045a5fbaaf50ecac9483e1249dd317ba4f9d189c405a730ba6effdefb87b94f +F test/windowE.test a82a4213c7b923220de5e457cb76c537a5d10d5e94641e3055ba21b79870a7fb F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0 F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c @@ -2198,9 +2198,9 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 6cb565fe20049a48619fa3c7995de30fd9e284cfacd1652465e1f9083daf2669 -Q +350152d5124b71b3dd640c109dbac5f05a3a9583a335fbe25f707e1b754c1c74 -R a1f9164445cca44472cf6716983bb612 +P b6ce57f807297966f305d257e616f1c88a2f25c29f622249194b19d6fa014580 +Q +614f8cbc374c7a2d39826706f16ab1c17e75abb420a70be356c7eefa95b271a5 +R 77d06bfbe62b997d7cac93e8723d523f U drh -Z bf49456621545adaa0498e79920722c7 +Z b38886bbf861d2a802ea3517edfed28f # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 15bc23efc5..659963f2f8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b6ce57f807297966f305d257e616f1c88a2f25c29f622249194b19d6fa014580 +eb95d18aee8ffb9a2550aadbecccaf43c0a5778973386da1196a46f645e04286 diff --git a/src/func.c b/src/func.c index 4260f3e72f..3881604b99 100644 --- a/src/func.c +++ b/src/func.c @@ -1966,11 +1966,16 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){ assert( p->cnt>0 ); p->cnt--; if( !p->approx ){ - if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){ - p->ovrfl = 1; - p->approx = 1; + i64 x = p->iSum; + if( sqlite3SubInt64(&x, sqlite3_value_int64(argv[0]))==0 ){ + p->iSum = x; + return; } - }else if( type==SQLITE_INTEGER ){ + p->ovrfl = 1; + p->approx = 1; + kahanBabuskaNeumaierInit(p, p->iSum); + } + if( type==SQLITE_INTEGER ){ i64 iVal = sqlite3_value_int64(argv[0]); if( iVal!=SMALLEST_INT64 ){ kahanBabuskaNeumaierStepInt64(p, -iVal); diff --git a/test/windowE.test b/test/windowE.test index 1cb67f56b0..548dc84187 100644 --- a/test/windowE.test +++ b/test/windowE.test @@ -62,7 +62,6 @@ do_execsql_test 2.0 { sqlite3_create_aggregate db -breakpoint do_catchsql_test 2.1 { SELECT min(x) OVER w1 FROM t1 WINDOW w1 AS (PARTITION BY x_count(x) OVER w1); @@ -105,6 +104,64 @@ do_execsql_test 3.1 { 537 1.0 538 1.0 539 1.0 540 1.0 543 1.0 544 1.0 } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t1 VALUES(2, 9223372036854775807); + INSERT INTO t1 VALUES(3, 3); + INSERT INTO t1 VALUES(4, 4); +} + +do_execsql_test 4.1 { + SELECT a, + total(b) OVER (ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + FROM t1; +} { + 1 9.22337203685478e+18 2 9.22337203685478e+18 3 7.0 4 4.0 +} + +do_execsql_test 4.2 { + SELECT a, + total(b) OVER (ORDER BY a ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING) + FROM t1; +} { + 1 9.22337203685478e+18 2 9.22337203685478e+18 3 7.0 4 4.0 +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 5.0 { + CREATE TABLE t(id, x); + INSERT INTO t VALUES(1, -1); + INSERT INTO t VALUES(2, 9223372036854775807); + INSERT INTO t VALUES(3, 1); + INSERT INTO t VALUES(4, 0.5); +} + +do_execsql_test 5.1 { + SELECT id, + sum(id) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING) + FROM t t1 +} { + 1 6 + 2 9 + 3 7 + 4 4 +} + +breakpoint +do_execsql_test 5.2 { + SELECT id, + sum(x) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING) + FROM t t1 +} { + 1 9223372036854775807 + 2 9.22337203685478e+18 + 3 1.5 + 4 0.5 +} finish_test