From: dan Date: Wed, 14 Sep 2011 19:41:44 +0000 (+0000) Subject: Merge latest changes from the trunk into the sessions branch. X-Git-Tag: version-3.13.0~148^2~254 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=93bca695786b8a7b1809ccd68113b6e13ed93fcc;p=thirdparty%2Fsqlite.git Merge latest changes from the trunk into the sessions branch. FossilOrigin-Name: c00e45ede7cbf71a3a6d1ccad0b9275010ca8493 --- 93bca695786b8a7b1809ccd68113b6e13ed93fcc diff --cc manifest index 3f34ca057c,bccc5fe4dc..883ad2f581 --- a/manifest +++ b/manifest @@@ -1,10 -1,10 +1,10 @@@ - C Merge\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch. - D 2011-08-26T19:20:47.301 -C Remove\s'const'\sfrom\sa\svariable\sthat\smight\sactually\sbe\swritten\swhen\san\sOOM\serror\soccurs.\sAlso,\sfix\sa\scouple\sMSVC/Win32\scompiler\swarnings. -D 2011-09-14T18:19:08.529 ++C Merge\slatest\schanges\sfrom\sthe\strunk\sinto\sthe\ssessions\sbranch. ++D 2011-09-14T19:41:44.795 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f - F Makefile.in 8c930e7b493d59099ea1304bd0f2aed152eb3315 + F Makefile.in d314143fa6be24828021d3f583ad37d9afdce505 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 - F Makefile.msc 55fe94bf23b4c1ff035f19b0ae2ea486350f8d01 - F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151 + F Makefile.msc 25da409ce0c7799e57f48a729a8e153b23027adc + F Makefile.vxworks 1deb39c8bb047296c30161ffa10c1b5423e632f9 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F VERSION f724de7326e87b7f3b0a55f16ef4b4d993680d54 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@@ -102,21 -102,9 +102,21 @@@ F ext/rtree/rtree_util.tcl 06aab2ed5b82 F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 +F ext/session/session1.test 502086908e4144dfaccb1baa77bc29d75a9daace +F ext/session/session2.test 99ca0da7ddb617d42bafd83adccf99f18ae0384b +F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01 +F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 +F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 +F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 +F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 +F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 +F ext/session/sessionfault.test 891453e96630ee2915081487fc4b7226f0aa252f +F ext/session/sqlite3session.c 57d04e1d6a3579e673e61dea29f214fb4e0fc505 +F ext/session/sqlite3session.h f374c9c4c96e08f67ac418871c29d423245c7673 +F ext/session/test_session.c ea4dc9b4a1895c8e6bddcbfe3838d7eb57df2d99 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 - F main.mk cb6055cd875d73dee78a7f88c04cd49457d8cc9a -F main.mk 8744cb76517817170f7fd2c78fbf0006fabb93c1 ++F main.mk ba82d040a497dc525b96103d007da17ce5baad6d F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac @@@ -136,16 -124,16 +136,16 @@@ F src/auth.c 523da7fb4979469955d822ff92 F src/backup.c 28a4fe55327ff708bfaf9d4326d02686f7a553c3 F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 - F src/btree.c ed13fdefdbe671d5777773dcfb3a162ddb4623ae - F src/btree.h 9ddf04226eac592d4cc3709c5a8b33b2351ff5f7 + F src/btree.c 77b09c69d4849a90361e6fe5db36d167f20600c0 + F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3 - F src/build.c 2d5de52df616a3bf5a659cbca85211c46e2ba9bd + F src/build.c 851e81f26a75abbb98bd99a7c5f10e8670d867bb F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac - F src/ctime.c caf51429be3e0d4114056a8273b0fff812ff8ae9 + F src/ctime.c e3132ec65240b2e2f3d50831021eac387f27584d F src/date.c a3c6842bad7ae632281811de112a8ba63ff08ab3 -F src/delete.c ff68e5ef23aee08c0ff528f699a19397ed8bbed8 +F src/delete.c 614d6e012aa5b624e78f3b556243497825de196b - F src/expr.c 4bbdfaf66bc614be9254ce0c26a17429067a3e07 + F src/expr.c cbcd8c2f1588a9862291a081699854c5e1cb28ab F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 9f00ea98f6b360d477b5a78b5b59a1fbde82431c F src/func.c 59bb046d7e3df1ab512ac339ccb0a6f996a17cb7 @@@ -191,16 -179,16 +191,16 @@@ F src/printf.c 585a36b6a963df832cfb6950 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 - F src/select.c d219c4b68d603cc734b6f9b1e2780fee12a1fa0d + F src/select.c bf7b7ea6befb483619da5f597b0864668b828c3c F src/shell.c bbe7818ff5bc8614105ceb81ad67b8bdc0b671dd -F src/sqlite.h.in 0a6c9c23337fd1352c5c75a613ff9533aa7d91cb +F src/sqlite.h.in 355493ac9492746a0bbd17a4fd40911aa89b5a3a F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93 - F src/sqliteInt.h a6f805d591b7b71703eb33dd9cd60ced889b71c6 -F src/sqliteInt.h c7e37ee49b1a922ddcd18fa98dd750efa4d2db14 ++F src/sqliteInt.h 68a33c1d88051fae92a9528f198fbcaf3ddb3b39 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e -F src/tclsqlite.c 3ef1dda2f1dc207c792eaadebf9d8adc44648581 +F src/tclsqlite.c be0e691e223a907aa032c7b3ed310dc0ff048109 - F src/test1.c 7439efb86c1022f19a39a8e61de2cbac23ffab03 + F src/test1.c 0f41b7c67719207a5de24b009e172c4dcf189827 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432 F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7 @@@ -250,14 -238,14 +250,14 @@@ F src/update.c 2d67e24d5a44d8b1c0839bf2 F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0 F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7 F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e - F src/vdbe.c 9bc9b5f1231b9ea1bd35fecb775cce970fe47ac7 - F src/vdbe.h ee8ba0243ff76fae3af1d020c8d82d8368a2a744 - F src/vdbeInt.h 1b36e54662ef3ee5c9ce4a5933e122ffb8782b93 - F src/vdbeapi.c ddd061183e2c3015f676e53ee85fcaf306617e8e - F src/vdbeaux.c 4b5f0e80af001976d61ecb1c1e44c03dd7cb3d16 -F src/vdbe.c 7008edbf8f608d82c035dcb1c56367ad85e68aaa -F src/vdbe.h a10b360bf69474babc8aba8fcc64b824c5e97d38 -F src/vdbeInt.h 693d6ac6810298fc6b4c503cfbe3f99a240f40af -F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98 -F src/vdbeaux.c ca8aa399e1be85fe82498b107128297a5d84e6a2 -F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3 ++F src/vdbe.c f03941d4126e2484a52652081a73f2e2e4d4eda1 ++F src/vdbe.h a3308e58577f1586e4b0afb5e08b1fb6ac743d0d ++F src/vdbeInt.h 1400515b37a4863cdda4601abc0f76eca846c9f5 ++F src/vdbeapi.c c969d467817ca90f99f3d3b46d115fbec08aeb4c ++F src/vdbeaux.c b09cc16325b4faad109fb3e59d393019d1600e55 +F src/vdbeblob.c fde0374afb0c512614aed191ac2683f6772d2b8f - F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b - F src/vdbesort.c 8a61a6d731cbe612217edf9eece6197f37c9489e + F src/vdbemem.c 5e6effb96dd53d233361cbfaa3f0a43b9af689e9 + F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790 F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114 F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582 F src/wal.c 3154756177d6219e233d84291d5b05f4e06ff5e9 @@@ -673,8 -661,7 +673,8 @@@ F test/select9.test 74c0fb2c6eecb0219cb F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532 F test/selectB.test 0d072c5846071b569766e6cd7f923f646a8b2bfa F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25 - F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c + F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118 +F test/session.test c1a17c11ef7d01c24fe2b9f7871190d949a8e718 F test/shared.test 34945a516532b11182c3eb26e31247eee3c9ae48 F test/shared2.test 8f71d4eb4d5261280de92284df74172545c852cc F test/shared3.test ebf77f023f4bdaa8f74f65822b559e86ce5c6257 @@@ -712,10 -699,10 +712,10 @@@ F test/tclsqlite.test d5298750115768bca F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test 51edd31c65ed1560dd600b1796e8325df96318e2 F test/temptrigger.test 26670ed7a39cf2296a7f0a9e0a1d7bdb7abe936d -F test/tester.tcl 0b2999b578964297663de4870babbbee29225622 +F test/tester.tcl 8db832ad03331dcae2f39b435feb2f789cd4e8d9 - F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f - F test/thread002.test 716631b06cccf33b368ab7f6dd3cad92907b8928 - F test/thread003.test 33d2d46e6a53ccb2ff8dc4d0c4e3b3aaee36dcd1 + F test/thread001.test 7cc2ce08f9cde95964736d11e91f9ab610f82f91 + F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 + F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 F test/thread004.test f51dfc3936184aaf73ee85f315224baad272a87f F test/thread005.test 50d10b5684399676174bd96c94ad4250b1a2c8b6 F test/thread1.test df115faa10a4ba1d456e9d4d9ec165016903eae4 @@@ -971,10 -958,10 +971,10 @@@ F tool/speedtest8.c 2902c46588c40b55661 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 - F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 + F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2 - P c5709036087b6b4fb6391ab7e4b4b870aac87a31 1dada5158215d1816edb69ff2610f9d2259ce19d - R a4d0f9879dd116c25d083f8cdc0d0501 - U drh - Z 0ce927a650c1609d421fc43e47e08b7b -P a1f3aeeb0988c848d40ce8f6da6e902935a997e2 -R 0af9d8f0b3f18e81a71e0aa10948427c -U mistachkin -Z d90e2842f2c20a0f3227a4c8a539b329 ++P eb036d6f81e15bac013316bf5b1b2ba3e0bd4605 3035dc1c7398791d550f4c02774ef7f961b4bb02 ++R 807d1da65636d94548ad55811c85e6a7 ++U dan ++Z e140cc97ae2304f1c705299d75477c59 diff --cc manifest.uuid index 8f69556b5d,c741eb7da4..39610efda7 --- a/manifest.uuid +++ b/manifest.uuid @@@ -1,1 -1,1 +1,1 @@@ - eb036d6f81e15bac013316bf5b1b2ba3e0bd4605 -3035dc1c7398791d550f4c02774ef7f961b4bb02 ++c00e45ede7cbf71a3a6d1ccad0b9275010ca8493 diff --cc src/vdbe.h index d0333d82f7,f4691c0e8f..9332b9851d --- a/src/vdbe.h +++ b/src/vdbe.h @@@ -61,7 -61,7 +61,8 @@@ 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 */ + int (*xAdvance)(BtCursor *, int *); } p4; #ifdef SQLITE_DEBUG char *zComment; /* Comment to improve readability */ @@@ -117,7 -117,7 +118,8 @@@ 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 */ + #define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */ ++#define P4_TABLE (-20) /* 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 --cc src/vdbeapi.c index dfe8f87a15,678f0d91e7..775a541f83 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@@ -1324,166 -1304,3 +1324,186 @@@ int sqlite3_stmt_status(sqlite3_stmt *p if( resetFlag ) pVdbe->aCounter[op-1] = 0; return v; } + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK ++/* ++** Allocate and populate an UnpackedRecord structure based on the serialized ++** record in nKey/pKey. Return a pointer to the new UnpackedRecord structure ++** if successful, or a NULL pointer if an OOM error is encountered. ++*/ ++static UnpackedRecord *vdbeUnpackRecord( ++ KeyInfo *pKeyInfo, ++ int nKey, ++ const void *pKey ++){ ++ char *dummy; /* Dummy argument for AllocUnpackedRecord() */ ++ UnpackedRecord *pRet; /* Return value */ ++ ++ pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo, 0, 0, &dummy); ++ if( pRet ){ ++ sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); ++ } ++ return pRet; ++} ++ +/* +** This function is called from within a pre-update callback to retrieve +** a field of the row currently being updated or deleted. +*/ +int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ + PreUpdate *p = db->pPreUpdate; + int rc = SQLITE_OK; + + /* Test that this call is being made from within an SQLITE_DELETE or + ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */ + if( !p || p->op==SQLITE_INSERT ){ + rc = SQLITE_MISUSE_BKPT; + goto preupdate_old_out; + } + if( iIdx>=p->pCsr->nField || iIdx<0 ){ + rc = SQLITE_RANGE; + goto preupdate_old_out; + } + + /* If the old.* record has not yet been loaded into memory, do so now. */ + if( p->pUnpacked==0 ){ + u32 nRec; + u8 *aRec; + + rc = sqlite3BtreeDataSize(p->pCsr->pCursor, &nRec); + if( rc!=SQLITE_OK ) goto preupdate_old_out; + aRec = sqlite3DbMallocRaw(db, nRec); + if( !aRec ) goto preupdate_old_out; + rc = sqlite3BtreeData(p->pCsr->pCursor, 0, nRec, aRec); + if( rc==SQLITE_OK ){ - p->pUnpacked = sqlite3VdbeRecordUnpack(&p->keyinfo, nRec, aRec, 0, 0); ++ p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec); + if( !p->pUnpacked ) rc = SQLITE_NOMEM; + } + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, aRec); + goto preupdate_old_out; + } + p->aRecord = aRec; + } + + if( iIdx>=p->pUnpacked->nField ){ + *ppValue = (sqlite3_value *)columnNullValue(); + }else{ + *ppValue = &p->pUnpacked->aMem[iIdx]; + if( iIdx==p->iPKey ){ + sqlite3VdbeMemSetInt64(*ppValue, p->iKey1); + } + sqlite3VdbeMemStoreType(*ppValue); + } + + preupdate_old_out: + sqlite3Error(db, rc, 0); + return sqlite3ApiExit(db, rc); +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +/* +** This function is called from within a pre-update callback to retrieve +** the number of columns in the row being updated, deleted or inserted. +*/ +int sqlite3_preupdate_count(sqlite3 *db){ + PreUpdate *p = db->pPreUpdate; + return (p ? p->keyinfo.nField : 0); +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +/* +** This function is designed to be called from within a pre-update callback +** only. It returns zero if the change that caused the callback was made +** immediately by a user SQL statement. Or, if the change was made by a +** trigger program, it returns the number of trigger programs currently +** on the stack (1 for a top-level trigger, 2 for a trigger fired by a +** top-level trigger etc.). +** +** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL +** or SET DEFAULT action is considered a trigger. +*/ +int sqlite3_preupdate_depth(sqlite3 *db){ + PreUpdate *p = db->pPreUpdate; + return (p ? p->v->nFrame : 0); +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK +/* +** This function is called from within a pre-update callback to retrieve +** a field of the row currently being updated or inserted. +*/ +int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ + PreUpdate *p = db->pPreUpdate; + int rc = SQLITE_OK; + Mem *pMem; + + if( !p || p->op==SQLITE_DELETE ){ + rc = SQLITE_MISUSE_BKPT; + goto preupdate_new_out; + } + if( iIdx>=p->pCsr->nField || iIdx<0 ){ + rc = SQLITE_RANGE; + goto preupdate_new_out; + } + + if( p->op==SQLITE_INSERT ){ + /* For an INSERT, memory cell p->iNewReg contains the serialized record + ** that is being inserted. Deserialize it. */ + UnpackedRecord *pUnpack = p->pNewUnpacked; + if( !pUnpack ){ + Mem *pData = &p->v->aMem[p->iNewReg]; + rc = sqlite3VdbeMemExpandBlob(pData); + if( rc!=SQLITE_OK ) goto preupdate_new_out; - pUnpack = sqlite3VdbeRecordUnpack(&p->keyinfo, pData->n, pData->z, 0, 0); ++ pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z); + if( !pUnpack ){ + rc = SQLITE_NOMEM; + goto preupdate_new_out; + } + p->pNewUnpacked = pUnpack; + } + if( iIdx>=pUnpack->nField ){ + pMem = (sqlite3_value *)columnNullValue(); + }else{ + pMem = &pUnpack->aMem[iIdx]; + if( iIdx==p->iPKey ){ + sqlite3VdbeMemSetInt64(pMem, p->iKey2); + } + sqlite3VdbeMemStoreType(pMem); + } + }else{ + /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required + ** value. Make a copy of the cell contents and return a pointer to it. + ** It is not safe to return a pointer to the memory cell itself as the + ** caller may modify the value text encoding. + */ + assert( p->op==SQLITE_UPDATE ); + if( !p->aNew ){ + p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem) * p->pCsr->nField); + if( !p->aNew ){ + rc = SQLITE_NOMEM; + goto preupdate_new_out; + } + } + assert( iIdx>=0 && iIdxpCsr->nField ); + pMem = &p->aNew[iIdx]; + if( pMem->flags==0 ){ + 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); + } + } + *ppValue = pMem; + + preupdate_new_out: + sqlite3Error(db, rc, 0); + return sqlite3ApiExit(db, rc); +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ diff --cc src/vdbeaux.c index 8b86e073fb,b00768477e..b7239bb684 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@@ -3243,67 -3239,3 +3241,83 @@@ void sqlite3VdbeSetVarmask(Vdbe *v, in v->expmask |= ((u32)1 << (iVar-1)); } } + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK ++ ++/* ++** If the second argument is not NULL, release any allocations associated ++** with the memory cells in the p->aMem[] array. Also free the UnpackedRecord ++** structure itself, using sqlite3DbFree(). ++** ++** This function is used to free UnpackedRecord structures allocated by ++** the vdbeUnpackRecord() function found in vdbeapi.c. ++*/ ++static void vdbeFreeUnpacked(sqlite3 *db, UnpackedRecord *p){ ++ if( p ){ ++ int i; ++ for(i=0; inField; i++){ ++ Mem *pMem = &p->aMem[i]; ++ if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem); ++ } ++ sqlite3DbFree(db, p); ++ } ++} ++ +/* +** Invoke the pre-update hook. If this is an UPDATE or DELETE pre-update call, +** then cursor passed as the second argument should point to the row about +** to be update or deleted. If the application calls sqlite3_preupdate_old(), +** the required value will be read from the row the cursor points to. +*/ +void sqlite3VdbePreUpdateHook( + Vdbe *v, /* Vdbe pre-update hook is invoked by */ + VdbeCursor *pCsr, /* Cursor to grab old.* values from */ + int op, /* SQLITE_INSERT, UPDATE or DELETE */ + const char *zDb, /* Database 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)); + if( op==SQLITE_UPDATE ){ + iKey2 = v->aMem[iReg].u.i; + }else{ + iKey2 = iKey1; + } + + assert( pCsr->nField==pTab->nCol + || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1) + ); + + preupdate.v = v; + preupdate.pCsr = pCsr; + preupdate.op = op; + preupdate.iNewReg = iReg; + preupdate.keyinfo.db = db; + preupdate.keyinfo.enc = ENC(db); + preupdate.keyinfo.nField = pTab->nCol; + 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; + sqlite3DbFree(db, preupdate.aRecord); - if( preupdate.pUnpacked ){ - sqlite3VdbeDeleteUnpackedRecord(preupdate.pUnpacked); - } - if( preupdate.pNewUnpacked ){ - sqlite3VdbeDeleteUnpackedRecord(preupdate.pNewUnpacked); - } ++ vdbeFreeUnpacked(db, preupdate.pUnpacked); ++ vdbeFreeUnpacked(db, preupdate.pNewUnpacked); + if( preupdate.aNew ){ + int i; + for(i=0; inField; i++){ + sqlite3VdbeMemRelease(&preupdate.aNew[i]); + } + sqlite3DbFree(db, preupdate.aNew); + } +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */