-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
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
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
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
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
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
-8a56de5b9c6f4522000f8d991373490b67b9e9d97f03c1ca2cf32816d84789ef
\ No newline at end of file
+bb6f2b8b486c225043bc64e5f74ff6bbad6c5d1f337f0c81eeb6172b087bb943
\ No newline at end of file
/*
** 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);
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 */
}
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;
sqlite3BtreeEnter(p);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
- rc = autoVacuumCommit(pBt);
+ rc = autoVacuumCommit(p);
if( rc!=SQLITE_OK ){
sqlite3BtreeLeave(p);
return rc;
/* 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
** 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);
}
#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().
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
/* 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*));
};
/*
#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)
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 */
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.
{ "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 },
#
#***********************************************************************
# 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
--- /dev/null
+# 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