mirror of
https://github.com/cuberite/SQLiteCpp.git
synced 2025-08-04 09:46:02 -04:00
Implement Database::backup() (#211)
Easily backup/restore a live DB via the sqlite3_backup_init() API - https://www.sqlite.org/backup.html - https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupinit Use the reference implementation from the documentation
This commit is contained in:
parent
3ba20a3519
commit
514d7d6846
@ -313,7 +313,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create or redefine a SQL function or aggregate in the sqlite database.
|
||||
* @brief Create or redefine a SQL function or aggregate in the sqlite database.
|
||||
*
|
||||
* This is the equivalent of the sqlite3_create_function_v2 command.
|
||||
* @see http://www.sqlite.org/c3ref/create_function.html
|
||||
@ -341,7 +341,7 @@ public:
|
||||
void (*apDestroy)(void *));
|
||||
|
||||
/**
|
||||
* @brief Create or redefine a SQL function or aggregate in the sqlite database.
|
||||
* @brief Create or redefine a SQL function or aggregate in the sqlite database.
|
||||
*
|
||||
* This is the equivalent of the sqlite3_create_function_v2 command.
|
||||
* @see http://www.sqlite.org/c3ref/create_function.html
|
||||
@ -373,7 +373,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load a module into the current sqlite database instance.
|
||||
* @brief Load a module into the current sqlite database instance.
|
||||
*
|
||||
* This is the equivalent of the sqlite3_load_extension call, but additionally enables
|
||||
* module loading support prior to loading the requested module.
|
||||
@ -392,8 +392,8 @@ public:
|
||||
/**
|
||||
* @brief Set the key for the current sqlite database instance.
|
||||
*
|
||||
* This is the equivalent of the sqlite3_key call and should thus be called
|
||||
* directly after opening the database.
|
||||
* This is the equivalent of the sqlite3_key call and should thus be called
|
||||
* directly after opening the database.
|
||||
* Open encrypted database -> call db.key("secret") -> database ready
|
||||
*
|
||||
* @param[in] aKey Key to decode/encode the database
|
||||
@ -421,10 +421,10 @@ public:
|
||||
/**
|
||||
* @brief Test if a file contains an unencrypted database.
|
||||
*
|
||||
* This is a simple test that reads the first bytes of a database file and
|
||||
* compares them to the standard header for unencrypted databases. If the
|
||||
* header does not match the standard string, we assume that we have an
|
||||
* encrypted file.
|
||||
* This is a simple test that reads the first bytes of a database file and
|
||||
* compares them to the standard header for unencrypted databases. If the
|
||||
* header does not match the standard string, we assume that we have an
|
||||
* encrypted file.
|
||||
*
|
||||
* @param[in] aFilename path/uri to a file
|
||||
*
|
||||
@ -434,6 +434,18 @@ public:
|
||||
*/
|
||||
static bool isUnencrypted(const std::string& aFilename);
|
||||
|
||||
/**
|
||||
* @brief Load or save the database content.
|
||||
*
|
||||
* This function is used to load the contents of a database file on disk
|
||||
* into the "main" database of open database connection, or to save the current
|
||||
* contents of the database into a database file on disk.
|
||||
*
|
||||
* @return SQLITE_OK on success or an error code from SQLite.
|
||||
*/
|
||||
enum class BackupType { Save, Load };
|
||||
int backup(const char* zFilename, BackupType type);
|
||||
|
||||
private:
|
||||
/// @{ Database must be non-copyable
|
||||
Database(const Database&);
|
||||
|
@ -300,4 +300,48 @@ bool Database::isUnencrypted(const std::string& aFilename)
|
||||
throw exception;
|
||||
}
|
||||
|
||||
// This is a reference implementation of live backup taken from the official sit:
|
||||
// https://www.sqlite.org/backup.html
|
||||
|
||||
int Database::backup(const char* zFilename, BackupType type) {
|
||||
/* Open the database file identified by zFilename. Exit early if this fails. */
|
||||
sqlite3* pFile;
|
||||
int rc = sqlite3_open(zFilename, &pFile);
|
||||
if (rc == SQLITE_OK)
|
||||
{
|
||||
/* If this is a 'load' operation (isSave==0), then data is copied
|
||||
** from the database file just opened to database mpSQLite.
|
||||
** Otherwise, if this is a 'save' operation (isSave==1), then data
|
||||
** is copied from mpSQLite to pFile. Set the variables pFrom and
|
||||
** pTo accordingly. */
|
||||
sqlite3* pFrom = (type == BackupType::Save ? mpSQLite : pFile);
|
||||
sqlite3* pTo = (type == BackupType::Save ? pFile : mpSQLite);
|
||||
|
||||
/* Set up the backup procedure to copy from the "main" database of
|
||||
** connection pFile to the main database of connection mpSQLite.
|
||||
** If something goes wrong, pBackup will be set to NULL and an error
|
||||
** code and message left in connection pTo.
|
||||
**
|
||||
** If the backup object is successfully created, call backup_step()
|
||||
** to copy data from pFile to mpSQLite. Then call backup_finish()
|
||||
** to release resources associated with the pBackup object. If an
|
||||
** error occurred, then an error code and message will be left in
|
||||
** connection pTo. If no error occurred, then the error code belonging
|
||||
** to pTo is set to SQLITE_OK.
|
||||
*/
|
||||
sqlite3_backup *pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main");
|
||||
if (pBackup)
|
||||
{
|
||||
sqlite3_backup_step(pBackup, -1);
|
||||
sqlite3_backup_finish(pBackup);
|
||||
}
|
||||
rc = sqlite3_errcode(pTo);
|
||||
}
|
||||
|
||||
/* Close the database connection opened on database file zFilename
|
||||
** and return the result of this function. */
|
||||
sqlite3_close(pFile);
|
||||
return rc;
|
||||
}
|
||||
|
||||
} // namespace SQLite
|
||||
|
@ -56,7 +56,7 @@ TEST(Database, ctorExecCreateDropExist)
|
||||
EXPECT_TRUE(db.tableExists("test"));
|
||||
EXPECT_TRUE(db.tableExists(std::string("test")));
|
||||
EXPECT_EQ(0, db.getLastInsertRowid());
|
||||
|
||||
|
||||
EXPECT_EQ(0, db.exec("DROP TABLE IF EXISTS test"));
|
||||
EXPECT_FALSE(db.tableExists("test"));
|
||||
EXPECT_FALSE(db.tableExists(std::string("test")));
|
||||
@ -88,7 +88,7 @@ TEST(Database, moveConstructor)
|
||||
remove("test.db3");
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TEST(Database, createCloseReopen)
|
||||
{
|
||||
@ -130,6 +130,28 @@ TEST(Database, inMemory)
|
||||
} // Close an destroy DB
|
||||
}
|
||||
|
||||
TEST(Database, import_export)
|
||||
{
|
||||
// Create a new in-memory database
|
||||
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
|
||||
EXPECT_FALSE(db.tableExists("test"));
|
||||
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
|
||||
EXPECT_TRUE(db.tableExists("test"));
|
||||
|
||||
// Export the data into a file
|
||||
remove("backup");
|
||||
EXPECT_EQ(db.backup("backup", SQLite::Database::BackupType::Save), SQLITE_OK);
|
||||
|
||||
// Trash the table
|
||||
db.exec("DROP TABLE test;");
|
||||
EXPECT_FALSE(db.tableExists("test"));
|
||||
|
||||
// Import the data back from the file
|
||||
EXPECT_EQ(db.backup("backup", SQLite::Database::BackupType::Load), SQLITE_OK);
|
||||
|
||||
EXPECT_TRUE(db.tableExists("test"));
|
||||
}
|
||||
|
||||
#if SQLITE_VERSION_NUMBER >= 3007015 // SQLite v3.7.15 is first version with PRAGMA busy_timeout
|
||||
TEST(Database, busyTimeout)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user