]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem with INTEGER PRIMARY KEY columns and the pre-update hook.
authordan <dan@noemail.net>
Sat, 19 Mar 2011 08:38:50 +0000 (08:38 +0000)
committerdan <dan@noemail.net>
Sat, 19 Mar 2011 08:38:50 +0000 (08:38 +0000)
FossilOrigin-Name: 24d4d5dd007197a141555bcca6f2ac9ab47cde80

14 files changed:
install-sh [changed mode: 0755->0644]
manifest
manifest.uuid
src/delete.c
src/insert.c
src/update.c
src/vdbe.c
src/vdbe.h
src/vdbeInt.h
src/vdbeapi.c
src/vdbeaux.c
test/hook.test
test/progress.test [changed mode: 0644->0755]
tool/mkopts.tcl [changed mode: 0644->0755]

old mode 100755 (executable)
new mode 100644 (file)
index a02bffa46b86bc58208cebc5fe6c8c0977351b36..fffd7c5851ca2392438423b90384198b3da2873b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,5 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Merge\sthe\sfix\sto\sticket\s[f7b4edece25c99485]\sinto\sthe\ssessions\sbranch.
-D 2011-03-19T02:37:38.712
+C Fix\sa\sproblem\swith\sINTEGER\sPRIMARY\sKEY\scolumns\sand\sthe\spre-update\shook.
+D 2011-03-19T08:38:50
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -105,7 +102,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
 F ext/session/sqlite3session.c d4ba709d457a7b184a72ccd3ab07e5a1e9dd9196
 F ext/session/sqlite3session.h 9551c002efd5fde07c52994c6b592308e0df2d6a
 F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535
-F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
+F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7
 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
@@ -135,7 +132,7 @@ F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc
 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 F src/ctime.c 52ff72f966cee3087e0138a3ec69371c22be3c01
 F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b
-F src/delete.c 3c0925e958a77804a004222baa1a2a8ad855306b
+F src/delete.c 122c1a767883c439ad6393d32920152ecb560429
 F src/expr.c 00817c672af554321fd67c44325afd7cef0e4648
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c 418b840007c873975fd0d071746d952f8bca20ce
@@ -144,7 +141,7 @@ F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3
 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
 F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c b0d4150ae6d6fae7c3e8b69b65bcf37988d80ac0
+F src/insert.c c46747b4bdde2ae4c2815526a151fefb66ba64a6
 F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
 F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
 F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
@@ -233,15 +230,15 @@ F src/test_vfstrace.c f5c3b3b893d81a580d0f577e6d9bcfc1fd496136
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
 F src/trigger.c 95d2ff4b2996fabe886c9764b5978980e29f4afa
-F src/update.c aa39db6c39a1e234e8badf49768e1389dbb34650
+F src/update.c ca6d4ad2d87e743d22c47f1a6715cc5abf5cda05
 F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685
 F src/util.c cd997077bad039efc0597eb027c929658f93c018
 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f
-F src/vdbe.c 3f6d91163b5b7b3d2609bf5f21461d902989cdc5
-F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2
-F src/vdbeInt.h 20d13da932eed0667a2e2383a9cb0f80099a5fd3
-F src/vdbeapi.c 0e53620e9a4889257eece201d517163d3093ee41
-F src/vdbeaux.c 9807ae2e6974172b1d7b077327f862f6bd4dda2a
+F src/vdbe.c c90edafd941481506f001b17cd8523683fdac853
+F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9
+F src/vdbeInt.h 2cf77c1d151a4a54facd596d52be6d60c1cb26e8
+F src/vdbeapi.c c4692c74b31f4abe638fbcbae3944c52b54e2c36
+F src/vdbeaux.c 0216b2c37509a44c3833b297765bee7bdd04fa2f
 F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
 F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5
@@ -480,7 +477,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
 F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c
-F test/hook.test d0a277022888caf75ae1d4ec79917668f2f0f2e6
+F test/hook.test d054aad1a3772dd9045510382875468a9dcae15f
 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
 F test/in.test 19b642bb134308980a92249750ea4ce3f6c75c2d
 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
@@ -608,7 +605,7 @@ F test/permutations.test 5b2a4cb756ffb2407cb4743163668d1d769febb6
 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850
 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
-F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
+F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x
 F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
 F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
 F test/quota.test ddafe133653093eb9a99ccd6264884ae43f9c9b8
@@ -897,7 +894,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
 F tool/lemon.c dfd81a51b6e27e469ba21d01a75ddf092d429027
 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
 F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309
-F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
+F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
 F tool/mksqlite3c.tcl cf44512a48112b1ba09590548660a5a6877afdb3
 F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff
@@ -922,14 +919,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P c615c38c3283e21c33550c093099a793761123a7 eedbcf0a0ba91bb8b9cd3d115081ba297e9959fe
-R d0ca47f6483ae12a6d0c994e1006aea9
-U drh
-Z 5fff78b74e6c376b68b45fceb2b4a735
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFNhBb2oxKgR168RlERAgoXAKCNG+a12IdNjhU70FvIK6nf6CqkoQCfbtYL
-k5XHY8ri1b+IAtTgBjHO+hs=
-=5lEb
------END PGP SIGNATURE-----
+P 1b736ac2934f2361dee5062e9033cbf26b41fc3a
+R 162f72638a0f38fbe0fc1273d5b87dc2
+U dan
+Z 3b532fd3ba73ffa805a9d5e7143aadc5
index a441a6b6aef77151caafc0744fc003285f1cf51a..e62b7f494c1dc46bc63f2761ff8468e1c68fb4e4 100644 (file)
@@ -1 +1 @@
-1b736ac2934f2361dee5062e9033cbf26b41fc3a
\ No newline at end of file
+24d4d5dd007197a141555bcca6f2ac9ab47cde80
\ No newline at end of file
index c7a686a8bd48c52a41c9822e720f71d693ac78ed..3075df05fc56a8df644d2fc3a858dcc4b70351d7 100644 (file)
@@ -542,7 +542,7 @@ void sqlite3GenerateRowDelete(
   if( pTab->pSelect==0 ){
     sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0);
     sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
-    sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
+    sqlite3VdbeChangeP4(v, -1, pTab, P4_TABLE);
   }
 
   /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
index 85b19ae3f73f1a6356e0f472c627a02d2a228d07..cf48d0ffe7979bb4d4678f440068ff62964099b8 100644 (file)
@@ -1291,7 +1291,7 @@ void sqlite3GenerateConstraintChecks(
           ** OP_Insert replace the existing entry than it is to delete the
           ** existing entry and then insert a new one. */
           sqlite3VdbeAddOp2(v, OP_Delete, baseCur, OPFLAG_ISNOOP);
-          sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
+          sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE);
           if( pTab->pIndex ){
             sqlite3MultiWrite(pParse);
             sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
@@ -1481,7 +1481,7 @@ void sqlite3CompleteInsertion(
   }
   sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid);
   if( !pParse->nested ){
-    sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
+    sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE);
   }
   sqlite3VdbeChangeP5(v, pik_flags);
 }
@@ -1803,7 +1803,7 @@ static int xferOptimization(
   sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
   sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
   sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
-  sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
+  sqlite3VdbeChangeP4(v, -1, (char *)pDest, P4_TABLE);
   sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);
   for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
     for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
index 2c9f246d77e6b71466c05f79eb39f8f6fcca714e..b67c76f5fe7f586f03e6e657ed6808c43b36d457 100644 (file)
@@ -503,7 +503,7 @@ void sqlite3Update(
         regNewRowid
     );
     if( !pParse->nested ){
-      sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
+      sqlite3VdbeChangeP4(v, -1, pTab, P4_TABLE);
     }
     sqlite3VdbeJumpHere(v, j1);
 
index d6cdaaafca04dc6ce5de3dc50560a583626e6944..de979b1cbb99e0035e8c2fbc1b8621c8e5bff81d 100644 (file)
@@ -3838,9 +3838,9 @@ case OP_NewRowid: {           /* out2-prerelease */
 ** is part of an INSERT operation.  The difference is only important to
 ** the update hook.
 **
-** Parameter P4 may point to a string containing the table-name, or
-** may be NULL. If it is not NULL, then the update-hook 
-** (sqlite3.xUpdateCallback) is invoked following a successful insert.
+** Parameter P4 may point to a Table structure, or may be NULL. If it is 
+** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked 
+** following a successful insert.
 **
 ** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically
 ** allocated, then ownership of P2 is transferred to the pseudo-cursor
@@ -3865,7 +3865,7 @@ case OP_InsertInt: {
   int nZero;        /* Number of zero-bytes to append */
   int seekResult;   /* Result of prior seek or 0 if no USESEEKRESULT flag */
   const char *zDb;  /* database name - used by the update hook */
-  const char *zTbl; /* Table name - used by the opdate hook */
+  Table *pTab;      /* Table structure - used by update and pre-update hooks */
   int op;           /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
 
   pData = &aMem[pOp->p2];
@@ -3876,6 +3876,7 @@ case OP_InsertInt: {
   assert( pC->pCursor!=0 );
   assert( pC->pseudoTableReg==0 );
   assert( pC->isTable );
+  assert( pOp->p4type==P4_TABLE || pOp->p4type==P4_NOTUSED );
   REGISTER_TRACE(pOp->p2, pData);
 
   if( pOp->opcode==OP_Insert ){
@@ -3889,20 +3890,20 @@ case OP_InsertInt: {
     iKey = pOp->p3;
   }
 
-  if( pOp->p4.z && (db->xPreUpdateCallback || db->xUpdateCallback) ){
+  if( pOp->p4type==P4_TABLE && (db->xPreUpdateCallback||db->xUpdateCallback) ){
     assert( pC->isTable );
     assert( pC->iDb>=0 );
     zDb = db->aDb[pC->iDb].zName;
-    zTbl = pOp->p4.z;
+    pTab = pOp->p4.pTab;
     op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
   }
 
   /* Invoke the pre-update hook, if any */
   if( db->xPreUpdateCallback 
-   && pOp->p4.z 
+   && pOp->p4type==P4_TABLE
    && (!(pOp->p5 & OPFLAG_ISUPDATE) || pC->rowidIsValid==0)
   ){
-    sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, zTbl, iKey, pOp->p2);
+    sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, iKey, pOp->p2);
   }
 
   if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
@@ -3930,7 +3931,7 @@ case OP_InsertInt: {
 
   /* Invoke the update-hook if required. */
   if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
-    db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey);
+    db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, iKey);
   }
   break;
 }
@@ -3950,12 +3951,12 @@ case OP_InsertInt: {
 ** P1 must not be pseudo-table.  It has to be a real table with
 ** multiple rows.
 **
-** If P4 is not NULL then, either the update or pre-update hook, or both,
-** may be invoked. The P1 cursor must have been positioned using OP_NotFound 
-** prior to invoking this opcode in this case. Specifically, if one is 
-** configured, the pre-update hook is invoked if P4 is not NULL. The 
-** update-hook is invoked if one is configured, P4 is not NULL, and the 
-** OPFLAG_NCHANGE flag is set in P2.
+** If P4 is not NULL then it points to a Table struture. In this case either 
+** the update or pre-update hook, or both, may be invoked. The P1 cursor must
+** have been positioned using OP_NotFound prior to invoking this opcode in 
+** this case. Specifically, if one is configured, the pre-update hook is 
+** invoked if P4 is not NULL. The update-hook is invoked if one is configured, 
+** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2.
 **
 ** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address
 ** of the memory cell that contains the value that the rowid of the row will
@@ -3965,7 +3966,7 @@ case OP_Delete: {
   i64 iKey;
   VdbeCursor *pC;
   const char *zDb;
-  const char *zTbl;
+  Table *pTab;
   int opflags;
 
   opflags = pOp->p2;
@@ -3974,6 +3975,7 @@ case OP_Delete: {
   pC = p->apCsr[pOp->p1];
   assert( pC!=0 );
   assert( pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */
+  assert( pOp->p4type==P4_TABLE || pOp->p4type==P4_NOTUSED );
 
   /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
   ** OP_Column on the same table without any intervening operations that
@@ -3995,7 +3997,7 @@ case OP_Delete: {
     assert( pC->rowidIsValid );  /* lastRowid set by previous OP_NotFound */
     iKey = pC->lastRowid;
     zDb = db->aDb[pC->iDb].zName;
-    zTbl = pOp->p4.z;
+    pTab = pOp->p4.pTab;
   }
 
   /* Invoke the pre-update-hook if required. */
@@ -4003,7 +4005,7 @@ case OP_Delete: {
     assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) );
     sqlite3VdbePreUpdateHook(p, pC,
         (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, 
-        zDb, zTbl, iKey,
+        zDb, pTab, iKey,
         pOp->p3
     );
   }
@@ -4019,7 +4021,7 @@ case OP_Delete: {
     p->nChange++;
     assert( pOp->p4.z );
     if( rc==SQLITE_OK && db->xUpdateCallback ){
-      db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey);
+      db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName,iKey);
     }
   }
   break;
index 71c871d52f9a51bb88e3eb85e70e0347ae932791..2a6fe95fd4f70860deb4888e0165cb277f9f5b1d 100644 (file)
@@ -61,6 +61,7 @@ struct VdbeOp {
     KeyInfo *pKeyInfo;     /* Used when p4type is P4_KEYINFO */
     int *ai;               /* Used when p4type is P4_INTARRAY */
     SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */
+    Table *pTab;           /* Used when p4type is P4_TABLE */
   } p4;
 #ifdef SQLITE_DEBUG
   char *zComment;          /* Comment to improve readability */
@@ -116,6 +117,7 @@ typedef struct VdbeOpList VdbeOpList;
 #define P4_INT32    (-14) /* P4 is a 32-bit signed integer */
 #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
 #define P4_SUBPROGRAM  (-18) /* P4 is a pointer to a SubProgram structure */
+#define P4_TABLE    (-19) /* P4 is a pointer to a Table structure */
 
 /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
 ** is made.  That copy is freed when the Vdbe is finalized.  But if the
index 447e025e945e358401855efff1042b3d53e7fba4..cac88af71e5eeed0a501a8e0fe1f0d7b6bf5eb52 100644 (file)
@@ -344,6 +344,9 @@ struct PreUpdate {
   UnpackedRecord *pUnpacked;      /* Unpacked version of aRecord[] */
   UnpackedRecord *pNewUnpacked;   /* Unpacked version of new.* record */
   int iNewReg;                    /* Register for new.* values */
+  i64 iKey1;                      /* First key value passed to hook */
+  i64 iKey2;                      /* Second key value passed to hook */
+  int iPKey;                      /* If not negative index of IPK column */
   Mem *aNew;                      /* Array of new.* values */
 };
 
@@ -404,7 +407,7 @@ void sqlite3VdbeFrameDelete(VdbeFrame*);
 int sqlite3VdbeFrameRestore(VdbeFrame *);
 void sqlite3VdbeMemStoreType(Mem *pMem);
 void sqlite3VdbePreUpdateHook(
-    Vdbe *, VdbeCursor *, int, const char*, const char*, i64, int);
+    Vdbe *, VdbeCursor *, int, const char*, Table *, i64, int);
 
 #ifdef SQLITE_DEBUG
 void sqlite3VdbeMemPrepareToChange(Vdbe*,Mem*);
index 4fde5893b6e607f460c886ac414919aea31f34df..284e565e13363dac91327f42e31ff7fbe134167c 100644 (file)
@@ -1369,6 +1369,9 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
     *ppValue = (sqlite3_value *)columnNullValue();
   }else{
     *ppValue = &p->pUnpacked->aMem[iIdx];
+    if( iIdx==p->iPKey ){
+      sqlite3VdbeMemSetInt64(*ppValue, p->iKey1);
+    }
     sqlite3VdbeMemStoreType(*ppValue);
   }
 
@@ -1423,6 +1426,9 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
       pMem = (sqlite3_value *)columnNullValue();
     }else{
       pMem = &pUnpack->aMem[iIdx];
+      if( iIdx==p->iPKey ){
+        sqlite3VdbeMemSetInt64(pMem, p->iKey2);
+      }
       sqlite3VdbeMemStoreType(pMem);
     }
   }else{
@@ -1442,8 +1448,12 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
     assert( iIdx>=0 && iIdx<p->pCsr->nField );
     pMem = &p->aNew[iIdx];
     if( pMem->flags==0 ){
-      rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
-      if( rc!=SQLITE_OK ) goto preupdate_new_out;
+      if( iIdx==p->iPKey ){
+        sqlite3VdbeMemSetInt64(pMem, p->iKey2);
+      }else{
+        rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
+        if( rc!=SQLITE_OK ) goto preupdate_new_out;
+      }
       sqlite3VdbeMemStoreType(pMem);
     }
   }
index 368330720dacb8df945b169ae2766d32236804f1..a2526ace203ee74c74936b115a12cc9632480afb 100644 (file)
@@ -3182,13 +3182,14 @@ void sqlite3VdbePreUpdateHook(
   VdbeCursor *pCsr,               /* Cursor to grab old.* values from */
   int op,                         /* SQLITE_INSERT, UPDATE or DELETE */
   const char *zDb,                /* Database name */
-  const char *zTbl,               /* Table name */
+  Table *pTab,                    /* Modified table */
   i64 iKey1,                      /* Initial key value */
   int iReg                        /* Register for new.* record */
 ){
   sqlite3 *db = v->db;
   i64 iKey2;
   PreUpdate preupdate;
+  const char *zTbl = pTab->zName;
 
   assert( db->pPreUpdate==0 );
   memset(&preupdate, 0, sizeof(PreUpdate));
@@ -3205,6 +3206,10 @@ void sqlite3VdbePreUpdateHook(
   preupdate.keyinfo.db = db;
   preupdate.keyinfo.enc = ENC(db);
   preupdate.keyinfo.nField = pCsr->nField;
+  preupdate.iKey1 = iKey1;
+  preupdate.iKey2 = iKey2;
+  preupdate.iPKey = pTab->iPKey;
+
   db->pPreUpdate = &preupdate;
   db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
   db->pPreUpdate = 0;
index 001e8ddf4a36e86e63dda536a582259ba3549264..9ceedbb75d1fc0ba60618a49b08859aa38d9b510 100644 (file)
@@ -622,7 +622,7 @@ do_execsql_test 7.5.2.0 {
   ALTER TABLE t8 ADD COLUMN c DEFAULT 'xxx';
 }
 
-# At time of writing, these two are broken. They demonstraight that the
+# At time of writing, these two are broken. They demonstrate that the
 # sqlite3_preupdate_old() method does not handle the case where ALTER TABLE
 # has been used to add a column with a default value other than NULL.
 #
@@ -637,5 +637,20 @@ do_preupdate_test 7.5.2.2 {
   UPDATE main t8 2 2   three four xxx  three five xxx
 }
 
+# This block of tests verifies that IPK values are correctly reported
+# by the sqlite3_preupdate_old() and sqlite3_preupdate_new() functions.
+#
+do_execsql_test 7.6.1 { CREATE TABLE t9(a, b INTEGER PRIMARY KEY, c) }
+do_preupdate_test 7.6.2 {
+  INSERT INTO t9 VALUES(1, 2, 3);
+  UPDATE t9 SET b = b+1, c = c+1;
+  DELETE FROM t9 WHERE a = 1;
+} {
+  INSERT main t9 2 2   1 2 3
+  UPDATE main t9 2 3   1 2 3   1 3 4
+  DELETE main t9 3 3   1 3 4
+}
+
+
 finish_test
 
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)