------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
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
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
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
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
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
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
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
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
-1b736ac2934f2361dee5062e9033cbf26b41fc3a
\ No newline at end of file
+24d4d5dd007197a141555bcca6f2ac9ab47cde80
\ No newline at end of file
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
** 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);
}
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);
}
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){
regNewRowid
);
if( !pParse->nested ){
- sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
+ sqlite3VdbeChangeP4(v, -1, pTab, P4_TABLE);
}
sqlite3VdbeJumpHere(v, j1);
** 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
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];
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 ){
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++;
/* 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;
}
** 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
i64 iKey;
VdbeCursor *pC;
const char *zDb;
- const char *zTbl;
+ Table *pTab;
int opflags;
opflags = pOp->p2;
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
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. */
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
);
}
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;
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 */
#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
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 */
};
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*);
*ppValue = (sqlite3_value *)columnNullValue();
}else{
*ppValue = &p->pUnpacked->aMem[iIdx];
+ if( iIdx==p->iPKey ){
+ sqlite3VdbeMemSetInt64(*ppValue, p->iKey1);
+ }
sqlite3VdbeMemStoreType(*ppValue);
}
pMem = (sqlite3_value *)columnNullValue();
}else{
pMem = &pUnpack->aMem[iIdx];
+ if( iIdx==p->iPKey ){
+ sqlite3VdbeMemSetInt64(pMem, p->iKey2);
+ }
sqlite3VdbeMemStoreType(pMem);
}
}else{
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);
}
}
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));
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;
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.
#
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