Skip to content

Commit 145de8e

Browse files
committed
Final touches
1 parent bff4fff commit 145de8e

File tree

2 files changed

+33
-22
lines changed

2 files changed

+33
-22
lines changed

README.md

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,20 +82,20 @@ Prepared Statements
8282
It is possible to retain and reuse statments this will keep the query plan and in case of an complex query or many uses might increase the performance significantly.
8383

8484
```c++
85-
8685
database db(":memory:");
8786

8887
// if you use << on a sqlite::database you get a prepared statment back
8988
// this will not be executed till it gets destroyed or you execute it explicitly
90-
auto ps = db << "select ?,? "; // get a prepared parsed and ready statment
89+
auto ps = db << "select a,b from table where something = ? and anotherthing = ?"; // get a prepared parsed and ready statment
9190

9291
// first if needed bind values to it
9392
ps << 5;
9493
int tmp = 8;
9594
ps << tmp;
9695

97-
// now you can execute it, if the statment was executed once it will not be executed again when it goes out of scope.
98-
// But beware that it will if it wasn't executed!
96+
// now you can execute it with `operator>>` or `execute()`.
97+
// If the statment was executed once it will not be executed again when it goes out of scope.
98+
// But beware that it will execute on destruction if it wasn't executed!
9999
ps >> [&](int a,int b){ ... };
100100

101101
// after a successfull execution the statment needs to be reset to be execute again. This will reset the bound values too!
@@ -108,7 +108,7 @@ It is possible to retain and reuse statments this will keep the query plan and i
108108
ps++;
109109

110110
// To disable the execution of a statment when it goes out of scope and wasn't used
111-
ps.set_used(true); // or false if you want it to execute even if it was used
111+
ps.used(true); // or false if you want it to execute even if it was used
112112

113113
// Usage Example:
114114

@@ -124,15 +124,30 @@ Shared Connections
124124
=====
125125
If you need the handle to the database connection to execute sqlite3 commands directly you can get a managed shared_ptr to it, so it will not close as long as you have a referenc to it.
126126
127+
Take this example on how to deal with a database backup using SQLITEs own functions in a save and modern way.
127128
```c++
128-
sqlite::connection_type con;
129-
130-
{ // scope of our db object
131-
database db(":memory:"); // Make a connection and create in memory db
132-
con = db.get_sqlite3_connection();
133-
} // here the temporary db would be lost but we still have the connection for our direct API calls
129+
try {
130+
database backup("backup"); //Open the database file we want to backup to
134131
135-
database db2(con); // or we can even make a new database object from it
132+
auto con = db.connection(); // get a handle to the DB we want to backup in our scope
133+
// this way we are sure the DB is open and ok while we backup
134+
135+
// Init Backup and make sure its freed on exit or exceptions!
136+
auto state =
137+
std::unique_ptr<sqlite3_backup,decltype(&sqlite3_backup_finish)>(
138+
sqlite3_backup_init(backup.connection().get(), "main", con.get(), "main"),
139+
sqlite3_backup_finish
140+
);
141+
142+
if(state) {
143+
int rc;
144+
// Each iteration of this loop copies 500 database pages from database db to the backup database.
145+
do {
146+
rc = sqlite3_backup_step(state.get(), 500);
147+
std::cout << "Remaining " << sqlite3_backup_remaining(pBackup) << "/" << sqlite3_backup_pagecount(pBackup) << "\n";
148+
} while(rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
149+
}
150+
} // Release allocated resources.
136151
```
137152

138153
Transactions

hdr/sqlite_modern_cpp.h

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ namespace sqlite {
133133
}
134134
}
135135

136-
void set_used(bool state) { execution_started = state; }
137-
bool get_used() const { return execution_started; }
136+
void used(bool state) { execution_started = state; }
137+
bool used() const { return execution_started; }
138138

139139
private:
140140
std::shared_ptr<sqlite3> _db;
@@ -228,7 +228,7 @@ namespace sqlite {
228228

229229
~database_binder() noexcept(false) {
230230
/* Will be executed if no >>op is found, but not if an exception
231-
is in mud flight */
231+
is in mid flight */
232232
if(!execution_started && !std::uncaught_exception()) {
233233
execute();
234234
}
@@ -279,16 +279,11 @@ namespace sqlite {
279279
database(std::shared_ptr<sqlite3> db):
280280
_db(db) {}
281281

282-
//template<typename T>
283-
//database_binder::chain_type operator<<(const T& sql) const {
284-
// return database_binder::chain_type(new database_binder(_db,std::string(sql)));
285-
//}
286-
287282
database_binder::chain_type operator<<(const char* sql) {
288283
return database_binder::chain_type(new database_binder(_db, std::string(sql)));
289284
}
290285

291-
connection_type get_sqlite3_connection() const { return _db; }
286+
connection_type connection() const { return _db; }
292287

293288
sqlite3_int64 last_insert_rowid() const {
294289
return sqlite3_last_insert_rowid(_db.get());
@@ -484,10 +479,11 @@ namespace sqlite {
484479
}
485480
#endif
486481

487-
// there is too much magic here, val might be rValue or rValue
482+
// there is too much magic here, val might be rValue or lValue
488483
template<typename T> void operator >> (database_binder::chain_type& db, T&& val) { *db >> std::forward<T>(val); }
489484
template<typename T> void operator >> (database_binder::chain_type&& db, T&& val) { db >> std::forward<T>(val); }
490485

486+
// Some ppl are lazy so we have a operator for proper prep. statemant handling.
491487
void operator++(database_binder::chain_type& db, int) { db->execute(); db->reset(); }
492488

493489
// Convert the rValue binder to a reference and call first op<<, its needed for the call that creates the binder (be carfull of recursion here!)

0 commit comments

Comments
 (0)