Skip to content

Commit 4590c8e

Browse files
committed
Database() constructor to wrap an existing sqlite3*, leaving it open on destruct
1 parent c0818e4 commit 4590c8e

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

include/SQLiteCpp/Database.h

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,21 @@ class Database
201201

202202
#endif // c++17
203203

204+
/**
205+
* @brief Wrap an existing sqlite3* connection opened by other means.
206+
*
207+
* When the Database object is constructed as a wrapper, its destruction does NOT automatically
208+
* sqlite3_close() the connection. In this case (only), Statement objects may outlive the Database object with
209+
* which they were constructed, so long as the underlying connection remains open.
210+
*
211+
* @param[in] apSQLite Existing sqlite3* connection to be wrapped
212+
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
213+
*
214+
* @throw SQLite::Exception in case of error
215+
*/
216+
Database(sqlite3* apSQLite,
217+
const int aBusyTimeoutMs = 0);
218+
204219
// Database is non-copyable
205220
Database(const Database&) = delete;
206221
Database& operator=(const Database&) = delete;
@@ -217,7 +232,12 @@ class Database
217232
*
218233
* @warning assert in case of error
219234
*/
220-
~Database() = default;
235+
~Database()
236+
{
237+
if (!mCloseOnDestruct) {
238+
mSQLitePtr.release(); // prevent Deleter
239+
}
240+
}
221241

222242
// Deleter functor to use with smart pointers to close the SQLite database connection in an RAII fashion.
223243
struct Deleter
@@ -414,7 +434,7 @@ class Database
414434
/// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
415435
const char* getErrorMsg() const noexcept;
416436

417-
/// Return the filename used to open the database.
437+
/// Return the filename used to open the database; empty if the Database wrapped existing sqlite3*
418438
const std::string& getFilename() const noexcept
419439
{
420440
return mFilename;
@@ -536,10 +556,7 @@ class Database
536556
static Header getHeaderInfo(const std::string& aFilename);
537557

538558
// Parse SQLite header data from a database file.
539-
Header getHeaderInfo()
540-
{
541-
return getHeaderInfo(mFilename);
542-
}
559+
Header getHeaderInfo();
543560

544561
/**
545562
* @brief BackupType for the backup() method
@@ -571,6 +588,7 @@ class Database
571588
private:
572589
// TODO: perhaps switch to having Statement sharing a pointer to the Connexion
573590
std::unique_ptr<sqlite3, Deleter> mSQLitePtr; ///< Pointer to SQLite Database Connection Handle
591+
bool mCloseOnDestruct; ///< true iff ~Database() is to use sqlite3_close() on mSQLitePtr
574592
std::string mFilename; ///< UTF-8 filename used to open the database
575593
};
576594

src/Database.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Database::Database(const char* apFilename,
7171
const int aFlags /* = SQLite::OPEN_READONLY*/,
7272
const int aBusyTimeoutMs /* = 0 */,
7373
const char* apVfs /* = nullptr*/) :
74+
mCloseOnDestruct(true),
7475
mFilename(apFilename)
7576
{
7677
sqlite3* handle;
@@ -86,6 +87,19 @@ Database::Database(const char* apFilename,
8687
}
8788
}
8889

90+
// Wrap an existing sqlite3* connection opened by other means.
91+
Database::Database(sqlite3* apSQLite,
92+
const int aBusyTimeoutMs /* = 0 */) :
93+
mCloseOnDestruct(false)
94+
{
95+
SQLITECPP_ASSERT(apSQLite != nullptr, "Database(nullptr)");
96+
mSQLitePtr.reset(apSQLite);
97+
if (aBusyTimeoutMs > 0)
98+
{
99+
setBusyTimeout(aBusyTimeoutMs);
100+
}
101+
}
102+
89103
// Deleter functor to use with smart pointers to close the SQLite database connection in an RAII fashion.
90104
void Database::Deleter::operator()(sqlite3* apSQLite)
91105
{
@@ -432,6 +446,18 @@ Header Database::getHeaderInfo(const std::string& aFilename)
432446
return h;
433447
}
434448

449+
Header Database::getHeaderInfo()
450+
{
451+
if (!mFilename.empty())
452+
{
453+
return getHeaderInfo(mFilename);
454+
}
455+
const char *zFilename = sqlite3_db_filename(mSQLitePtr.get(), nullptr);
456+
return getHeaderInfo(std::string(zFilename ? zFilename : ""));
457+
}
458+
459+
460+
435461
void Database::backup(const char* apFilename, BackupType aType)
436462
{
437463
// Open the database file identified by apFilename

0 commit comments

Comments
 (0)