From 2c7188732d7c62a0b04bc972c3b161442e693e28 Mon Sep 17 00:00:00 2001
From: dan <Dan Kennedy>
Date: Tue, 22 Jun 2021 18:32:05 +0000
Subject: [PATCH] Add the sqlite3_changes64() and sqlite3_total_changes64() API
 functions.

FossilOrigin-Name: 48fdec22c966003f5577e0bf52906ef90df11e4e395723a646304e67ed976f37
---
 manifest          | 34 +++++++++++++++++-----------------
 manifest.uuid     |  2 +-
 src/btree.c       |  4 ++--
 src/btree.h       |  2 +-
 src/func.c        |  2 +-
 src/main.c        | 10 ++++++++--
 src/sqlite.h.in   | 21 +++++++++++++++------
 src/sqliteInt.h   |  6 +++---
 src/tclsqlite.c   |  4 ++--
 src/vacuum.c      |  4 ++--
 src/vdbe.c        |  2 +-
 src/vdbeInt.h     |  6 +++---
 src/vdbeaux.c     |  2 +-
 test/changes.test |  6 ++++++
 14 files changed, 63 insertions(+), 42 deletions(-)

diff --git a/manifest b/manifest
index 6b799dd407..9a44b2b29f 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sproblem\scausing\ssqlite3_changes()\sto\sreturn\san\sincorrect\svalue\sfollowing\sa\s"DELETE\sFROM\stbl"\scommand\son\san\sintkey\stable\s(because\sinternal\sb+tree\scells\swere\sbeing\sincluded\sin\sthe\scount).
-D 2021-06-22T18:06:23.070
+C Add\sthe\ssqlite3_changes64()\sand\ssqlite3_total_changes64()\sAPI\sfunctions.
+D 2021-06-22T18:32:05.878
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -485,8 +485,8 @@ F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853
 F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c 34f14b261a0de31a2c195c88a698e940e93e112c137845c620a7149fde493300
-F src/btree.h ace9c1c243612bb95c32d848e3f9e159340c2caefcb68412b441569f56328f65
+F src/btree.c e204a9c8fb4fe5dbb910a863ba487f4af9b5c501254ec4ccbfcdd6b1f65b7fb4
+F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
 F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0
 F src/build.c ea28944f65b04f771e7aa5d614d406faa1bde5fe4ce882e2ead73049f03ed568
 F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
@@ -499,7 +499,7 @@ F src/delete.c 62451bba9fe641159e9c0b7d9d2bab1c48d0cff11e16de2d14000603d2af1fcf
 F src/expr.c 30a2abf526531ce6bd45fbc85bfec0fc3f6e5a0fb490cd2350855f2fc34dd789
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c e9063648396c58778f77583a678342fe4a9bc82436bf23c5f9f444f2df0fdaa4
-F src/func.c 9eb67f0aaf1cf439c21d6fc8afe270973d6e8345af3f1ebda98ad42186d30f5b
+F src/func.c 29264c728fc02a167eabc7c30c6c7719d8c9020f7ce5795061d25cf3322ed2d8
 F src/global.c 25ba4d58476f6be29bba9d9d14f7f146b78476d3a4d75ebb8c3b736328afe0f9
 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
@@ -508,7 +508,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c 2189e0e596010a0dc5405d9f14f78db1ee2fa71138c931f5b6ea96610b95bfc1
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 12684b3f19cd103cea97cdf14d0758196d0c646e12a898d7245141a9abfde9a4
-F src/main.c 9c06f8dc6137aaa990692ce30db1c00c3e6a574c5a4756640625c19b507c65ec
+F src/main.c c49a03dc832c479fbdce6f0bb51f20ac3c7c2541a956c8cba68a2f61c4d23ba6
 F src/malloc.c cbc93cdd429c4594912017d92ab656e2579aca64dbd1c6888551275bed46f25b
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -546,14 +546,14 @@ F src/resolve.c 35630effd4d16d2373caa41bae40a3d71f853f3ad0cb4f572f2ed4b8c350c1e9
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
 F src/select.c 4fa607bab6bcc580f12dbaf9c800b2250a1e408f10321a1d3bcb1dd30c447e62
 F src/shell.c.in f3e91c697f33daae14923355dcadfc26bb0c1eabdb343e5508706893e017a0a6
-F src/sqlite.h.in 8549395aa13361d5dcea04e3a57d680af10f7ee0989c45ebfffe3a3bcb2cdc3d
+F src/sqlite.h.in ee3df0ee7aa8ca2364377861bfa0ebd33b86c34d212f915147df9fc6a09b980f
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
-F src/sqliteInt.h ab37a8dd95884fc25ef1eb7b6d53d6674905c67298affc2b5bf947f739096504
+F src/sqliteInt.h fccf952bd572fe52f3bd2928982bd80933308c1118fdde27f667d0de7c77fb30
 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
-F src/tclsqlite.c 97645e4a15dde6a6ad6de8d81057ff9869413b866015a89e208fedacd709493e
+F src/tclsqlite.c 05663f6b5010b044eac0ef22fc8fb5ea3406d2502700a898261683258042c88b
 F src/test1.c 2100f4c28bae21ce83a9a0c5ec6827efd0e15d11b93b569b614daa5654b3fcf6
 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
@@ -615,12 +615,12 @@ F src/update.c 56fa0458b1ffc1042629f926443e8ed44203983df3ab2b0db2ba556e6ceed68c
 F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
 F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048
-F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
-F src/vdbe.c 226deb5bc5d88c4feb215cccaecdbe36924078737f27629fa06123d4da10f609
+F src/vacuum.c 454973a59fb20bb982efc2df568a098616db6328a0491b6e84e2e07f7333db45
+F src/vdbe.c e86894469af9c4c7824832df00f38ef727f6127080c69a7ad2f06d519c6db9aa
 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
-F src/vdbeInt.h 465fcb494db4ca6630fb9c19b2f3dfed597fbe885b0d4204193a5093b0dd7dc6
+F src/vdbeInt.h 1fc1e3581afcd3f56bdbe930639edac84ee823c034f31da97f49c35522f4c8c2
 F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5
-F src/vdbeaux.c 17e5f6a491d439396296dd20427829fad14c78a6be8f84415d253ff94c31ce9a
+F src/vdbeaux.c 23f9800742b11eb6d1d775fd332a88252e44e9f7ba94b826e211a5d9dbfe0ced
 F src/vdbeblob.c c6b8db50b227f66fb404215732068df76485b5b433e5f9d4d9ac27410b218193
 F src/vdbemem.c 53881aa0a7845922a075b3f375695588618098871a7a4120af4c297b80fa3e64
 F src/vdbesort.c cd5130f683706c1a43e165a74187745fb3351cb56052cf9dc91de820634bbde2
@@ -756,7 +756,7 @@ F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
 F test/carray01.test 3f2658bbddd75a013735a296ae2178ff441aca3f00ba623cfbae00b732ede792
 F test/cast.test 336fa21989b5170ebcaf90c24266be22dd97b3e23d1fad5ecf6ad4efb04c4423
 F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
-F test/changes.test 5d39e302b1d8047897961fdd682b4ce74a8abae6a7ba921a949d12ad0c4a9673
+F test/changes.test 9dd8e597d84072122fc8a4fcdea837f4a54a461e6e536053ea984303e8ca937b
 F test/check.test 4a2a91ed67eee84a6be16057c48d5198b6fb24849cd6da6cd855981de3fbb416
 F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014
 F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760
@@ -1919,7 +1919,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 53f64e83b39cb56ac7211ffc80d06da13318e1da9dbca7b9123954f5be229a0d
-R b8b931728b78e63830e81de935919c1c
+P f662ff4746aaa43e63e20710b8cbfeeceab3183e953ac1685c41846d2e9d124c
+R d7ab321cd3717ae98c57b82526dde848
 U dan
-Z 0889b85b76d9b21be2f69e6657d9c993
+Z 21b9ccfdea30ed9e9c32e68e5722010b
diff --git a/manifest.uuid b/manifest.uuid
index 698f3426e2..a38d536818 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-f662ff4746aaa43e63e20710b8cbfeeceab3183e953ac1685c41846d2e9d124c
\ No newline at end of file
+48fdec22c966003f5577e0bf52906ef90df11e4e395723a646304e67ed976f37
\ No newline at end of file
diff --git a/src/btree.c b/src/btree.c
index f6e6ec545f..57c556cc26 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9543,7 +9543,7 @@ static int clearDatabasePage(
   BtShared *pBt,           /* The BTree that contains the table */
   Pgno pgno,               /* Page number to clear */
   int freePageFlag,        /* Deallocate page if true */
-  int *pnChange            /* Add number of Cells freed to this counter */
+  i64 *pnChange            /* Add number of Cells freed to this counter */
 ){
   MemPage *pPage;
   int rc;
@@ -9606,7 +9606,7 @@ cleardatabasepage_out:
 ** If pnChange is not NULL, then the integer value pointed to by pnChange
 ** is incremented by the number of entries in the table.
 */
-int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
+int sqlite3BtreeClearTable(Btree *p, int iTable, i64 *pnChange){
   int rc;
   BtShared *pBt = p->pBt;
   sqlite3BtreeEnter(p);
diff --git a/src/btree.h b/src/btree.h
index fe724d6bb5..f80ba4a97b 100644
--- a/src/btree.h
+++ b/src/btree.h
@@ -123,7 +123,7 @@ int sqlite3BtreeIncrVacuum(Btree *);
 #define BTREE_BLOBKEY    2    /* Table has keys only - no data */
 
 int sqlite3BtreeDropTable(Btree*, int, int*);
-int sqlite3BtreeClearTable(Btree*, int, int*);
+int sqlite3BtreeClearTable(Btree*, int, i64*);
 int sqlite3BtreeClearTableOfCursor(BtCursor*);
 int sqlite3BtreeTripAllCursors(Btree*, int, int);
 
diff --git a/src/func.c b/src/func.c
index dc19ec7222..807b4574a1 100644
--- a/src/func.c
+++ b/src/func.c
@@ -582,7 +582,7 @@ static void changes(
 ){
   sqlite3 *db = sqlite3_context_db_handle(context);
   UNUSED_PARAMETER2(NotUsed, NotUsed2);
-  sqlite3_result_int(context, sqlite3_changes(db));
+  sqlite3_result_int64(context, sqlite3_changes64(db));
 }
 
 /*
diff --git a/src/main.c b/src/main.c
index a04a6bc0f2..f73f103f2a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1086,7 +1086,7 @@ void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){
 /*
 ** Return the number of changes in the most recent call to sqlite3_exec().
 */
-int sqlite3_changes(sqlite3 *db){
+sqlite3_int64 sqlite3_changes64(sqlite3 *db){
 #ifdef SQLITE_ENABLE_API_ARMOR
   if( !sqlite3SafetyCheckOk(db) ){
     (void)SQLITE_MISUSE_BKPT;
@@ -1095,11 +1095,14 @@ int sqlite3_changes(sqlite3 *db){
 #endif
   return db->nChange;
 }
+int sqlite3_changes(sqlite3 *db){
+  return (int)sqlite3_changes64(db);
+}
 
 /*
 ** Return the number of changes since the database handle was opened.
 */
-int sqlite3_total_changes(sqlite3 *db){
+sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){
 #ifdef SQLITE_ENABLE_API_ARMOR
   if( !sqlite3SafetyCheckOk(db) ){
     (void)SQLITE_MISUSE_BKPT;
@@ -1108,6 +1111,9 @@ int sqlite3_total_changes(sqlite3 *db){
 #endif
   return db->nTotalChange;
 }
+int sqlite3_total_changes(sqlite3 *db){
+  return (int)sqlite3_total_changes64(db);
+}
 
 /*
 ** Close all open savepoints. This function only manipulates fields of the
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index f8037a2d94..28c4bf01ef 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -2464,11 +2464,14 @@ void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
 ** CAPI3REF: Count The Number Of Rows Modified
 ** METHOD: sqlite3
 **
-** ^This function returns the number of rows modified, inserted or
+** ^These functions return the number of rows modified, inserted or
 ** deleted by the most recently completed INSERT, UPDATE or DELETE
 ** statement on the database connection specified by the only parameter.
-** ^Executing any other type of SQL statement does not modify the value
-** returned by this function.
+** The two functions are identical except for the type of the return value
+** and that if the number of rows modified by the most recent INSERT, UPDATE 
+** or DELETE is greater than the maximum value supported by type "int", then
+** the return value of sqlite3_changes() is undefined. ^Executing any other
+** type of SQL statement does not modify the value returned by these functions.
 **
 ** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
 ** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], 
@@ -2517,16 +2520,21 @@ void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
 ** </ul>
 */
 int sqlite3_changes(sqlite3*);
+sqlite3_int64 sqlite3_changes64(sqlite3*);
 
 /*
 ** CAPI3REF: Total Number Of Rows Modified
 ** METHOD: sqlite3
 **
-** ^This function returns the total number of rows inserted, modified or
+** ^These functions return the total number of rows inserted, modified or
 ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
 ** since the database connection was opened, including those executed as
-** part of trigger programs. ^Executing any other type of SQL statement
-** does not affect the value returned by sqlite3_total_changes().
+** part of trigger programs. The two functions are identical except for the 
+** type of the return value and that if the number of rows modified by the 
+** connection exceeds the maximum value supported by type "int", then
+** the return value of sqlite3_total_changes() is undefined. ^Executing 
+** any other type of SQL statement does not affect the value returned by 
+** sqlite3_total_changes().
 ** 
 ** ^Changes made as part of [foreign key actions] are included in the
 ** count, but those made as part of REPLACE constraint resolution are
@@ -2554,6 +2562,7 @@ int sqlite3_changes(sqlite3*);
 ** </ul>
 */
 int sqlite3_total_changes(sqlite3*);
+sqlite3_int64 sqlite3_total_changes64(sqlite3*);
 
 /*
 ** CAPI3REF: Interrupt A Long-Running Query
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 91af412bbd..6906d7ed57 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1522,8 +1522,8 @@ struct sqlite3 {
   u8 nSqlExec;                  /* Number of pending OP_SqlExec opcodes */
   int nextPagesize;             /* Pagesize after VACUUM if >0 */
   u32 magic;                    /* Magic number for detect library misuse */
-  int nChange;                  /* Value returned by sqlite3_changes() */
-  int nTotalChange;             /* Value returned by sqlite3_total_changes() */
+  i64 nChange;                  /* Value returned by sqlite3_changes() */
+  i64 nTotalChange;             /* Value returned by sqlite3_total_changes() */
   int aLimit[SQLITE_N_LIMIT];   /* Limits */
   int nMaxSorterMmap;           /* Maximum size of regions mapped by sorter */
   struct sqlite3InitInfo {      /* Information used during initialization */
@@ -4741,7 +4741,7 @@ Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
 int sqlite3CheckCollSeq(Parse *, CollSeq *);
 int sqlite3WritableSchema(sqlite3*);
 int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
-void sqlite3VdbeSetChanges(sqlite3 *, int);
+void sqlite3VdbeSetChanges(sqlite3 *, i64);
 int sqlite3AddInt64(i64*,i64);
 int sqlite3SubInt64(i64*,i64);
 int sqlite3MulInt64(i64*,i64);
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index 2206bca321..8874ab7699 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -2207,7 +2207,7 @@ static int SQLITE_TCLAPI DbObjCmd(
       return TCL_ERROR;
     }
     pResult = Tcl_GetObjResult(interp);
-    Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db));
+    Tcl_SetWideIntObj(pResult, sqlite3_changes64(pDb->db));
     break;
   }
 
@@ -3255,7 +3255,7 @@ deserialize_error:
       return TCL_ERROR;
     }
     pResult = Tcl_GetObjResult(interp);
-    Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db));
+    Tcl_SetWideIntObj(pResult, sqlite3_total_changes64(pDb->db));
     break;
   }
 
diff --git a/src/vacuum.c b/src/vacuum.c
index 93e2307d1a..be0e17535d 100644
--- a/src/vacuum.c
+++ b/src/vacuum.c
@@ -151,8 +151,8 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
   Btree *pTemp;           /* The temporary database we vacuum into */
   u32 saved_mDbFlags;     /* Saved value of db->mDbFlags */
   u64 saved_flags;        /* Saved value of db->flags */
-  int saved_nChange;      /* Saved value of db->nChange */
-  int saved_nTotalChange; /* Saved value of db->nTotalChange */
+  i64 saved_nChange;      /* Saved value of db->nChange */
+  i64 saved_nTotalChange; /* Saved value of db->nTotalChange */
   u32 saved_openFlags;    /* Saved value of db->openFlags */
   u8 saved_mTrace;        /* Saved trace settings */
   Db *pDb = 0;            /* Database to detach at end of vacuum */
diff --git a/src/vdbe.c b/src/vdbe.c
index 6623009aac..e21e0a55f0 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -6250,7 +6250,7 @@ case OP_Destroy: {     /* out2 */
 ** See also: Destroy
 */
 case OP_Clear: {
-  int nChange;
+  i64 nChange;
  
   sqlite3VdbeIncrWriteCounter(p, 0);
   nChange = 0;
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index b6e0288807..4a41c43a52 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -180,8 +180,8 @@ struct VdbeFrame {
   int nMem;               /* Number of entries in aMem */
   int nChildMem;          /* Number of memory cells for child frame */
   int nChildCsr;          /* Number of cursors for child frame */
-  int nChange;            /* Statement changes (Vdbe.nChange)     */
-  int nDbChange;          /* Value of db->nChange */
+  i64 nChange;            /* Statement changes (Vdbe.nChange)     */
+  i64 nDbChange;          /* Value of db->nChange */
 };
 
 /* Magic number for sanity checking on VdbeFrame objects */
@@ -388,7 +388,7 @@ struct Vdbe {
   u32 cacheCtr;           /* VdbeCursor row cache generation counter */
   int pc;                 /* The program counter */
   int rc;                 /* Value to return */
-  int nChange;            /* Number of db changes made since last reset */
+  i64 nChange;            /* Number of db changes made since last reset */
   int iStatement;         /* Statement number (or 0 if has no opened stmt) */
   i64 iCurrentTime;       /* Value of julianday('now') for this statement */
   i64 nFkConstraint;      /* Number of imm. FK constraints this VM */
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index edbf062749..7f08b5d25b 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -5009,7 +5009,7 @@ int sqlite3VdbeIdxKeyCompare(
 ** This routine sets the value to be returned by subsequent calls to
 ** sqlite3_changes() on the database handle 'db'. 
 */
-void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
+void sqlite3VdbeSetChanges(sqlite3 *db, i64 nChange){
   assert( sqlite3_mutex_held(db->mutex) );
   db->nChange = nChange;
   db->nTotalChange += nChange;
diff --git a/test/changes.test b/test/changes.test
index 3b31c50c0d..21db075f96 100644
--- a/test/changes.test
+++ b/test/changes.test
@@ -16,6 +16,12 @@ set testdir [file dirname $argv0]
 source $testdir/tester.tcl
 set testprefix changes
 
+# To test that the change-counters do not suffer from 32-bit signed integer 
+# rollover, add the following line to the array of test cases below. The
+# test will take will over an hour to run.
+#
+#   7 (1<<31)+10 ""
+#
 
 foreach {tn nRow wor} {
   1 50 ""