Add the sqlite3_autovacuum_pages() interface.

FossilOrigin-Name: ca2703c339f76101f25051a2ed380398b018782883bfee68b5f2d69a1de9091a
This commit is contained in:
drh 2021-10-30 20:22:32 +00:00
commit d4cc4d02cb
11 changed files with 346 additions and 29 deletions

View File

@ -1,5 +1,5 @@
C Fix\san\sincorrect\sassert()\sstatement\sin\ssqlite3GenerateConstraintChecks().\ndbsqlfuzz\s4190cff310aeab359a55f354e560db95d3a6f47d
D 2021-10-30T18:17:59.636
C Add\sthe\ssqlite3_autovacuum_pages()\sinterface.
D 2021-10-30T20:22:32.855
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 004c647dfb5332ee4b56385f3ac264ebea781cb00f7a1561a48f4a45b78fed61
F src/btree.c 2c8a52a7fd84b1aec4a79e7861b6368aecbf011a43247cc7d9a2946c7f0ae5ea
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7
F src/build.c 8bdda90f9b1189c7b0813575171b3c6b2d74b3ade57c11cb4383776781ea9335
@ -512,8 +512,8 @@ F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3f2892de7820d8e0b34a90bff8a3e2f879bc528683fa2ebb9e779ae56b64b741
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 185e4b905c3a399e9376597a04cf668f6f992513290978ac978cf4991954d89f
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 317bbdf926ec7c391fb00bcaa1f82799836a1151568bd9d343f43c2cdf1a48b9
F src/sqlite3ext.h d8f6f67ae9ad990a70dd03c093bcdc8883e159ff4bfd16a496f8fb80c6840b5a
F src/sqliteInt.h 02f7ccc971d67d8641707f219b9c304113d43a9a128b73a39d1fcaa036c885b7
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 bd1c3c2637db35c0a69513e008c0e6a177b360ccae7689e0bf69f15b55e24bae
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,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 8ba73b3cadb72ffcf176d19f9f946c1b90b224e5ab9a0e9eb9a83affa7476d23
R b527768918a8e4077efc0dd96c45874f
P 623c0d086bda135c49bfc238c31498facdcbe8ecc7659cc1af61594df0c6e899 60cd9da9258e0b701d4bb3f9c91c5d0a12e925b9b937df619b09f33a287b4a33
R c2365c0f257a6e1be84889548b719edd
T +closed 60cd9da9258e0b701d4bb3f9c91c5d0a12e925b9b937df619b09f33a287b4a33
U drh
Z ea8a849e6713aaef4d0e7842051d5f8f
Z 46db034af6d2112bb92acfe1ff1351cf

View File

@ -1 +1 @@
623c0d086bda135c49bfc238c31498facdcbe8ecc7659cc1af61594df0c6e899
ca2703c339f76101f25051a2ed380398b018782883bfee68b5f2d69a1de9091a

View File

@ -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;

View File

@ -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

View File

@ -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().

View File

@ -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>
** &nbsp; unsigned int demonstration_autovac_pages_callback(
** &nbsp; void *pClientData,
** &nbsp; const char *zSchema,
** &nbsp; unsigned int nDbPage,
** &nbsp; unsigned int nFreePage,
** &nbsp; unsigned int nBytePerPage
** &nbsp; ){
** &nbsp; return nFreePage;
** &nbsp; }
** </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

View File

@ -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)

View File

@ -1566,6 +1566,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 */

View File

@ -8233,6 +8233,96 @@ 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;
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;
if( zScript ){
size_t nScript = strlen(zScript);
pData = sqlite3_malloc64( sizeof(*pData) + nScript + 1 );
if( pData==0 ){
Tcl_AppendResult(interp, "out of memory", (void*)0);
return TCL_ERROR;
}
pData->interp = interp;
pData->zScript = (char*)&pData[1];
memcpy(pData->zScript, zScript, nScript+1);
rc = sqlite3_autovacuum_pages(db,test_autovacuum_pages_callback,
pData, sqlite3_free);
}else{
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 +8614,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 },

View File

@ -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
View 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