diff options
| author | 2021-12-17 07:06:30 -0500 | |
|---|---|---|
| committer | 2021-12-17 07:06:30 -0500 | |
| commit | 1fdc150116cad39aae5c5da407c3312b47a59e3a (patch) | |
| tree | 123c79a4d7ad2d45781ba03ce939f7539fb428d8 /Plugins/DbSqliteWx/rekeyvacuum.c | |
| parent | feda8a7db8d1d7c5439aa8f8feef7cc0dd2b59a0 (diff) | |
New upstream version 3.3.3+dfsg1.upstream/3.3.3+dfsg1
Diffstat (limited to 'Plugins/DbSqliteWx/rekeyvacuum.c')
| -rw-r--r-- | Plugins/DbSqliteWx/rekeyvacuum.c | 273 |
1 files changed, 0 insertions, 273 deletions
diff --git a/Plugins/DbSqliteWx/rekeyvacuum.c b/Plugins/DbSqliteWx/rekeyvacuum.c deleted file mode 100644 index 1fd9aed..0000000 --- a/Plugins/DbSqliteWx/rekeyvacuum.c +++ /dev/null @@ -1,273 +0,0 @@ -/* -** 2018-02-24 -** -** 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 contains an adjusted version of function wx_sqlite3RunVacuum -** to allow reducing or removing reserved page space. -** For this purpose the number of reserved bytes per page for the target -** database is passed as a parameter to the adjusted function. -** -** NOTE: When upgrading to a new version of SQLite3 it is strongly -** recommended to check the original function wx_sqlite3RunVacuum of the -** new version for relevant changes, and to incorporate them in the -** adjusted function below. -** -** The code below is based on SQLite version 3.24.0 - check when updating SQLite. -*/ - -/* -** This routine implements the OP_Vacuum opcode of the VDBE. -*/ -/* CHANGE 1 of 3: Add function parameter nRes */ -SQLITE_PRIVATE int wx_sqlite3RunVacuumForRekey(char **pzErrMsg, wx_sqlite3 *db, int iDb, int nRes){ - int rc = SQLITE_OK; /* Return code from service routines */ - Btree *pMain; /* The database being vacuumed */ - Btree *pTemp; /* The temporary database we vacuum into */ - u16 saved_mDbFlags; /* Saved value of db->mDbFlags */ - u32 saved_flags; /* Saved value of db->flags */ - int saved_nChange; /* Saved value of db->nChange */ - int saved_nTotalChange; /* Saved value of db->nTotalChange */ - u8 saved_mTrace; /* Saved trace settings */ - Db *pDb = 0; /* Database to detach at end of vacuum */ - int isMemDb; /* True if vacuuming a :memory: database */ - /* CHANGE 2 of 3: Do not define local variable nRes */ - /*int nRes;*/ /* Bytes of reserved space at the end of each page */ - int nDb; /* Number of attached databases */ - const char *zDbMain; /* Schema name of database to vacuum */ - - if (!db->autoCommit) { - wx_sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); - return SQLITE_ERROR; - } - if (db->nVdbeActive>1) { - wx_sqlite3SetString(pzErrMsg, db, "cannot VACUUM - SQL statements in progress"); - return SQLITE_ERROR; - } - - /* Save the current value of the database flags so that it can be - ** restored before returning. Then set the writable-schema flag, and - ** disable CHECK and foreign key constraints. */ - saved_flags = db->flags; - saved_mDbFlags = db->mDbFlags; - saved_nChange = db->nChange; - saved_nTotalChange = db->nTotalChange; - saved_mTrace = db->mTrace; - db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; - db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; - db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows); - db->mTrace = 0; - - zDbMain = db->aDb[iDb].zDbSName; - pMain = db->aDb[iDb].pBt; - isMemDb = wx_sqlite3PagerIsMemdb(wx_sqlite3BtreePager(pMain)); - - /* Attach the temporary database as 'vacuum_db'. The synchronous pragma - ** can be set to 'off' for this file, as it is not recovered if a crash - ** occurs anyway. The integrity of the database is maintained by a - ** (possibly synchronous) transaction opened on the main database before - ** wx_sqlite3BtreeCopyFile() is called. - ** - ** An optimisation would be to use a non-journaled pager. - ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but - ** that actually made the VACUUM run slower. Very little journalling - ** actually occurs when doing a vacuum since the vacuum_db is initially - ** empty. Only the journal header is written. Apparently it takes more - ** time to parse and run the PRAGMA to turn journalling off than it does - ** to write the journal header file. - */ - nDb = db->nDb; - rc = execSql(db, pzErrMsg, "ATTACH''AS vacuum_db"); - if (rc != SQLITE_OK) goto end_of_vacuum; - assert((db->nDb - 1) == nDb); - pDb = &db->aDb[nDb]; - assert(strcmp(pDb->zDbSName, "vacuum_db") == 0); - pTemp = pDb->pBt; - - /* The call to execSql() to attach the temp database has left the file - ** locked (as there was more than one active statement when the transaction - ** to read the schema was concluded. Unlock it here so that this doesn't - ** cause problems for the call to BtreeSetPageSize() below. */ - wx_sqlite3BtreeCommit(pTemp); - - /* CHANGE 3 of 3: Do not call wx_sqlite3BtreeGetOptimalReserve */ - /* nRes = wx_sqlite3BtreeGetOptimalReserve(pMain); */ - - /* A VACUUM cannot change the pagesize of an encrypted database. */ -#ifdef SQLITE_HAS_CODEC - if (db->nextPagesize) { - extern void wx_sqlite3CodecGetKey(wx_sqlite3*, int, void**, int*); - int nKey; - char *zKey; - wx_sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey); - if (nKey) db->nextPagesize = 0; - } -#endif - - wx_sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); - wx_sqlite3BtreeSetSpillSize(pTemp, wx_sqlite3BtreeSetSpillSize(pMain, 0)); - wx_sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF | PAGER_CACHESPILL); - - /* Begin a transaction and take an exclusive lock on the main database - ** file. This is done before the wx_sqlite3BtreeGetPageSize(pMain) call below, - ** to ensure that we do not try to change the page-size on a WAL database. - */ - rc = execSql(db, pzErrMsg, "BEGIN"); - if (rc != SQLITE_OK) goto end_of_vacuum; - rc = wx_sqlite3BtreeBeginTrans(pMain, 2); - if (rc != SQLITE_OK) goto end_of_vacuum; - - /* Do not attempt to change the page size for a WAL database */ - if (wx_sqlite3PagerGetJournalMode(wx_sqlite3BtreePager(pMain)) - == PAGER_JOURNALMODE_WAL) { - db->nextPagesize = 0; - } - - if (wx_sqlite3BtreeSetPageSize(pTemp, wx_sqlite3BtreeGetPageSize(pMain), nRes, 0) - || (!isMemDb && wx_sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0)) - || NEVER(db->mallocFailed) - ) { - rc = SQLITE_NOMEM_BKPT; - goto end_of_vacuum; - } - -#ifndef SQLITE_OMIT_AUTOVACUUM - wx_sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac >= 0 ? db->nextAutovac : - wx_sqlite3BtreeGetAutoVacuum(pMain)); -#endif - - /* Query the schema of the main database. Create a mirror schema - ** in the temporary database. - */ - db->init.iDb = nDb; /* force new CREATE statements into vacuum_db */ - rc = execSqlF(db, pzErrMsg, - "SELECT sql FROM \"%w\".sqlite_master" - " WHERE type='table'AND name<>'sqlite_sequence'" - " AND coalesce(rootpage,1)>0", - zDbMain - ); - if (rc != SQLITE_OK) goto end_of_vacuum; - rc = execSqlF(db, pzErrMsg, - "SELECT sql FROM \"%w\".sqlite_master" - " WHERE type='index'", - zDbMain - ); - if (rc != SQLITE_OK) goto end_of_vacuum; - db->init.iDb = 0; - - /* Loop through the tables in the main database. For each, do - ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy - ** the contents to the temporary database. - */ - rc = execSqlF(db, pzErrMsg, - "SELECT'INSERT INTO vacuum_db.'||quote(name)" - "||' SELECT*FROM\"%w\".'||quote(name)" - "FROM vacuum_db.sqlite_master " - "WHERE type='table'AND coalesce(rootpage,1)>0", - zDbMain - ); - assert((db->mDbFlags & DBFLAG_Vacuum) != 0); - db->mDbFlags &= ~DBFLAG_Vacuum; - if (rc != SQLITE_OK) goto end_of_vacuum; - - /* Copy the triggers, views, and virtual tables from the main database - ** over to the temporary database. None of these objects has any - ** associated storage, so all we have to do is copy their entries - ** from the SQLITE_MASTER table. - */ - rc = execSqlF(db, pzErrMsg, - "INSERT INTO vacuum_db.sqlite_master" - " SELECT*FROM \"%w\".sqlite_master" - " WHERE type IN('view','trigger')" - " OR(type='table'AND rootpage=0)", - zDbMain - ); - if (rc) goto end_of_vacuum; - - /* At this point, there is a write transaction open on both the - ** vacuum database and the main database. Assuming no error occurs, - ** both transactions are closed by this block - the main database - ** transaction by wx_sqlite3BtreeCopyFile() and the other by an explicit - ** call to wx_sqlite3BtreeCommit(). - */ - { - u32 meta; - int i; - - /* This array determines which meta meta values are preserved in the - ** vacuum. Even entries are the meta value number and odd entries - ** are an increment to apply to the meta value after the vacuum. - ** The increment is used to increase the schema cookie so that other - ** connections to the same database will know to reread the schema. - */ - static const unsigned char aCopy[] = { - BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */ - BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */ - BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ - BTREE_USER_VERSION, 0, /* Preserve the user version */ - BTREE_APPLICATION_ID, 0, /* Preserve the application id */ - }; - - assert(1 == wx_sqlite3BtreeIsInTrans(pTemp)); - assert(1 == wx_sqlite3BtreeIsInTrans(pMain)); - - /* Copy Btree meta values */ - for (i = 0; i<ArraySize(aCopy); i += 2) { - /* GetMeta() and UpdateMeta() cannot fail in this context because - ** we already have page 1 loaded into cache and marked dirty. */ - wx_sqlite3BtreeGetMeta(pMain, aCopy[i], &meta); - rc = wx_sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta + aCopy[i + 1]); - if (NEVER(rc != SQLITE_OK)) goto end_of_vacuum; - } - - rc = wx_sqlite3BtreeCopyFile(pMain, pTemp); - if (rc != SQLITE_OK) goto end_of_vacuum; - rc = wx_sqlite3BtreeCommit(pTemp); - if (rc != SQLITE_OK) goto end_of_vacuum; -#ifndef SQLITE_OMIT_AUTOVACUUM - wx_sqlite3BtreeSetAutoVacuum(pMain, wx_sqlite3BtreeGetAutoVacuum(pTemp)); -#endif - } - - assert(rc == SQLITE_OK); - rc = wx_sqlite3BtreeSetPageSize(pMain, wx_sqlite3BtreeGetPageSize(pTemp), nRes, 1); - -end_of_vacuum: - /* Restore the original value of db->flags */ - db->init.iDb = 0; - db->mDbFlags = saved_mDbFlags; - db->flags = saved_flags; - db->nChange = saved_nChange; - db->nTotalChange = saved_nTotalChange; - db->mTrace = saved_mTrace; - wx_sqlite3BtreeSetPageSize(pMain, -1, -1, 1); - - /* Currently there is an SQL level transaction open on the vacuum - ** database. No locks are held on any other files (since the main file - ** was committed at the btree level). So it safe to end the transaction - ** by manually setting the autoCommit flag to true and detaching the - ** vacuum database. The vacuum_db journal file is deleted when the pager - ** is closed by the DETACH. - */ - db->autoCommit = 1; - - if (pDb) { - wx_sqlite3BtreeClose(pDb->pBt); - pDb->pBt = 0; - pDb->pSchema = 0; - } - - /* This both clears the schemas and reduces the size of the db->aDb[] - ** array. */ - wx_sqlite3ResetAllSchemasOfConnection(db); - - return rc; -} - |
