mirror of
https://github.com/sqlite/sqlite.git
synced 2024-11-22 03:40:55 +01:00
Demostrate a prototype sqlite3_autovacuum_pages() interface.
FossilOrigin-Name: bb6f2b8b486c225043bc64e5f74ff6bbad6c5d1f337f0c81eeb6172b087bb943
This commit is contained in:
parent
220f0d6f8e
commit
1bbfc6744c
30
manifest
30
manifest
@ -1,5 +1,5 @@
|
||||
C Protect\sthe\sWhereTerm.u\sunion\susing\snearby\sassert()s\sand/or\sbranches.
|
||||
D 2021-10-15T17:06:16.174
|
||||
C Demostrate\sa\sprototype\ssqlite3_autovacuum_pages()\sinterface.
|
||||
D 2021-10-15T23:02:27.945
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -490,7 +490,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
|
||||
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
|
||||
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
|
||||
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c 35782a608c940e219a01cf9d84de55e11668a42ede3b7b2d2fb4a6edb52e97e5
|
||||
F src/btree.c faa3248f55eb34269874273a85e682e25dc4a3aa50334ec80564c6fc1e394e23
|
||||
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
|
||||
F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0
|
||||
F src/build.c f70d6375ea5b78daac5b1d24eab53ed7b81c3e68a17dff9581c50c0c06180e00
|
||||
@ -512,8 +512,8 @@ F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c b32e2dcbca838cb8acd4777a59243db4bcea53089e3181b0ea3e4dc75b43aeff
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 0aa9e7f08e168e3874cb54984408e3976dafdf5616d511952c425b5ac088ea3e
|
||||
F src/main.c bfe067d61ebbd0e6eb023f1fb6b353021e621cf1657e061d629064a740bfbf6f
|
||||
F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c
|
||||
F src/main.c 546dd2418c4f5d59aced76c68e55290735feb420ee305051fbd55ab8fff0d255
|
||||
F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
@ -551,15 +551,15 @@ F src/resolve.c ae65c88f5d0d4bc0052b203773d407efa2387c2bd6b202f87178006c7bb8632c
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c 32d25b5af6c708aa63373c78c2e59681910387a7a78c08ec3086cadc77d41627
|
||||
F src/shell.c.in e80fe5118fc3b942c1becc67ebfca6a887dbab9295e0bd5b6da61c4375baa637
|
||||
F src/sqlite.h.in f0c1ecb5af508aa8e970cd8bc0ec851e6c380b81825038d458846c2fcdfcef50
|
||||
F src/sqlite.h.in 99786216caf1c57aa3d70f95a7f84566dff6a9eeb50174799ea3b387eafd2a22
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
|
||||
F src/sqliteInt.h 642c17df9e5a3517db452ac73a2b953143449a8bc2f6570c60de455a89a8571c
|
||||
F src/sqlite3ext.h d8f6f67ae9ad990a70dd03c093bcdc8883e159ff4bfd16a496f8fb80c6840b5a
|
||||
F src/sqliteInt.h 896cc476bb814ad1f893715e7e174dede81c94b4fed4073de0e76b68f11bf827
|
||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 428e813dabf82804bc13196af35a0c3c6ef4347fe557fa6717c5c66bba6e8520
|
||||
F src/test1.c 63761c2be2607f1b425fde991beda48aed384f8d67f2b4ee549174c88b433009
|
||||
F src/test1.c f69bb12219d440b3f6ed382136d9aabe82a146532143afcb3b583d810bd9a57b
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
|
||||
@ -705,7 +705,8 @@ F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
|
||||
F test/autoindex3.test 2d13958a5617e987624a428d7aed91bf51f322b49b476e3573fadec697ce6da5
|
||||
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
|
||||
F test/autoindex5.test 2ee94f033b87ca0160e08d81034c507aff8e230df2627f0304fa309b2fee19a3
|
||||
F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9
|
||||
F test/autovacuum.test 00671369bbf96c6a49989a9425f5b78b94075d6a4b031e5e00000c2c32f365df
|
||||
F test/autovacuum2.test 76f7eb4fe6a6bf6d33a196a7141dba98886d2fb53a268d7feca285d5da4759d7
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avfs.test 0c3a38e03cccb0fc3127838462dc05dc3f4c1480d770c084b388304c25de3652
|
||||
F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e
|
||||
@ -1929,7 +1930,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 7b8ea2298927fd34f27b3345add3ce751ed728387fe3d9207b601ba6449d5af9
|
||||
R f8f24b4e90ad954c123bdee77c1d3c2d
|
||||
P 8a56de5b9c6f4522000f8d991373490b67b9e9d97f03c1ca2cf32816d84789ef
|
||||
R f133145eb98f519a7c135450fb3d5209
|
||||
T *branch * autovacuum-pages-callback
|
||||
T *sym-autovacuum-pages-callback *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 0a05442607cc8af1d2c0566962c413f4
|
||||
Z ead09303b823a782b5e7be4edc1ec190
|
||||
|
@ -1 +1 @@
|
||||
8a56de5b9c6f4522000f8d991373490b67b9e9d97f03c1ca2cf32816d84789ef
|
||||
bb6f2b8b486c225043bc64e5f74ff6bbad6c5d1f337f0c81eeb6172b087bb943
|
53
src/btree.c
53
src/btree.c
@ -3939,16 +3939,18 @@ int sqlite3BtreeIncrVacuum(Btree *p){
|
||||
/*
|
||||
** This routine is called prior to sqlite3PagerCommit when a transaction
|
||||
** is committed for an auto-vacuum database.
|
||||
**
|
||||
** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
|
||||
** the database file should be truncated to during the commit process.
|
||||
** i.e. the database has been reorganized so that only the first *pnTrunc
|
||||
** pages are in use.
|
||||
*/
|
||||
static int autoVacuumCommit(BtShared *pBt){
|
||||
static int autoVacuumCommit(Btree *p){
|
||||
int rc = SQLITE_OK;
|
||||
Pager *pPager = pBt->pPager;
|
||||
VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); )
|
||||
Pager *pPager;
|
||||
BtShared *pBt;
|
||||
sqlite3 *db;
|
||||
VVA_ONLY( int nRef );
|
||||
|
||||
assert( p!=0 );
|
||||
pBt = p->pBt;
|
||||
pPager = pBt->pPager;
|
||||
VVA_ONLY( nRef = sqlite3PagerRefcount(pPager); )
|
||||
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
invalidateAllOverflowCache(pBt);
|
||||
@ -3956,6 +3958,7 @@ static int autoVacuumCommit(BtShared *pBt){
|
||||
if( !pBt->incrVacuum ){
|
||||
Pgno nFin; /* Number of pages in database after autovacuuming */
|
||||
Pgno nFree; /* Number of pages on the freelist initially */
|
||||
Pgno nVac; /* Number of pages to vacuum */
|
||||
Pgno iFree; /* The next page to be freed */
|
||||
Pgno nOrig; /* Database size before freeing */
|
||||
|
||||
@ -3969,18 +3972,42 @@ static int autoVacuumCommit(BtShared *pBt){
|
||||
}
|
||||
|
||||
nFree = get4byte(&pBt->pPage1->aData[36]);
|
||||
nFin = finalDbSize(pBt, nOrig, nFree);
|
||||
db = p->db;
|
||||
if( db->xAutovacPages ){
|
||||
int iDb;
|
||||
for(iDb=0; ALWAYS(iDb<db->nDb); iDb++){
|
||||
if( db->aDb[iDb].pBt==p ) break;
|
||||
}
|
||||
nVac = db->xAutovacPages(
|
||||
db->pAutovacPagesArg,
|
||||
db->aDb[iDb].zDbSName,
|
||||
nOrig,
|
||||
nFree,
|
||||
pBt->pageSize
|
||||
);
|
||||
if( nVac>nFree ){
|
||||
nVac = nFree;
|
||||
}
|
||||
if( nVac==0 ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}else{
|
||||
nVac = nFree;
|
||||
}
|
||||
nFin = finalDbSize(pBt, nOrig, nVac);
|
||||
if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
|
||||
if( nFin<nOrig ){
|
||||
rc = saveAllCursors(pBt, 0, 0);
|
||||
}
|
||||
for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
|
||||
rc = incrVacuumStep(pBt, nFin, iFree, 1);
|
||||
rc = incrVacuumStep(pBt, nFin, iFree, nVac==nFree);
|
||||
}
|
||||
if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
|
||||
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
||||
put4byte(&pBt->pPage1->aData[32], 0);
|
||||
put4byte(&pBt->pPage1->aData[36], 0);
|
||||
if( nVac==nFree ){
|
||||
put4byte(&pBt->pPage1->aData[32], 0);
|
||||
put4byte(&pBt->pPage1->aData[36], 0);
|
||||
}
|
||||
put4byte(&pBt->pPage1->aData[28], nFin);
|
||||
pBt->bDoTruncate = 1;
|
||||
pBt->nPage = nFin;
|
||||
@ -4031,7 +4058,7 @@ int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){
|
||||
sqlite3BtreeEnter(p);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum ){
|
||||
rc = autoVacuumCommit(pBt);
|
||||
rc = autoVacuumCommit(p);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3BtreeLeave(p);
|
||||
return rc;
|
||||
|
@ -483,6 +483,8 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
/* Version 3.36.1 and later */
|
||||
sqlite3_changes64,
|
||||
sqlite3_total_changes64,
|
||||
/* Version 3.37.0 and later */
|
||||
sqlite3_autovacuum_pages,
|
||||
};
|
||||
|
||||
/* True if x is the directory separator character
|
||||
|
31
src/main.c
31
src/main.c
@ -1403,6 +1403,9 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
||||
** structure?
|
||||
*/
|
||||
sqlite3DbFree(db, db->aDb[1].pSchema);
|
||||
if( db->xAutovacDestr ){
|
||||
db->xAutovacDestr(db->pAutovacPagesArg);
|
||||
}
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
db->eOpenState = SQLITE_STATE_CLOSED;
|
||||
sqlite3_mutex_free(db->mutex);
|
||||
@ -2304,6 +2307,34 @@ void *sqlite3_preupdate_hook(
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
|
||||
|
||||
/*
|
||||
** Register a function to be invoked prior to each autovacuum that
|
||||
** determines the number of pages to vacuum.
|
||||
*/
|
||||
int sqlite3_autovacuum_pages(
|
||||
sqlite3 *db, /* Attach the hook to this database */
|
||||
unsigned int (*xCallback)(void*,const char*,u32,u32,u32),
|
||||
void *pArg, /* Argument to the function */
|
||||
void (*xDestructor)(void*) /* Destructor for pArg */
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
if( xDestructor ) xDestructor(pArg);
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( db->xAutovacDestr ){
|
||||
db->xAutovacDestr(db->pAutovacPagesArg);
|
||||
}
|
||||
db->xAutovacPages = xCallback;
|
||||
db->pAutovacPagesArg = pArg;
|
||||
db->xAutovacDestr = xDestructor;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
/*
|
||||
** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
|
||||
|
@ -6406,6 +6406,72 @@ sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
|
||||
void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
|
||||
void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Autovacuum Compaction Amount Callback
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
|
||||
** function C that is invoked prior to each autovacuum of the database
|
||||
** file. ^The callback is passed a copy of the generic data pointer (P),
|
||||
** the schema-name of the attached database that is being autovacuumed,
|
||||
** the the size of the database file in pages, the number of free pages,
|
||||
** and the number of bytes per page, respectively. The callback should
|
||||
** return the number of free pages that should be removed by the
|
||||
** autovacuum. ^If the callback returns zero, then no autovacuum happens.
|
||||
** ^If the value returned is greater than or equal to the number of
|
||||
** free pages, then a complete autovacuum happens.
|
||||
**
|
||||
** <p>^If there are multiple ATTACH-ed database files that are being
|
||||
** modified as part of a transaction commit, then the autovacuum pages
|
||||
** callback is invoked separately for each file.
|
||||
**
|
||||
** <p><b>The callback is not reentrant.</b> The callback function should
|
||||
** not attempt to invoke any other SQLite interface. If it does, bad
|
||||
** things may happen, including segmentation faults and corrupt database
|
||||
** files. The callback function should be a simple function that
|
||||
** does some arithmetic on its input parameters and returns a result.
|
||||
**
|
||||
** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional
|
||||
** destructor for the P parameter. ^If X is not NULL, then X(P) is
|
||||
** invoked whenever the database connection closes or when the callback
|
||||
** is overwritten by another invocation of sqlite3_autovacuum_pages().
|
||||
**
|
||||
** <p>^There is only one autovacuum pages callback per database connection.
|
||||
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
|
||||
** previous invocations for that database connection. ^If the callback
|
||||
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
|
||||
** then the autovacuum steps callback is cancelled. The return value
|
||||
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
|
||||
** be some other error code if something goes wrong. The current
|
||||
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
|
||||
** return codes might be added in future releases.
|
||||
**
|
||||
** <p>If no autovacuum pages callback is specified (the usual case) or
|
||||
** a NULL pointer is provided for the callback,
|
||||
** then the default behavior is to vacuum all free pages. So, in other
|
||||
** words, the default behavior is the same as if the callback function
|
||||
** were something like this:
|
||||
**
|
||||
** <blockquote><pre>
|
||||
** unsigned int demonstration_autovac_pages_callback(
|
||||
** void *pClientData,
|
||||
** const char *zSchema,
|
||||
** unsigned int nDbPage,
|
||||
** unsigned int nFreePage,
|
||||
** unsigned int nBytePerPage
|
||||
** ){
|
||||
** return nFreePage;
|
||||
** }
|
||||
** </pre></blockquote>
|
||||
*/
|
||||
int sqlite3_autovacuum_pages(
|
||||
sqlite3 *db,
|
||||
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
|
||||
void*,
|
||||
void(*)(void*)
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Data Change Notification Callbacks
|
||||
** METHOD: sqlite3
|
||||
|
@ -340,6 +340,10 @@ struct sqlite3_api_routines {
|
||||
/* Version 3.36.1 and later */
|
||||
sqlite3_int64 (*changes64)(sqlite3*);
|
||||
sqlite3_int64 (*total_changes64)(sqlite3*);
|
||||
/* Version 3.37.0 and later */
|
||||
int (*autovacuum_pages)(sqlite3*,
|
||||
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
|
||||
void*, void(*)(void*));
|
||||
};
|
||||
|
||||
/*
|
||||
@ -646,6 +650,11 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_database_file_object sqlite3_api->database_file_object
|
||||
/* Version 3.34.0 and later */
|
||||
#define sqlite3_txn_state sqlite3_api->txn_state
|
||||
/* Version 3.36.1 and later */
|
||||
#define sqlite3_changes64 sqlite3_api->changes64
|
||||
#define sqlite3_total_changes64 sqlite3_api->total_changes64
|
||||
* Version 3.37.0 and later */
|
||||
#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
@ -1565,6 +1565,9 @@ struct sqlite3 {
|
||||
void (*xRollbackCallback)(void*); /* Invoked at every commit. */
|
||||
void *pUpdateArg;
|
||||
void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
|
||||
void *pAutovacPagesArg; /* Client argument to autovac_pages */
|
||||
void (*xAutovacDestr)(void*); /* Destructor for pAutovacPAgesArg */
|
||||
unsigned int (*xAutovacPages)(void*,const char*,u32,u32,u32);
|
||||
Parse *pParse; /* Current parse */
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
void *pPreUpdateArg; /* First argument to xPreUpdateCallback */
|
||||
|
93
src/test1.c
93
src/test1.c
@ -8233,6 +8233,98 @@ static int SQLITE_TCLAPI test_decode_hexdb(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Client data for the autovacuum_pages callback.
|
||||
*/
|
||||
struct AutovacPageData {
|
||||
Tcl_Interp *interp;
|
||||
char *zScript;
|
||||
};
|
||||
typedef struct AutovacPageData AutovacPageData;
|
||||
|
||||
/*
|
||||
** Callback functions for sqlite3_autovacuum_pages
|
||||
*/
|
||||
static unsigned int test_autovacuum_pages_callback(
|
||||
void *pClientData,
|
||||
const char *zSchema,
|
||||
unsigned int nFilePages,
|
||||
unsigned int nFreePages,
|
||||
unsigned int nBytePerPage
|
||||
){
|
||||
AutovacPageData *pData = (AutovacPageData*)pClientData;
|
||||
Tcl_DString str;
|
||||
unsigned int x;
|
||||
char zBuf[100];
|
||||
Tcl_DStringInit(&str);
|
||||
Tcl_DStringAppend(&str, pData->zScript, -1);
|
||||
Tcl_DStringAppendElement(&str, zSchema);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nFilePages);
|
||||
Tcl_DStringAppendElement(&str, zBuf);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nFreePages);
|
||||
Tcl_DStringAppendElement(&str, zBuf);
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nBytePerPage);
|
||||
Tcl_DStringAppendElement(&str, zBuf);
|
||||
Tcl_ResetResult(pData->interp);
|
||||
Tcl_Eval(pData->interp, Tcl_DStringValue(&str));
|
||||
Tcl_DStringFree(&str);
|
||||
x = nFreePages;
|
||||
(void)Tcl_GetIntFromObj(0, Tcl_GetObjResult(pData->interp), (int*)&x);
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_autovacuum_pages DB SCRIPT
|
||||
**
|
||||
** Add an autovacuum-pages callback to database connection DB. The callback
|
||||
** will invoke SCRIPT, after appending parameters.
|
||||
**
|
||||
** If SCRIPT is an empty string or is omitted, then the callback is
|
||||
** cancelled.
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_autovacuum_pages(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
AutovacPageData *pData;
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
const char *zScript;
|
||||
size_t nScript;
|
||||
if( objc!=2 && objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB ?SCRIPT?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
zScript = objc==3 ? Tcl_GetString(objv[2]) : 0;
|
||||
nScript = zScript ? strlen(zScript) : 0;
|
||||
pData = sqlite3_malloc64( sizeof(*pData) + nScript + 1 );
|
||||
if( pData==0 ){
|
||||
Tcl_AppendResult(interp, "out of memory", (void*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pData->interp = interp;
|
||||
if( zScript ){
|
||||
pData->zScript = (char*)&pData[1];
|
||||
memcpy(pData->zScript, zScript, nScript+1);
|
||||
rc = sqlite3_autovacuum_pages(db,test_autovacuum_pages_callback,
|
||||
pData, sqlite3_free);
|
||||
}else{
|
||||
pData->zScript = 0;
|
||||
rc = sqlite3_autovacuum_pages(db, 0, 0, 0);
|
||||
}
|
||||
if( rc ){
|
||||
char zBuf[1000];
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf,
|
||||
"sqlite3_autovacuum_pages() returns %d", rc);
|
||||
Tcl_AppendResult(interp, zBuf, (void*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Register commands with the TCL interpreter.
|
||||
@ -8524,6 +8616,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "atomic_batch_write", test_atomic_batch_write, 0 },
|
||||
{ "sqlite3_mmap_warm", test_mmap_warm, 0 },
|
||||
{ "sqlite3_config_sorterref", test_config_sorterref, 0 },
|
||||
{ "sqlite3_autovacuum_pages", test_autovacuum_pages, 0 },
|
||||
{ "decode_hexdb", test_decode_hexdb, 0 },
|
||||
{ "test_write_db", test_write_db, 0 },
|
||||
{ "sqlite3_register_cksumvfs", test_register_cksumvfs, 0 },
|
||||
|
@ -9,9 +9,8 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the SELECT statement.
|
||||
# focus of this file is testing the autovacuum feature.
|
||||
#
|
||||
# $Id: autovacuum.test,v 1.29 2009/04/06 17:50:03 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
87
test/autovacuum2.test
Normal file
87
test/autovacuum2.test
Normal file
@ -0,0 +1,87 @@
|
||||
# 2021-10-15
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the sqlite3_autovacuum_pages() interface
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# If this build of the library does not support auto-vacuum, omit this
|
||||
# whole file.
|
||||
ifcapable {!autovacuum || !pragma} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Demonstrate basic sqlite3_autovacuum_pages functionality
|
||||
#
|
||||
do_execsql_test autovacuum2-1.0 {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA auto_vacuum=FULL;
|
||||
CREATE TABLE t1(x);
|
||||
VACUUM;
|
||||
INSERT INTO t1(x) VALUES(zeroblob(10000));
|
||||
PRAGMA page_count;
|
||||
} {12}
|
||||
proc autovac_page_callback {schema filesize freesize pagesize} {
|
||||
global autovac_callback_data
|
||||
lappend autovac_callback_data $schema $filesize $freesize $pagesize
|
||||
return [expr {$freesize/2}]
|
||||
}
|
||||
sqlite3_autovacuum_pages db autovac_page_callback
|
||||
set autovac_callback_data {}
|
||||
do_execsql_test autovacuum2-1.1 {
|
||||
BEGIN;
|
||||
DELETE FROM t1;
|
||||
PRAGMA freelist_count;
|
||||
PRAGMA page_count;
|
||||
} {9 12}
|
||||
do_execsql_test autovacuum2-1.2 {
|
||||
COMMIT;
|
||||
} {}
|
||||
do_test autovacuum2-1.3 {
|
||||
set autovac_callback_data
|
||||
} {main 12 9 1024}
|
||||
do_execsql_test autovacuum2-1.4 {
|
||||
PRAGMA freelist_count;
|
||||
PRAGMA page_count;
|
||||
} {5 8}
|
||||
do_execsql_test autovacuum2-1.5 {
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
# Disable the autovacuum-pages callback. Then do any transaction.
|
||||
# The database should shrink to minimal size
|
||||
#
|
||||
sqlite3_autovacuum_pages db
|
||||
do_execsql_test autovacuum2-1.10 {
|
||||
CREATE TABLE t2(x);
|
||||
PRAGMA freelist_count;
|
||||
} {0}
|
||||
|
||||
# Rig the autovacuum-pages callback to always return zero. No
|
||||
# autovacuum will happen.
|
||||
#
|
||||
proc autovac_page_callback_off {schema filesize freesize pagesize} {
|
||||
return 0
|
||||
}
|
||||
sqlite3_autovacuum_pages db autovac_page_callback_off
|
||||
do_execsql_test autovacuum2-1.20 {
|
||||
BEGIN;
|
||||
INSERT INTO t1(x) VALUES(zeroblob(10000));
|
||||
DELETE FROM t1;
|
||||
PRAGMA freelist_count;
|
||||
COMMIT;
|
||||
PRAGMA freelist_count;
|
||||
} {9 9}
|
||||
|
||||
finish_test
|
Loading…
Reference in New Issue
Block a user