From 319eeb7b33eb9380924475f799ec66773c7ea953 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 19 Mar 2011 08:38:50 +0000 Subject: [PATCH] Fix a problem with INTEGER PRIMARY KEY columns and the pre-update hook. FossilOrigin-Name: 24d4d5dd007197a141555bcca6f2ac9ab47cde80 --- install-sh | 0 manifest | 46 ++++++++++++++++++---------------------------- manifest.uuid | 2 +- src/delete.c | 2 +- src/insert.c | 6 +++--- src/update.c | 2 +- src/vdbe.c | 40 +++++++++++++++++++++------------------- src/vdbe.h | 2 ++ src/vdbeInt.h | 5 ++++- src/vdbeapi.c | 14 ++++++++++++-- src/vdbeaux.c | 7 ++++++- test/hook.test | 17 ++++++++++++++++- test/progress.test | 0 tool/mkopts.tcl | 0 14 files changed, 85 insertions(+), 58 deletions(-) mode change 100755 => 100644 install-sh mode change 100644 => 100755 test/progress.test mode change 100644 => 100755 tool/mkopts.tcl diff --git a/install-sh b/install-sh old mode 100755 new mode 100644 diff --git a/manifest b/manifest index a02bffa46b..fffd7c5851 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index a441a6b6ae..e62b7f494c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1b736ac2934f2361dee5062e9033cbf26b41fc3a \ No newline at end of file +24d4d5dd007197a141555bcca6f2ac9ab47cde80 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index c7a686a8bd..3075df05fc 100644 --- a/src/delete.c +++ b/src/delete.c @@ -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 diff --git a/src/insert.c b/src/insert.c index 85b19ae3f7..cf48d0ffe7 100644 --- a/src/insert.c +++ b/src/insert.c @@ -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){ diff --git a/src/update.c b/src/update.c index 2c9f246d77..b67c76f5fe 100644 --- a/src/update.c +++ b/src/update.c @@ -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); diff --git a/src/vdbe.c b/src/vdbe.c index d6cdaaafca..de979b1cbb 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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; diff --git a/src/vdbe.h b/src/vdbe.h index 71c871d52f..2a6fe95fd4 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -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 diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 447e025e94..cac88af71e 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -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*); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 4fde5893b6..284e565e13 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -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 && iIdxpCsr->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); } } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 368330720d..a2526ace20 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -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; diff --git a/test/hook.test b/test/hook.test index 001e8ddf4a..9ceedbb75d 100644 --- a/test/hook.test +++ b/test/hook.test @@ -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 diff --git a/test/progress.test b/test/progress.test old mode 100644 new mode 100755 diff --git a/tool/mkopts.tcl b/tool/mkopts.tcl old mode 100644 new mode 100755