From aa59505ae85ee929b2d80d13e54ea17300f64e57 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 23 May 2017 19:23:45 +0000 Subject: [PATCH] Add experimental new API sqlite3_wal_info(). FossilOrigin-Name: 5b9d498f6e9de6ee2ab86370c02c28a2a8b83d717b96d23b1fc52107677e45a2 --- manifest | 26 +++++++++++++------------- manifest.uuid | 2 +- src/main.c | 31 +++++++++++++++++++++++++++++++ src/pager.c | 5 +++++ src/pager.h | 2 ++ src/sqlite.h.in | 25 +++++++++++++++++++++++++ src/test1.c | 36 ++++++++++++++++++++++++++++++++++++ src/wal.c | 16 ++++++++++++++++ src/wal.h | 3 +++ test/concurrent2.test | 29 +++++++++++++++++++++++++++++ 10 files changed, 161 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 779e15b1f4..8d9ba32435 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Invoke\ssqlite3_log()\sin\sresponse\sto\sirregularities\ssurrounding\sthe\nPager.pAllRead\sbit-vector. -D 2017-05-19T19:57:15.749 +C Add\sexperimental\snew\sAPI\ssqlite3_wal_info(). +D 2017-05-23T19:23:45.315 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 8eeb80162074004e906b53d7340a12a14c471a83743aab975947e95ce061efcc @@ -372,7 +372,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c d4bb3a135948553d18cf992f76f7ed7b18aa0327f250607b5a6671e55d9947d5 F src/legacy.c e88ed13c2d531decde75d42c2e35623fb9ce3cb0 F src/loadext.c a72909474dadce771d3669bf84bf689424f6f87d471fee898589c3ef9b2acfd9 -F src/main.c 1e448d204045c1dcd604853639d9d8fe253aa9ec302a2f1ffd2e22752fd6b708 +F src/main.c 5559b8e5aa6a7222d3dff52ae377b48e4365a7a4e3ea21491fc6c508a1fb838a F src/malloc.c e20bb2b48abec52d3faf01cce12e8b4f95973755fafec98d45162dfdab111978 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -394,8 +394,8 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820 F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c ba57b91a11790725f53238c6e3f38734a296219f2cab26e0df764b7fb43c952e -F src/pager.h 5e7b4e5afdcbdf558c211f27786672b3d2536003d0fb6c4888addb500c826e15 +F src/pager.c babddba9a8aa02feae4544175d4eeaee65321c263d78cf3ff3e0670df41bc837 +F src/pager.h 1afb4b777b3a297d56dc6cafc4f17d47d92522e9d2cb106839ea0fa0d6d489c7 F src/parse.y 21660e5224d1e1635a4ad45ad4365c8f67153b8081b7a11e35629844ecb48ab0 F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870 F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 @@ -409,7 +409,7 @@ F src/resolve.c 3e518b962d932a997fae373366880fc028c75706 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c d74b1cde1d9ca6d08bec50b60a5be19440273646bc8ae16648d748c38161d5b7 F src/shell.c a37d96b20b3644d0eb905df5aa7a0fcf9f6e73c15898337230c760a24a8df794 -F src/sqlite.h.in 8dd468837a4f6d76713e3a4cc65bea48095009038593d41040ab46c1b351197f +F src/sqlite.h.in 6eae6c87571d142f5aee27d49b13b5aec06bae40c706494e8565a64ab68b03f5 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28 F src/sqliteInt.h b7e590bc90ebee66cf79fb41312a7cdbce881b7db316d934c159294ff6087fd5 @@ -417,7 +417,7 @@ F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/tclsqlite.c c8cf60d0c5411d5e70e7c136470d29dbe760d250f55198b71682c67086524e4a -F src/test1.c c99f0442918a7a5d5b68a95d6024c211989e6c782c15ced5a558994baaf76a5e +F src/test1.c 108f95744b7c949ac806ad67a4be5d9e283bbe2011639a1b7ca512a1c52e908a F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c d03f5b5da9a2410b7a91c64b0d3306ed28ab6fee F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6 @@ -485,8 +485,8 @@ F src/vdbesort.c e72fe02a2121386ba767ede8942e9450878b8fc873abf3d1b6824485f092570 F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834 F src/vtab.c 35b9bdc2b41de32a417141d12097bcc4e29a77ed7cdb8f836d1d2305d946b61b F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 2858e71b30d521c80949fa10ed6b116367865594 -F src/wal.h 8659519a248ef0f33e575b20ab04211cebe1f430 +F src/wal.c 0c4faf368f51abb3f077fa5c175920b73b6a07584688a287c8d77296b6af582e +F src/wal.h 79378c5cd2127f32060d4952d827a7abdd490f8f9e5cbb14a4c39657ed99ad15 F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791 F src/where.c c6352f15be5031907c68bcbde96cad1a6da20e9f4051d10168a59235de9a8566 F src/whereInt.h 2a4b634d63ce488b46d4b0da8f2eaa8f9aeab202bc25ef76f007de5e3fba1f20 @@ -610,7 +610,7 @@ F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1 F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b F test/concfault.test 500f17c3fcfe7705114422bcc6ddd3c740001a43 F test/concurrent.test 3eb5e6a911dc6ff72e3a679f563e683b436f6c701e6e1d6050173df2b8448d6b -F test/concurrent2.test 77d655c6af93e77803b5c926555a838bb21f922f +F test/concurrent2.test ba7e166187289ee23089fff4f9527bc36f7cc324196cc8e84d31eae2769e678f F test/concurrent3.test 0a5f7e3036d1eccf0782d7153ac21f5f222e9468 F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c @@ -1589,7 +1589,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0eed152162b4721f7aaba8b480426476978a869e9578f100fca7b1d32942fe1a -R dfb5691b0d7dbb9b1f618a1ddfa439f1 +P 9527089b7aa3695cd577f31b263b4777e9bd62dbbc1bd3af892c570e52e8c3a1 +R 37ee232af322d70fdc5a9c9d4ab6870b U dan -Z 2e92764e6404f57fc047755474f473c5 +Z 786d45f8ca40d966271275a2c1f1d5ca diff --git a/manifest.uuid b/manifest.uuid index e02de0443e..eb3f0245f3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9527089b7aa3695cd577f31b263b4777e9bd62dbbc1bd3af892c570e52e8c3a1 \ No newline at end of file +5b9d498f6e9de6ee2ab86370c02c28a2a8b83d717b96d23b1fc52107677e45a2 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 32d00087f5..57172a4a2e 100644 --- a/src/main.c +++ b/src/main.c @@ -4095,3 +4095,34 @@ void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ sqlite3_free(pSnapshot); } #endif /* SQLITE_ENABLE_SNAPSHOT */ + +SQLITE_EXPERIMENTAL int sqlite3_wal_info( + sqlite3 *db, const char *zDb, + unsigned int *pnPrior, unsigned int *pnFrame +){ + int rc = SQLITE_OK; + +#ifndef SQLITE_OMIT_WAL + Btree *pBt; + int iDb; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ){ + return SQLITE_MISUSE_BKPT; + } +#endif + + sqlite3_mutex_enter(db->mutex); + iDb = sqlite3FindDbName(db, zDb); + if( iDb<0 ){ + return SQLITE_ERROR; + } + pBt = db->aDb[iDb].pBt; + rc = sqlite3PagerWalInfo(sqlite3BtreePager(pBt), pnPrior, pnFrame); + sqlite3_mutex_leave(db->mutex); +#endif /* SQLITE_OMIT_WAL */ + + return rc; +} + + diff --git a/src/pager.c b/src/pager.c index 8c17a001bd..4b0d5bcba6 100644 --- a/src/pager.c +++ b/src/pager.c @@ -7707,6 +7707,11 @@ int sqlite3PagerSnapshotRecover(Pager *pPager){ return rc; } #endif /* SQLITE_ENABLE_SNAPSHOT */ + +int sqlite3PagerWalInfo(Pager *pPager, u32 *pnPrior, u32 *pnFrame){ + return sqlite3WalInfo(pPager->pWal, pnPrior, pnFrame); +} + #endif /* !SQLITE_OMIT_WAL */ #ifdef SQLITE_ENABLE_ZIPVFS diff --git a/src/pager.h b/src/pager.h index 8bf2caa6f5..aa98bce95d 100644 --- a/src/pager.h +++ b/src/pager.h @@ -231,6 +231,8 @@ int sqlite3PagerIsWal(Pager*); int sqlite3PagerIswriteable(DbPage*); +int sqlite3PagerWalInfo(Pager*, u32 *pnPrior, u32 *pnFrame); + #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) void *sqlite3PagerCodec(DbPage *); #endif diff --git a/src/sqlite.h.in b/src/sqlite.h.in index d836e97058..df228b2c9a 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8495,6 +8495,31 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); +/* +** CAPI3REF: Wal related information regarding the most recent COMMIT +** EXPERIMENTAL +** +** This function reports on the state of the wal file (if any) for database +** zDb, which should be "main", "temp", or the name of the attached database. +** Its results - the values written to the output parameters - are only +** defined if the most recent SQL command on the connection was a successful +** COMMIT that wrote data to wal-mode database zDb. +** +** Assuming the above conditions are met, output parameter (*pnFrame) is set +** to the total number of frames in the wal file. Parameter (*pnPrior) is +** set to the number of frames that were present in the wal file before the +** most recent transaction was committed. So that the number of frames written +** by the most recent transaction is (*pnFrame)-(*pnPrior). +** +** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. It +** is not an error if this function is called at a time when the results +** are undefined. +*/ +SQLITE_EXPERIMENTAL int sqlite3_wal_info( + sqlite3 *db, const char *zDb, + unsigned int *pnPrior, unsigned int *pnFrame +); + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. diff --git a/src/test1.c b/src/test1.c index 87b255c9e9..f648f0559a 100644 --- a/src/test1.c +++ b/src/test1.c @@ -7369,6 +7369,41 @@ static int SQLITE_TCLAPI test_dbconfig_maindbname_icecube( } } +/* +** Usage: sqlite3_wal_info DB DBNAME +*/ +static int SQLITE_TCLAPI test_wal_info( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + sqlite3 *db; + char *zName; + unsigned int nPrior; + unsigned int nFrame; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zName = Tcl_GetString(objv[2]); + + rc = sqlite3_wal_info(db, zName, &nPrior, &nFrame); + if( rc!=SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); + return TCL_ERROR; + }else{ + Tcl_Obj *pNew = Tcl_NewObj(); + Tcl_ListObjAppendElement(interp, pNew, Tcl_NewWideIntObj((i64)nPrior)); + Tcl_ListObjAppendElement(interp, pNew, Tcl_NewWideIntObj((i64)nFrame)); + Tcl_SetObjResult(interp, pNew); + } + return TCL_OK; +} + /* ** Register commands with the TCL interpreter. */ @@ -7639,6 +7674,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 }, #endif { "sqlite3_delete_database", test_delete_database, 0 }, + { "sqlite3_wal_info", test_wal_info, 0 }, }; static int bitmask_size = sizeof(Bitmask)*8; static int longdouble_size = sizeof(LONGDOUBLE_TYPE); diff --git a/src/wal.c b/src/wal.c index c56b1365cb..73b5f7ad82 100644 --- a/src/wal.c +++ b/src/wal.c @@ -446,6 +446,7 @@ struct Wal { WalIndexHdr hdr; /* Wal-index header for current transaction */ u32 minFrame; /* Ignore wal frames before this one */ u32 iReCksum; /* On commit, recalculate checksums from here */ + u32 nPriorFrame; /* For sqlite3WalInfo() */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ #ifdef SQLITE_DEBUG @@ -2507,6 +2508,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ testcase( rc==SQLITE_PROTOCOL ); testcase( rc==SQLITE_OK ); + pWal->nPriorFrame = pWal->hdr.mxFrame; #ifdef SQLITE_ENABLE_SNAPSHOT if( rc==SQLITE_OK ){ if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ @@ -2948,6 +2950,7 @@ int sqlite3WalLockForCommit(Wal *pWal, PgHdr *pPage1, Bitvec *pAllRead){ } } + pWal->nPriorFrame = pWal->hdr.mxFrame; return rc; } @@ -3118,6 +3121,7 @@ static int walRestartLog(Wal *pWal){ ** to handle if this transaction is rolled back. */ walRestartHdr(pWal, salt1); walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); + pWal->nPriorFrame = 0; }else if( rc!=SQLITE_BUSY ){ return rc; } @@ -3759,4 +3763,16 @@ sqlite3_file *sqlite3WalFile(Wal *pWal){ return pWal->pWalFd; } +/* +** Return the values required by sqlite3_wal_info(). +*/ +int sqlite3WalInfo(Wal *pWal, u32 *pnPrior, u32 *pnFrame){ + int rc = SQLITE_OK; + if( pWal ){ + *pnFrame = pWal->hdr.mxFrame; + *pnPrior = pWal->nPriorFrame; + } + return rc; +} + #endif /* #ifndef SQLITE_OMIT_WAL */ diff --git a/src/wal.h b/src/wal.h index 5243bca162..b636d57a0a 100644 --- a/src/wal.h +++ b/src/wal.h @@ -153,5 +153,8 @@ int sqlite3WalFramesize(Wal *pWal); /* Return the sqlite3_file object for the WAL file */ sqlite3_file *sqlite3WalFile(Wal *pWal); +/* sqlite3_wal_info() data */ +int sqlite3WalInfo(Wal *pWal, u32 *pnPrior, u32 *pnFrame); + #endif /* ifndef SQLITE_OMIT_WAL */ #endif /* SQLITE_WAL_H */ diff --git a/test/concurrent2.test b/test/concurrent2.test index e0600ff9c3..6a9a40d16a 100644 --- a/test/concurrent2.test +++ b/test/concurrent2.test @@ -548,5 +548,34 @@ do_multiclient_test tn { } {} } +do_multiclient_test tn { + do_test 11.$tn.1 { + sql1 { + PRAGMA journal_mode = wal; + CREATE TABLE t1(a); + } + } {wal} + + do_test 11.$tn.2 { + code1 { sqlite3_wal_info db main } + } {0 2} + + do_test 11.$tn.3 { + sql1 { INSERT INTO t1 VALUES(1) } + code1 { sqlite3_wal_info db main } + } {2 3} + + do_test 11.$tn.4 { + sql2 { INSERT INTO t1 VALUES(2) } + code2 { sqlite3_wal_info db2 main } + } {3 4} + + do_test 11.$tn.5 { + sql1 { PRAGMA wal_checkpoint } + sql2 { INSERT INTO t1 VALUES(3) } + code2 { sqlite3_wal_info db2 main } + } {0 1} +} + finish_test