From 75ab17c3ecb0a3817ccfda3f82a0fb3cf38a188e Mon Sep 17 00:00:00 2001 From: Wongoo Lee Date: Fri, 10 Jun 2016 16:18:31 -0700 Subject: [PATCH 1/4] Supports sqlite3 backup API. --- README.md | 16 ++++++++++++++++ headeronly_src/sqlite3pp.h | 4 ++++ headeronly_src/sqlite3pp.ipp | 20 ++++++++++++++++++++ test/testbackup.cpp | 25 +++++++++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 test/testbackup.cpp diff --git a/README.md b/README.md index 630346e..2685752 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,22 @@ sqlite3pp::query qry( "SELECT epi.* FROM episodes epi, test.contacts con WHERE epi.id = con.id"); ``` +## backup + +```cpp +sqlite3pp::database db("test.db"); +sqlite3pp::database backupdb("backup.db"); + +db.backup( + backupdb, + [](int pagecount, int remaining, int rc) { + cout << pagecount << "/" << remaining << endl; + if (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED) { + // sleep or do nothing. + } + }); +``` + ## callback ```cpp diff --git a/headeronly_src/sqlite3pp.h b/headeronly_src/sqlite3pp.h index 985fbaa..ce64714 100644 --- a/headeronly_src/sqlite3pp.h +++ b/headeronly_src/sqlite3pp.h @@ -78,6 +78,7 @@ namespace sqlite3pp using rollback_handler = std::function; using update_handler = std::function; using authorize_handler = std::function; + using backup_handler = std::function; explicit database(char const* dbname = nullptr, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, const char* vfs = nullptr); @@ -92,6 +93,9 @@ namespace sqlite3pp int attach(char const* dbname, char const* name); int detach(char const* name); + int backup(database& destdb, backup_handler h); + int backup(char const* dbname, database& destdb, char const* destdbname, backup_handler h, int step_page = 5); + long long int last_insert_rowid() const; int enable_foreign_keys(bool enable = true); diff --git a/headeronly_src/sqlite3pp.ipp b/headeronly_src/sqlite3pp.ipp index 9d1487a..bcdbd7e 100644 --- a/headeronly_src/sqlite3pp.ipp +++ b/headeronly_src/sqlite3pp.ipp @@ -132,6 +132,26 @@ namespace sqlite3pp return executef("DETACH '%q'", name); } + inline int database::backup(database& destdb, backup_handler h) + { + return backup("main", destdb, "main", h, 5); + } + + inline int database::backup(char const* dbname, database& destdb, char const* destdbname, backup_handler h, int step_page) + { + sqlite3_backup* bkup = sqlite3_backup_init(destdb.db_, destdbname, db_, dbname); + if (!bkup) { + return error_code(); + } + auto rc = SQLITE_OK; + do { + rc = sqlite3_backup_step(bkup, step_page); + h(sqlite3_backup_remaining(bkup), sqlite3_backup_pagecount(bkup), rc); + } while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED); + sqlite3_backup_finish(bkup); + return rc; + } + inline void database::set_busy_handler(busy_handler h) { bh_ = h; diff --git a/test/testbackup.cpp b/test/testbackup.cpp new file mode 100644 index 0000000..af0f602 --- /dev/null +++ b/test/testbackup.cpp @@ -0,0 +1,25 @@ +#include +#include "sqlite3pp.h" + +using namespace std; + +int main() +{ + try { + sqlite3pp::database db("test.db"); + sqlite3pp::database backupdb("backup.db"); + + db.backup( + backupdb, + [](int pagecount, int remaining, int rc) { + cout << pagecount << "/" << remaining << endl; + if (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED) { + // sleep(250); + } + }); + } + catch (exception& ex) { + cout << ex.what() << endl; + } + +} From 37a742340edeca904a2adc47aab78bbf2ee21b75 Mon Sep 17 00:00:00 2001 From: Wongoo Lee Date: Wed, 15 Jun 2016 08:42:11 -0700 Subject: [PATCH 2/4] Uses empty function for default backup handler. --- headeronly_src/sqlite3pp.h | 2 +- headeronly_src/sqlite3pp.ipp | 4 +++- src/sqlite3pp.cpp | 22 ++++++++++++++++++++++ src/sqlite3pp.h | 4 ++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/headeronly_src/sqlite3pp.h b/headeronly_src/sqlite3pp.h index ce64714..06a1945 100644 --- a/headeronly_src/sqlite3pp.h +++ b/headeronly_src/sqlite3pp.h @@ -93,7 +93,7 @@ namespace sqlite3pp int attach(char const* dbname, char const* name); int detach(char const* name); - int backup(database& destdb, backup_handler h); + int backup(database& destdb, backup_handler h = {}); int backup(char const* dbname, database& destdb, char const* destdbname, backup_handler h, int step_page = 5); long long int last_insert_rowid() const; diff --git a/headeronly_src/sqlite3pp.ipp b/headeronly_src/sqlite3pp.ipp index bcdbd7e..050ebab 100644 --- a/headeronly_src/sqlite3pp.ipp +++ b/headeronly_src/sqlite3pp.ipp @@ -146,7 +146,9 @@ namespace sqlite3pp auto rc = SQLITE_OK; do { rc = sqlite3_backup_step(bkup, step_page); - h(sqlite3_backup_remaining(bkup), sqlite3_backup_pagecount(bkup), rc); + if (h) { + h(sqlite3_backup_remaining(bkup), sqlite3_backup_pagecount(bkup), rc); + } } while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED); sqlite3_backup_finish(bkup); return rc; diff --git a/src/sqlite3pp.cpp b/src/sqlite3pp.cpp index be86a75..e2828db 100644 --- a/src/sqlite3pp.cpp +++ b/src/sqlite3pp.cpp @@ -134,6 +134,28 @@ namespace sqlite3pp return executef("DETACH '%q'", name); } + int database::backup(database& destdb, backup_handler h) + { + return backup("main", destdb, "main", h, 5); + } + + int database::backup(char const* dbname, database& destdb, char const* destdbname, backup_handler h, int step_page) + { + sqlite3_backup* bkup = sqlite3_backup_init(destdb.db_, destdbname, db_, dbname); + if (!bkup) { + return error_code(); + } + auto rc = SQLITE_OK; + do { + rc = sqlite3_backup_step(bkup, step_page); + if (h) { + h(sqlite3_backup_remaining(bkup), sqlite3_backup_pagecount(bkup), rc); + } + } while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED); + sqlite3_backup_finish(bkup); + return rc; + } + void database::set_busy_handler(busy_handler h) { bh_ = h; diff --git a/src/sqlite3pp.h b/src/sqlite3pp.h index 8b292c8..263d061 100644 --- a/src/sqlite3pp.h +++ b/src/sqlite3pp.h @@ -79,6 +79,7 @@ namespace sqlite3pp using rollback_handler = std::function; using update_handler = std::function; using authorize_handler = std::function; + using backup_handler = std::function; explicit database(char const* dbname = nullptr, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, const char* vfs = nullptr); @@ -93,6 +94,9 @@ namespace sqlite3pp int attach(char const* dbname, char const* name); int detach(char const* name); + int backup(database& destdb, backup_handler h = {}); + int backup(char const* dbname, database& destdb, char const* destdbname, backup_handler h, int step_page = 5); + long long int last_insert_rowid() const; int enable_foreign_keys(bool enable = true); From b1143ba2a2a436001e81227a960cc263f0aa43c5 Mon Sep 17 00:00:00 2001 From: Wongoo Lee Date: Wed, 15 Jun 2016 08:45:00 -0700 Subject: [PATCH 3/4] Documents no backup handler backup call. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 2685752..f321e52 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,10 @@ sqlite3pp::query qry( sqlite3pp::database db("test.db"); sqlite3pp::database backupdb("backup.db"); +db.backup(backupdb); +``` + +```cpp db.backup( backupdb, [](int pagecount, int remaining, int rc) { From 22ad8b67418ecf6521cf6209d83a6ff421acbd2b Mon Sep 17 00:00:00 2001 From: Wongoo Lee Date: Wed, 15 Jun 2016 08:46:45 -0700 Subject: [PATCH 4/4] Uses default value in header files. --- headeronly_src/sqlite3pp.ipp | 2 +- src/sqlite3pp.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/headeronly_src/sqlite3pp.ipp b/headeronly_src/sqlite3pp.ipp index 050ebab..cd5f29d 100644 --- a/headeronly_src/sqlite3pp.ipp +++ b/headeronly_src/sqlite3pp.ipp @@ -134,7 +134,7 @@ namespace sqlite3pp inline int database::backup(database& destdb, backup_handler h) { - return backup("main", destdb, "main", h, 5); + return backup("main", destdb, "main", h); } inline int database::backup(char const* dbname, database& destdb, char const* destdbname, backup_handler h, int step_page) diff --git a/src/sqlite3pp.cpp b/src/sqlite3pp.cpp index e2828db..58fdfce 100644 --- a/src/sqlite3pp.cpp +++ b/src/sqlite3pp.cpp @@ -136,7 +136,7 @@ namespace sqlite3pp int database::backup(database& destdb, backup_handler h) { - return backup("main", destdb, "main", h, 5); + return backup("main", destdb, "main", h); } int database::backup(char const* dbname, database& destdb, char const* destdbname, backup_handler h, int step_page)