summaryrefslogtreecommitdiffstats
path: root/Plugins/DbSqliteWx/rekeyvacuum.c
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2021-12-17 07:06:30 -0500
committerLibravatarUnit 193 <unit193@unit193.net>2021-12-17 07:06:30 -0500
commit1fdc150116cad39aae5c5da407c3312b47a59e3a (patch)
tree123c79a4d7ad2d45781ba03ce939f7539fb428d8 /Plugins/DbSqliteWx/rekeyvacuum.c
parentfeda8a7db8d1d7c5439aa8f8feef7cc0dd2b59a0 (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.c273
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;
-}
-