mirror of
https://github.com/cuberite/SQLiteCpp.git
synced 2025-08-04 09:46:02 -04:00
Replace Database::backup() "C" implementation by calling the Backup class
This commit is contained in:
parent
92ff87be60
commit
9ea0cffc15
@ -162,3 +162,4 @@ Version 3.0.0 - January 1 2020
|
|||||||
- Visual Studio 2015 minimum
|
- Visual Studio 2015 minimum
|
||||||
- Googletest 1.10
|
- Googletest 1.10
|
||||||
- Remove Statement::isOk() deprecated in 2.2.0 when renamed to Statement::hasRow()
|
- Remove Statement::isOk() deprecated in 2.2.0 when renamed to Statement::hasRow()
|
||||||
|
- Replace Database::backup() "C" implementation by calling the Backup class
|
||||||
|
@ -27,16 +27,8 @@ namespace SQLite
|
|||||||
* A Backup object is used to backup a source database file to a destination database file
|
* A Backup object is used to backup a source database file to a destination database file
|
||||||
* in a safe and online way.
|
* in a safe and online way.
|
||||||
*
|
*
|
||||||
* Resource Acquisition Is Initialization (RAII) means that the Backup Resource
|
* See also the a reference implementation of live backup taken from the official site:
|
||||||
* is allocated in the constructor and released in the destructor, so that there is
|
* https://www.sqlite.org/backup.html
|
||||||
* no need to worry about memory management or the validity of the underlying SQLite Backup.
|
|
||||||
*
|
|
||||||
* Thread-safety: a Backup object shall not be shared by multiple threads, because :
|
|
||||||
* 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads
|
|
||||||
* provided that no single database connection is used simultaneously in two or more threads."
|
|
||||||
* 2) the SQLite "Serialized" mode is not supported by SQLiteC++,
|
|
||||||
* because of the way it shares the underling SQLite precompiled statement
|
|
||||||
* in a custom shared pointer (See the inner class "Statement::Ptr").
|
|
||||||
*/
|
*/
|
||||||
class Backup
|
class Backup
|
||||||
{
|
{
|
||||||
|
@ -489,9 +489,9 @@ public:
|
|||||||
* into the "main" database of open database connection, or to save the current
|
* into the "main" database of open database connection, or to save the current
|
||||||
* contents of the database into a database file on disk.
|
* contents of the database into a database file on disk.
|
||||||
*
|
*
|
||||||
* @return SQLITE_OK on success or an error code from SQLite.
|
* @throw SQLite::Exception in case of error
|
||||||
*/
|
*/
|
||||||
int backup(const char* zFilename, BackupType type);
|
void backup(const char* apFilename, BackupType aType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
|
* @brief Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <SQLiteCpp/Database.h>
|
#include <SQLiteCpp/Database.h>
|
||||||
|
|
||||||
#include <SQLiteCpp/Assertion.h>
|
#include <SQLiteCpp/Assertion.h>
|
||||||
|
#include <SQLiteCpp/Backup.h>
|
||||||
#include <SQLiteCpp/Exception.h>
|
#include <SQLiteCpp/Exception.h>
|
||||||
#include <SQLiteCpp/Statement.h>
|
#include <SQLiteCpp/Statement.h>
|
||||||
|
|
||||||
@ -405,49 +406,20 @@ Header Database::getHeaderInfo(const std::string& aFilename)
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Database::backup(const char* apFilename, BackupType aType)
|
||||||
|
{
|
||||||
|
// Open the database file identified by apFilename
|
||||||
|
Database otherDatabase(apFilename, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
|
||||||
|
|
||||||
// This is a reference implementation of live backup taken from the official sit:
|
// For a 'Save' operation, data is copied from the current Database to the other. A 'Load' is the reverse.
|
||||||
// https://www.sqlite.org/backup.html
|
Database& src = (aType == Save ? *this : otherDatabase);
|
||||||
|
Database& dest = (aType == Save ? otherDatabase : *this);
|
||||||
|
|
||||||
int Database::backup(const char* zFilename, BackupType type) {
|
// Set up the backup procedure to copy between the "main" databases of each connection
|
||||||
/* Open the database file identified by zFilename. Exit early if this fails. */
|
Backup bkp(dest, src);
|
||||||
sqlite3* pFile;
|
bkp.executeStep(); // Execute all steps at once
|
||||||
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 == Save ? getHandle() : pFile);
|
|
||||||
sqlite3* pTo = (type == Save ? pFile : getHandle());
|
|
||||||
|
|
||||||
/* Set up the backup procedure to copy from the "main" database of
|
// RAII Finish Backup an Close the other Database
|
||||||
** 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
|
} // namespace SQLite
|
||||||
|
@ -131,7 +131,7 @@ TEST(Database, inMemory)
|
|||||||
} // Close an destroy DB
|
} // Close an destroy DB
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Database, import_export)
|
TEST(Database, backup)
|
||||||
{
|
{
|
||||||
// Create a new in-memory database
|
// Create a new in-memory database
|
||||||
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
|
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
|
||||||
@ -141,14 +141,14 @@ TEST(Database, import_export)
|
|||||||
|
|
||||||
// Export the data into a file
|
// Export the data into a file
|
||||||
remove("backup");
|
remove("backup");
|
||||||
EXPECT_EQ(db.backup("backup", SQLite::Database::Save), SQLITE_OK);
|
EXPECT_NO_THROW(db.backup("backup", SQLite::Database::Save));
|
||||||
|
|
||||||
// Trash the table
|
// Trash the table
|
||||||
db.exec("DROP TABLE test;");
|
db.exec("DROP TABLE test;");
|
||||||
EXPECT_FALSE(db.tableExists("test"));
|
EXPECT_FALSE(db.tableExists("test"));
|
||||||
|
|
||||||
// Import the data back from the file
|
// Import the data back from the file
|
||||||
EXPECT_EQ(db.backup("backup", SQLite::Database::Load), SQLITE_OK);
|
EXPECT_NO_THROW(db.backup("backup", SQLite::Database::Load));
|
||||||
|
|
||||||
EXPECT_TRUE(db.tableExists("test"));
|
EXPECT_TRUE(db.tableExists("test"));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user