From: drh Date: Wed, 2 Dec 2015 20:40:26 +0000 (+0000) Subject: Merge recent enhancements from trunk. X-Git-Tag: version-3.13.0~148^2~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1bb15fc973f5b1b472897095f629abcc663bd453;p=thirdparty%2Fsqlite.git Merge recent enhancements from trunk. FossilOrigin-Name: d1a1278d7f3306536dc9cbd8fb300898f1e373e8 --- 1bb15fc973f5b1b472897095f629abcc663bd453 diff --cc Makefile.in index d76b5e4d18,f8766ac8f7..0d82204e06 --- a/Makefile.in +++ b/Makefile.in @@@ -406,10 -402,10 +406,11 @@@ TESTSRC = $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ - $(TOP)/src/test_wsd.c \ + $(TOP)/src/test_windirent.c \ + $(TOP)/src/test_wsd.c \ $(TOP)/ext/fts3/fts3_term.c \ - $(TOP)/ext/fts3/fts3_test.c \ + $(TOP)/ext/fts3/fts3_test.c \ + $(TOP)/ext/session/test_session.c \ $(TOP)/ext/rbu/test_rbu.c # Statically linked extensions diff --cc manifest index dfc4906ec6,123da22f21..78db225910 --- a/manifest +++ b/manifest @@@ -1,8 -1,8 +1,8 @@@ - C Merge\sthe\slatest\senhancements\sfrom\strunk. - D 2015-11-19T19:40:40.385 - F Makefile.in c9dfc95717a5af63ab90b36f22afd11e865e3559 -C Remove\sunreachable\sbranches\sfrom\sthe\sdecltype\scomputation\slogic\sin\sthe\squery\nplanner. -D 2015-12-02T19:46:12.775 -F Makefile.in 23d9a63484a383fc64951b25ef44067930f98dc6 ++C Merge\srecent\senhancements\sfrom\strunk. ++D 2015-12-02T20:40:26.162 ++F Makefile.in e7d3be066453d66f333e7cb98f4c9d3e700bfc09 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 - F Makefile.msc 4f04d3dbe993b706c956509b1437559d7f2469b1 -F Makefile.msc e8fdca1cb89a1b58b5f4d3a130ea9a3d28cb314d ++F Makefile.msc 820453f6340c500e2377a6ebd681cecfa92afd79 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 8b9d3ac6f1962f94e06ba05462422a544f9c4e36 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@@ -283,7 -263,7 +283,7 @@@ F ext/userauth/userauth.c 5fa3bdb492f48 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 - F main.mk 4f8d448adb9a7302cd5106f583ddc47067f1017d -F main.mk 9001039f432baeba1074e2d1885f3dfd572b8636 ++F main.mk 65524a49d6bbeb624b5953ed50a8c84d9dc34d16 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@@ -305,17 -285,17 +305,17 @@@ F src/btmutex.c 45a968cc85afed9b5e6cf55 F src/btree.c d3bdd8462a86492e2ebc9aca4a0168429017de25 F src/btree.h 2d76dee44704c47eed323356a758662724b674a0 F src/btreeInt.h 3ab435ed27adea54d040584b0bcc488ee7db1e38 - F src/build.c 5a3b71786e2b96d2bb92d40f190eb1fe736f25ca + F src/build.c e83da4d004a4e050c01acbb821ff7a7b1019c29b F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f - F src/ctime.c 509ef9c64d1321f42448f111da86400b1799218a + F src/ctime.c 58eda76364fb6f374e044aa4493219b13abf9400 F src/date.c fb1c99172017dcc8e237339132c91a21a0788584 F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78 -F src/delete.c 00af9f08a15ddc5cba5962d3d3e5bf2d67b2e7da +F src/delete.c 86e3940d07fe69a40270c2aaf6ca6c7adf19246c - F src/expr.c 0080c0f12806eca91e75a23a121a68918e9da357 + F src/expr.c cb1a419508e5b27769a91e00e36e94724e7b1d51 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0 - F src/func.c ecdd69ec6a1e406f04cc73324be2ebbf6354197f + F src/func.c fe50a9ab977acc0bb0fcd46741e0071fa388888e F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 @@@ -324,7 -304,7 +324,7 @@@ F src/insert.c 8ab83219eb56a103edb73bb0 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810 - F src/main.c 59798e68b7f93eaf243b2b4d054dd4eb6ead907a -F src/main.c 3f2828fce1e45c3ad096c69eee1e96962c7281c5 ++F src/main.c cf9fcb71ea8ea46ad20b37dc1af67c1a17cf73b5 F src/malloc.c 337bbe9c7d436ef9b7d06b5dd10bbfc8f3025972 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@@ -355,16 -335,16 +355,16 @@@ F src/pcache1.c 46a110be31a8d9f9b414317 F src/pragma.c f3e7147299ca05ef4304a36f1fd6e002729c72c6 F src/pragma.h 3d94aebbebd2089899fecc01909bf2608b39507d F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 - F src/printf.c f8fc8f04e75b1e983ef2793c27ec7a43b287e94a + F src/printf.c ca05561795ad6c2fa47acdd007702586282f7feb F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 - F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 + F src/resolve.c f4c897ca76ca6d5e0b3f0499c627392ffe657c8e F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e - F src/select.c 2376d320907a5c28c55290f18fd94aa3400bf97c - F src/shell.c 072fc3601b0ac02e50939b469fabeecfe3d66dcd - F src/sqlite.h.in eed36953a0b5ce6c099b0cb2cb6b6ba220e6ca77 + F src/select.c 1611828a7116e5f6cc1e69cd07d59b0d2c662ea9 -F src/shell.c 2796237990d42e6a5a7beafee65ef70cc8767d21 -F src/sqlite.h.in 5bd83191711d3dc85030326daa9e8e5226a495e7 ++F src/shell.c 98bf4a35a121c9d4b91940a53794f2cbc354c45c ++F src/sqlite.h.in fc89d305439df88cfe018dbbaf1770645766fa2f F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad - F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924 - F src/sqliteInt.h d85782b8b5b2057ac015f7ec20195b7ce869960d + F src/sqlite3ext.h 41ef50b0418a7c5ad1337bb80db5a7928dee764f -F src/sqliteInt.h 64256d193a16a147d9f6317cc4e095fdd3e0a2e9 ++F src/sqliteInt.h 0bf170994dbc42d4344eed5d59d88ed0631aa4d1 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@@ -383,10 -363,10 +383,10 @@@ F src/test_autoext.c dea8a01a7153b9adc9 F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f - F src/test_config.c a25edf31cc0dbe17f5d1d667b1320cbb4e52b6dd -F src/test_config.c 48850687dd5abc8260e23835632511054ccae172 ++F src/test_config.c bae65b68a216f31e225a46187497bdc007c1c5e5 F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc - F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f + F src/test_fs.c aab47ac456316502faa265daadf9ac832fea12b9 F src/test_func.c 0d9c25956152adefee8881c6fadc8354793764d0 F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32 @@@ -418,18 -400,18 +420,18 @@@ F src/threads.c bbfb74450643cb5372a43ad F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785 F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66 F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f - F src/update.c c2fff3b60bfcabcb0372acbe8cf6f77c2bb515bc -F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3 ++F src/update.c d8d675aa299336ac086ad2039d7e812cd6237db0 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c - F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd + F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 - F src/vdbe.c 9539aa0ccf4844b8b59466ef3c15dbffb479a390 -F src/vdbe.c 4d75375fa8bf911aa76ab8383d6f7eea0dec0fda -F src/vdbe.h efb7a8c1459e31f3ea4377824c6a7e4cb5068637 -F src/vdbeInt.h 75c2e82ee3357e9210c06474f8d9bdf12c81105d -F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca -F src/vdbeaux.c 9a234c9aaab4ad725daf94667cfed441a437c52d -F src/vdbeblob.c fdc4a81605ae7a35ae94a55bd768b66d6be16f15 -F src/vdbemem.c fdd1578e47bea61390d472de53c565781d81e045 ++F src/vdbe.c 5c3dd0f49bfebfddbfa4d389ed394b2b28d48cbf +F src/vdbe.h bfe3f80dba435377cdb64fd917f2529f0f48ab77 - F src/vdbeInt.h d6ae6e64ad16e213f37306b1735ff72fb98bec69 - F src/vdbeapi.c f5eda36a5c85ef578957ab4311e8d9b1f51a3552 - F src/vdbeaux.c 67db9a1c132207f4d6a8f4e76531cea39539fcaa - F src/vdbeblob.c b400c25ac822af3c507ef84b5cd93c1583a70321 ++F src/vdbeInt.h 4f3b46806b93faa92f0511c7ce30ed31aaec65be ++F src/vdbeapi.c ab2cb8fe23fb9f3195f1311eaa800495d83b6118 ++F src/vdbeaux.c 514e93b162bf3e84c82478f174728cda9135b558 ++F src/vdbeblob.c cc13eca96b8ec51b6248de785a1aec5df11f5805 +F src/vdbemem.c 25b6cfd665b5073480452426e84136edd94140c0 - F src/vdbesort.c 8b23930a1289526f6d2a3a9f2e965bcc963e4a68 + F src/vdbesort.c a7ec02da4494c59dfd071126dd3726be5a11459d F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vtab.c 2a8b44aa372c33f6154208e7a7f6c44254549806 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb @@@ -781,9 -763,9 +783,9 @@@ F test/fuzzdata4.db 1882f0055fb63214d84 F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98 - F test/hexlit.test 1d312fa816dfd3650a3bb488093bc09a0c927f67 + F test/hexlit.test d7b0a5f41123df1e43985b91b8b2e70f95282d21 F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711 -F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f +F test/hook.test aa41c095d26822b8a51aa4c82904a14347961be6 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/ieee754.test 118b665a97a8df0e8f2fbdb07d113e596f4a6b53 F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 @@@ -1414,10 -1397,10 +1418,10 @@@ F tool/speedtest2.tcl ee2149167303ba8e9 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c - F tool/sqldiff.c db1232df457fdd4cbf2a919a497fc44bb18fb933 + F tool/sqldiff.c 653db1a9294e0b34849c4504599c282a18d8b8c6 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d -F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f +F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148 F tool/tostr.tcl 96022f35ada2194f6f8ccf6fd95809e90ed277c4 F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003 F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c @@@ -1425,7 -1408,7 +1429,7 @@@ F tool/vdbe_profile.tcl 246d0da094856d7 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f - P 78bc42e664e9fa9ee21ad9762c369f291fcdf5db 126b998cf163dcdd5a222634f1e929f04db3c700 - R d78a5057451ca68f4e40e727fe9ca899 -P 3e1d71fcaf57c0223ab9a7366c8607f8f66bb21c -R 0397cf9717330ffe9055735c8207c81a ++P 7d6cfc79e7e5534ebacd980479917bc528a638f7 4f2bcff94c672312805be1400050a7026f93a9d7 ++R 50fae771d9c27e855af8c38f94348078 U drh - Z 251138aef0997d710e6be89ddc7546bd -Z 6381d064415ccbeec9de47fb6017aaa8 ++Z 355385643ee65578020d9d55249a7cd0 diff --cc manifest.uuid index 77c3b5ff65,c4252b6021..ca5a2e0553 --- a/manifest.uuid +++ b/manifest.uuid @@@ -1,1 -1,1 +1,1 @@@ - 7d6cfc79e7e5534ebacd980479917bc528a638f7 -4f2bcff94c672312805be1400050a7026f93a9d7 ++d1a1278d7f3306536dc9cbd8fb300898f1e373e8 diff --cc src/vdbe.c index 5557db6d43,f87fddafed..9589f876ac --- a/src/vdbe.c +++ b/src/vdbe.c @@@ -4286,10 -4284,9 +4294,10 @@@ case OP_InsertInt: assert( memIsValid(pData) ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->pCursor!=0 ); - assert( pC->pseudoTableReg==0 ); + assert( pC->eCurType==CURTYPE_BTREE ); + assert( pC->uc.pCursor!=0 ); assert( pC->isTable ); + assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC ); REGISTER_TRACE(pOp->p2, pData); if( pOp->opcode==OP_Insert ){ @@@ -4387,50 -4361,27 +4395,50 @@@ case OP_Delete: assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ + assert( pC->eCurType==CURTYPE_BTREE ); + assert( pC->uc.pCursor!=0 ); assert( pC->deferredMoveto==0 ); - hasUpdateCallback = db->xUpdateCallback && pOp->p4.z && pC->isTable; - if( pOp->p5 && hasUpdateCallback ){ - sqlite3BtreeKeySize(pC->uc.pCursor, &pC->movetoTarget); - } -- #ifdef SQLITE_DEBUG - /* The seek operation that positioned the cursor prior to OP_Delete will - ** have also set the pC->movetoTarget field to the rowid of the row that - ** is being deleted */ - if( pOp->p4.z && pC->isTable && pOp->p5==0 ){ + if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){ + /* If p5 is zero, the seek operation that positioned the cursor prior to + ** OP_Delete will have also set the pC->movetoTarget field to the rowid of + ** the row that is being deleted */ i64 iKey = 0; - sqlite3BtreeKeySize(pC->pCursor, &iKey); + sqlite3BtreeKeySize(pC->uc.pCursor, &iKey); - assert( pC->movetoTarget==iKey ); + assert( pC->movetoTarget==iKey ); + } +#endif + + /* If the update-hook or pre-update-hook will be invoked, set zDb to + ** the name of the db to pass as to it. Also set local pTab to a copy + ** of p4.pTab. Finally, if p5 is true, indicating that this cursor was + ** last moved with OP_Next or OP_Prev, not Seek or NotFound, set + ** VdbeCursor.movetoTarget to the current rowid. */ + if( pOp->p4.pTab && HAS_UPDATE_HOOK(db) ){ + assert( pC->iDb>=0 ); + zDb = db->aDb[pC->iDb].zName; + pTab = pOp->p4.pTab; + if( pOp->p5 && pC->isTable ){ - sqlite3BtreeKeySize(pC->pCursor, &pC->movetoTarget); ++ sqlite3BtreeKeySize(pC->uc.pCursor, &pC->movetoTarget); + } + } + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + /* Invoke the pre-update-hook if required. */ + if( db->xPreUpdateCallback && pOp->p4.pTab && HasRowid(pTab) ){ + assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) ); + sqlite3VdbePreUpdateHook(p, pC, + (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, + zDb, pTab, pC->movetoTarget, + pOp->p3 + ); } #endif + + if( opflags & OPFLAG_ISNOOP ) break; - rc = sqlite3BtreeDelete(pC->pCursor, pOp->p5); + rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ diff --cc src/vdbeapi.c index 12546bdc8c,33c6ba3b28..b50892b86d --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@@ -1598,187 -1598,6 +1598,187 @@@ int sqlite3_stmt_status(sqlite3_stmt *p return (int)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 ){ + memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1)); + 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); ++ rc = sqlite3BtreeDataSize(p->pCsr->uc.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); ++ rc = sqlite3BtreeData(p->pCsr->uc.pCursor, 0, nRec, aRec); + if( rc==SQLITE_OK ){ + 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); + } + } + + preupdate_old_out: + sqlite3Error(db, rc); + 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 = 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); + } + } + }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; + } + } + } + *ppValue = pMem; + + preupdate_new_out: + sqlite3Error(db, rc); + return sqlite3ApiExit(db, rc); +} +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + #ifdef SQLITE_ENABLE_STMT_SCANSTATUS /* ** Return status data for a single loop within query pStmt.