From be5400ca992bcf86ba9de9e75288872d0d2d7741 Mon Sep 17 00:00:00 2001 From: Kacperos155 Date: Sat, 23 Jul 2022 16:07:53 +0200 Subject: [PATCH 1/8] Small improvements & code cleanup --- include/SQLiteCpp/Backup.h | 17 ++++++++++------- include/SQLiteCpp/Database.h | 12 ++++++------ include/SQLiteCpp/Savepoint.h | 8 ++++---- include/SQLiteCpp/Statement.h | 14 +++++--------- include/SQLiteCpp/Transaction.h | 4 ++-- src/Backup.cpp | 32 ++++++++++++++++---------------- src/Column.cpp | 2 +- src/Database.cpp | 13 ++++++------- src/Savepoint.cpp | 4 ++-- src/Transaction.cpp | 6 ++---- 10 files changed, 54 insertions(+), 58 deletions(-) diff --git a/include/SQLiteCpp/Backup.h b/include/SQLiteCpp/Backup.h index 21ad662..ac940cb 100644 --- a/include/SQLiteCpp/Backup.h +++ b/include/SQLiteCpp/Backup.h @@ -14,6 +14,7 @@ #include #include +#include // Forward declaration to avoid inclusion of in a header struct sqlite3_backup; @@ -95,9 +96,6 @@ public: Backup(const Backup&) = delete; Backup& operator=(const Backup&) = delete; - /// Release the SQLite Backup resource. - ~Backup(); - /** * @brief Execute a step of backup with a given number of source pages to be copied * @@ -114,14 +112,19 @@ public: int executeStep(const int aNumPage = -1); /// Return the number of source pages still to be backed up as of the most recent call to executeStep(). - int getRemainingPageCount(); + int getRemainingPageCount() const; /// Return the total number of pages in the source database as of the most recent call to executeStep(). - int getTotalPageCount(); + int getTotalPageCount() const; private: - // TODO: use std::unique_ptr with a custom deleter to call sqlite3_backup_finish() - sqlite3_backup* mpSQLiteBackup = nullptr; ///< Pointer to SQLite Database Backup Handle + // Deleter functor to use with smart pointers to close the SQLite database backup in an RAII fashion. + struct Deleter + { + void operator()(sqlite3_backup* apBackup); + }; + + std::unique_ptr mpSQLiteBackup{}; ///< Pointer to SQLite Database Backup Handle }; } // namespace SQLite diff --git a/include/SQLiteCpp/Database.h b/include/SQLiteCpp/Database.h index 7ee45d8..3ef3d88 100644 --- a/include/SQLiteCpp/Database.h +++ b/include/SQLiteCpp/Database.h @@ -78,8 +78,8 @@ extern const int OPEN_NOFOLLOW; // SQLITE_OPEN_NOFOLLOW extern const int OK; ///< SQLITE_OK (used by check() bellow) -extern const char* VERSION; ///< SQLITE_VERSION string from the sqlite3.h used at compile time -extern const int VERSION_NUMBER; ///< SQLITE_VERSION_NUMBER from the sqlite3.h used at compile time +extern const char* const VERSION; ///< SQLITE_VERSION string from the sqlite3.h used at compile time +extern const int VERSION_NUMBER; ///< SQLITE_VERSION_NUMBER from the sqlite3.h used at compile time /// Return SQLite version string using runtime call to the compiled library const char* getLibVersion() noexcept; @@ -328,7 +328,7 @@ public: * * @return the sqlite result code. */ - int tryExec(const std::string aQueries) noexcept + int tryExec(const std::string& aQueries) noexcept { return tryExec(aQueries.c_str()); } @@ -389,7 +389,7 @@ public: * * @throw SQLite::Exception in case of error */ - bool tableExists(const char* apTableName); + bool tableExists(const char* apTableName) const; /** * @brief Shortcut to test if a table exists. @@ -402,7 +402,7 @@ public: * * @throw SQLite::Exception in case of error */ - bool tableExists(const std::string& aTableName) + bool tableExists(const std::string& aTableName) const { return tableExists(aTableName.c_str()); } @@ -552,7 +552,7 @@ public: static Header getHeaderInfo(const std::string& aFilename); // Parse SQLite header data from a database file. - Header getHeaderInfo() + Header getHeaderInfo() const { return getHeaderInfo(mFilename); } diff --git a/include/SQLiteCpp/Savepoint.h b/include/SQLiteCpp/Savepoint.h index d389720..14b25cc 100644 --- a/include/SQLiteCpp/Savepoint.h +++ b/include/SQLiteCpp/Savepoint.h @@ -66,7 +66,7 @@ class Savepoint { * Exception is thrown in case of error, then the Savepoint is NOT * initiated. */ - Savepoint(Database& aDatabase, std::string name); + Savepoint(Database& aDatabase, const std::string& name); // Savepoint is non-copyable Savepoint(const Savepoint&) = delete; @@ -88,8 +88,8 @@ class Savepoint { void rollback(); private: - Database& mDatabase; ///< Reference to the SQLite Database Connection - std::string msName; ///< Name of the Savepoint - bool mbReleased; ///< True when release has been called + Database& mDatabase; ///< Reference to the SQLite Database Connection + std::string msName; ///< Name of the Savepoint + bool mbReleased{ false }; ///< True when release has been called }; } // namespace SQLite diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index c81e215..809b8d3 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -74,18 +74,14 @@ public: Statement(aDatabase, aQuery.c_str()) {} - /** - * @brief Move an SQLite statement. - * - * @param[in] aStatement Statement to move - */ - Statement(Statement&& aStatement) noexcept; - Statement& operator=(Statement&& aStatement) noexcept = default; - // Statement is non-copyable Statement(const Statement&) = delete; Statement& operator=(const Statement&) = delete; + Statement(Statement&& aStatement) noexcept; + Statement& operator=(Statement&& aStatement) noexcept = default; + // TODO: Change Statement move constructor to default + /// Finalize and unregister the SQL query from the SQLite Database Connection. /// The finalization will be done by the destructor of the last shared pointer ~Statement() = default; @@ -705,7 +701,7 @@ private: int mColumnCount{0}; //!< Number of columns in the result of the prepared statement bool mbHasRow{false}; //!< true when a row has been fetched with executeStep() bool mbDone{false}; //!< true when the last executeStep() had no more row to fetch - + /// Map of columns index by name (mutable so getColumnIndex can be const) mutable std::map mColumnNames{}; }; diff --git a/include/SQLiteCpp/Transaction.h b/include/SQLiteCpp/Transaction.h index d7f26ca..0fdefea 100644 --- a/include/SQLiteCpp/Transaction.h +++ b/include/SQLiteCpp/Transaction.h @@ -87,8 +87,8 @@ public: void commit(); private: - Database& mDatabase; ///< Reference to the SQLite Database Connection - bool mbCommited; ///< True when commit has been called + Database& mDatabase; ///< Reference to the SQLite Database Connection + bool mbCommited{ false }; ///< True when commit has been called }; diff --git a/src/Backup.cpp b/src/Backup.cpp index 183d314..92920d8 100644 --- a/src/Backup.cpp +++ b/src/Backup.cpp @@ -24,10 +24,10 @@ Backup::Backup(Database& aDestDatabase, Database& aSrcDatabase, const char* apSrcDatabaseName) { - mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), + mpSQLiteBackup.reset(sqlite3_backup_init(aDestDatabase.getHandle(), apDestDatabaseName, aSrcDatabase.getHandle(), - apSrcDatabaseName); + apSrcDatabaseName)); if (nullptr == mpSQLiteBackup) { // If an error occurs, the error code and message are attached to the destination database connection. @@ -48,19 +48,10 @@ Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) : { } -// Release resource for SQLite database backup -Backup::~Backup() -{ - if (mpSQLiteBackup) - { - sqlite3_backup_finish(mpSQLiteBackup); - } -} - // Execute backup step with a given number of source pages to be copied int Backup::executeStep(const int aNumPage /* = -1 */) { - const int res = sqlite3_backup_step(mpSQLiteBackup, aNumPage); + const int res = sqlite3_backup_step(mpSQLiteBackup.get(), aNumPage); if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res) { throw SQLite::Exception(sqlite3_errstr(res), res); @@ -69,15 +60,24 @@ int Backup::executeStep(const int aNumPage /* = -1 */) } // Get the number of remaining source pages to be copied in this backup process -int Backup::getRemainingPageCount() +int Backup::getRemainingPageCount() const { - return sqlite3_backup_remaining(mpSQLiteBackup); + return sqlite3_backup_remaining(mpSQLiteBackup.get()); } // Get the number of total source pages to be copied in this backup process -int Backup::getTotalPageCount() +int Backup::getTotalPageCount() const { - return sqlite3_backup_pagecount(mpSQLiteBackup); + return sqlite3_backup_pagecount(mpSQLiteBackup.get()); +} + +// Release resource for SQLite database backup +void SQLite::Backup::Deleter::operator()(sqlite3_backup* apBackup) +{ + if (apBackup) + { + sqlite3_backup_finish(apBackup); + } } } // namespace SQLite diff --git a/src/Column.cpp b/src/Column.cpp index f5dc0d9..01550a0 100644 --- a/src/Column.cpp +++ b/src/Column.cpp @@ -78,7 +78,7 @@ double Column::getDouble() const noexcept const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept { auto pText = reinterpret_cast(sqlite3_column_text(mStmtPtr.get(), mIndex)); - return (pText?pText:apDefaultValue); + return (pText ? pText : apDefaultValue); } // Return a pointer to the blob value (*not* NULL terminated) of the column specified by its index starting at 0 diff --git a/src/Database.cpp b/src/Database.cpp index eb76c88..d787cf2 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -27,6 +27,7 @@ namespace SQLite { +const int OK = SQLITE_OK; const int OPEN_READONLY = SQLITE_OPEN_READONLY; const int OPEN_READWRITE = SQLITE_OPEN_READWRITE; const int OPEN_CREATE = SQLITE_OPEN_CREATE; @@ -42,10 +43,8 @@ const int OPEN_NOFOLLOW = SQLITE_OPEN_NOFOLLOW; const int OPEN_NOFOLLOW = 0; #endif -const int OK = SQLITE_OK; - -const char* VERSION = SQLITE_VERSION; -const int VERSION_NUMBER = SQLITE_VERSION_NUMBER; +const char* const VERSION = SQLITE_VERSION; +const int VERSION_NUMBER = SQLITE_VERSION_NUMBER; // Return SQLite version string using runtime call to the compiled library const char* getLibVersion() noexcept @@ -142,7 +141,7 @@ Column Database::execAndGet(const char* apQuery) } // Shortcut to test if a table exists. -bool Database::tableExists(const char* apTableName) +bool Database::tableExists(const char* apTableName) const { Statement query(*this, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?"); query.bind(1, apTableName); @@ -439,8 +438,8 @@ void Database::backup(const char* apFilename, BackupType aType) Database otherDatabase(apFilename, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); // For a 'Save' operation, data is copied from the current Database to the other. A 'Load' is the reverse. - Database& src = (aType == Save ? *this : otherDatabase); - Database& dest = (aType == Save ? otherDatabase : *this); + Database& src = (aType == BackupType::Save ? *this : otherDatabase); + Database& dest = (aType == BackupType::Save ? otherDatabase : *this); // Set up the backup procedure to copy between the "main" databases of each connection Backup bkp(dest, src); diff --git a/src/Savepoint.cpp b/src/Savepoint.cpp index b3d13a2..2475a09 100644 --- a/src/Savepoint.cpp +++ b/src/Savepoint.cpp @@ -18,8 +18,8 @@ namespace SQLite { // Begins the SQLite savepoint -Savepoint::Savepoint(Database& aDatabase, std::string aName) - : mDatabase(aDatabase), msName(aName), mbReleased(false) { +Savepoint::Savepoint(Database& aDatabase, const std::string& aName) + : mDatabase(aDatabase), msName(aName) { // workaround because you cannot bind to SAVEPOINT // escape name for use in query Statement stmt(mDatabase, "SELECT quote(?)"); diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 2a8857a..abfb9b8 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -21,8 +21,7 @@ namespace SQLite // Begins the SQLite transaction Transaction::Transaction(Database& aDatabase, TransactionBehavior behavior) : - mDatabase(aDatabase), - mbCommited(false) + mDatabase(aDatabase) { const char *stmt; switch (behavior) { @@ -43,8 +42,7 @@ Transaction::Transaction(Database& aDatabase, TransactionBehavior behavior) : // Begins the SQLite transaction Transaction::Transaction(Database &aDatabase) : - mDatabase(aDatabase), - mbCommited(false) + mDatabase(aDatabase) { mDatabase.exec("BEGIN"); } From 29e9f31c896560509b465854560b0f38a3c1733e Mon Sep 17 00:00:00 2001 From: Kacperos155 Date: Sat, 23 Jul 2022 16:12:44 +0200 Subject: [PATCH 2/8] Use transparent comparator in mColumnNames to avoid creating std::string when comparing --- include/SQLiteCpp/Statement.h | 2 +- src/Statement.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index 809b8d3..4982352 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -703,7 +703,7 @@ private: bool mbDone{false}; //!< true when the last executeStep() had no more row to fetch /// Map of columns index by name (mutable so getColumnIndex can be const) - mutable std::map mColumnNames{}; + mutable std::map> mColumnNames{}; }; diff --git a/src/Statement.cpp b/src/Statement.cpp index 64e16d2..bef22b0 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -275,7 +275,7 @@ int Statement::getColumnIndex(const char* apName) const for (int i = 0; i < mColumnCount; ++i) { const char* pName = sqlite3_column_name(getPreparedStatement(), i); - mColumnNames[pName] = i; + mColumnNames.emplace(pName, i); } } @@ -288,7 +288,7 @@ int Statement::getColumnIndex(const char* apName) const return iIndex->second; } -const char * Statement::getColumnDeclaredType(const int aIndex) const +const char* Statement::getColumnDeclaredType(const int aIndex) const { checkIndex(aIndex); const char * result = sqlite3_column_decltype(getPreparedStatement(), aIndex); From 258b9c34df17d550a25dcf94d84c1394c27d9714 Mon Sep 17 00:00:00 2001 From: Kacperos155 Date: Sat, 23 Jul 2022 16:14:16 +0200 Subject: [PATCH 3/8] .gitignore: add ".vs " directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f22bfa2..e6ea691 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build example1 *.a +.vs/ .vscode/ /SQLiteCpp.sln *.ncb From e576abaf7ce962e3f6e45e721ae38900abf3f3d1 Mon Sep 17 00:00:00 2001 From: Kacperos155 Date: Sun, 24 Jul 2022 18:54:00 +0200 Subject: [PATCH 4/8] Restore Backup destructor & small style changes --- include/SQLiteCpp/Backup.h | 11 +++----- include/SQLiteCpp/Column.h | 4 --- include/SQLiteCpp/Row.h | 47 +++++++++++++++++++++++++++++++++ include/SQLiteCpp/Savepoint.h | 2 +- include/SQLiteCpp/Statement.h | 8 +++--- include/SQLiteCpp/Transaction.h | 2 +- src/Backup.cpp | 27 ++++++++++--------- src/Row.cpp | 25 ++++++++++++++++++ 8 files changed, 96 insertions(+), 30 deletions(-) create mode 100644 include/SQLiteCpp/Row.h create mode 100644 src/Row.cpp diff --git a/include/SQLiteCpp/Backup.h b/include/SQLiteCpp/Backup.h index ac940cb..ea6f71f 100644 --- a/include/SQLiteCpp/Backup.h +++ b/include/SQLiteCpp/Backup.h @@ -96,6 +96,9 @@ public: Backup(const Backup&) = delete; Backup& operator=(const Backup&) = delete; + /// Release the SQLite Backup resource. + ~Backup(); + /** * @brief Execute a step of backup with a given number of source pages to be copied * @@ -118,13 +121,7 @@ public: int getTotalPageCount() const; private: - // Deleter functor to use with smart pointers to close the SQLite database backup in an RAII fashion. - struct Deleter - { - void operator()(sqlite3_backup* apBackup); - }; - - std::unique_ptr mpSQLiteBackup{}; ///< Pointer to SQLite Database Backup Handle + sqlite3_backup* mpSQLiteBackup = nullptr; ///< Pointer to SQLite Database Backup Handle }; } // namespace SQLite diff --git a/include/SQLiteCpp/Column.h b/include/SQLiteCpp/Column.h index bc349f9..2dee76d 100644 --- a/include/SQLiteCpp/Column.h +++ b/include/SQLiteCpp/Column.h @@ -56,10 +56,6 @@ public: */ explicit Column(const Statement::TStatementPtr& aStmtPtr, int aIndex); - // default destructor: the finalization will be done by the destructor of the last shared pointer - // default copy constructor and assignment operator are perfectly suited : - // they copy the Statement::Ptr which in turn increments the reference counter. - /** * @brief Return a pointer to the named assigned to this result column (potentially aliased) * diff --git a/include/SQLiteCpp/Row.h b/include/SQLiteCpp/Row.h new file mode 100644 index 0000000..8a20a6c --- /dev/null +++ b/include/SQLiteCpp/Row.h @@ -0,0 +1,47 @@ +/** + * @file Row.h + * @ingroup SQLiteCpp + * @brief TODO: + * + * Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com) + * Copyright (c) 2015-2021 Sebastien Rombauts (sebastien.rombauts@gmail.com) + * + * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt + * or copy at http://opensource.org/licenses/MIT) + */ +#pragma once + +#include + +#include + +// Forward declaration to avoid inclusion of in a header +struct sqlite3_stmt; +class Row; + +namespace SQLite +{ + + +class Row +{ +public: + Row(RowExecutor::TRowPtr apRow, std::size_t aID); + + /** + * @brief Test if the column value is NULL + * + * @param[in] aIndex Index of the column, starting at 0 + * + * @return true if the column value is NULL + * + * Throw an exception if the specified index is out of the [0, getColumnCount()) range. + */ + bool isColumnNull(const int aIndex) const; + +private: + RowExecutor::TRowWeakPtr mpRow; + std::size_t ID; +}; + +} // namespace SQLite diff --git a/include/SQLiteCpp/Savepoint.h b/include/SQLiteCpp/Savepoint.h index 14b25cc..681cde0 100644 --- a/include/SQLiteCpp/Savepoint.h +++ b/include/SQLiteCpp/Savepoint.h @@ -90,6 +90,6 @@ class Savepoint { private: Database& mDatabase; ///< Reference to the SQLite Database Connection std::string msName; ///< Name of the Savepoint - bool mbReleased{ false }; ///< True when release has been called + bool mbReleased = false; ///< True when release has been called }; } // namespace SQLite diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index 4982352..ce95893 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -698,12 +698,12 @@ private: std::string mQuery; //!< UTF-8 SQL Query sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle TStatementPtr mpPreparedStatement; //!< Shared Pointer to the prepared SQLite Statement Object - int mColumnCount{0}; //!< Number of columns in the result of the prepared statement - bool mbHasRow{false}; //!< true when a row has been fetched with executeStep() - bool mbDone{false}; //!< true when the last executeStep() had no more row to fetch + int mColumnCount = 0; //!< Number of columns in the result of the prepared statement + bool mbHasRow = false; //!< true when a row has been fetched with executeStep() + bool mbDone = false; //!< true when the last executeStep() had no more row to fetch /// Map of columns index by name (mutable so getColumnIndex can be const) - mutable std::map> mColumnNames{}; + mutable std::map> mColumnNames; }; diff --git a/include/SQLiteCpp/Transaction.h b/include/SQLiteCpp/Transaction.h index 0fdefea..a2198f9 100644 --- a/include/SQLiteCpp/Transaction.h +++ b/include/SQLiteCpp/Transaction.h @@ -88,7 +88,7 @@ public: private: Database& mDatabase; ///< Reference to the SQLite Database Connection - bool mbCommited{ false }; ///< True when commit has been called + bool mbCommited = false; ///< True when commit has been called }; diff --git a/src/Backup.cpp b/src/Backup.cpp index 92920d8..4c91e69 100644 --- a/src/Backup.cpp +++ b/src/Backup.cpp @@ -24,10 +24,10 @@ Backup::Backup(Database& aDestDatabase, Database& aSrcDatabase, const char* apSrcDatabaseName) { - mpSQLiteBackup.reset(sqlite3_backup_init(aDestDatabase.getHandle(), + mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), apDestDatabaseName, aSrcDatabase.getHandle(), - apSrcDatabaseName)); + apSrcDatabaseName); if (nullptr == mpSQLiteBackup) { // If an error occurs, the error code and message are attached to the destination database connection. @@ -48,10 +48,19 @@ Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) : { } +// Release resource for SQLite database backup +Backup::~Backup() +{ + if (mpSQLiteBackup) + { + sqlite3_backup_finish(mpSQLiteBackup); + } +} + // Execute backup step with a given number of source pages to be copied int Backup::executeStep(const int aNumPage /* = -1 */) { - const int res = sqlite3_backup_step(mpSQLiteBackup.get(), aNumPage); + const int res = sqlite3_backup_step(mpSQLiteBackup, aNumPage); if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res) { throw SQLite::Exception(sqlite3_errstr(res), res); @@ -62,22 +71,14 @@ int Backup::executeStep(const int aNumPage /* = -1 */) // Get the number of remaining source pages to be copied in this backup process int Backup::getRemainingPageCount() const { - return sqlite3_backup_remaining(mpSQLiteBackup.get()); + return sqlite3_backup_remaining(mpSQLiteBackup); } // Get the number of total source pages to be copied in this backup process int Backup::getTotalPageCount() const { - return sqlite3_backup_pagecount(mpSQLiteBackup.get()); + return sqlite3_backup_pagecount(mpSQLiteBackup); } -// Release resource for SQLite database backup -void SQLite::Backup::Deleter::operator()(sqlite3_backup* apBackup) -{ - if (apBackup) - { - sqlite3_backup_finish(apBackup); - } -} } // namespace SQLite diff --git a/src/Row.cpp b/src/Row.cpp new file mode 100644 index 0000000..0ddc0d1 --- /dev/null +++ b/src/Row.cpp @@ -0,0 +1,25 @@ +/** + * @file Row.cpp + * @ingroup SQLiteCpp + * @brief TODO: + * + * Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com) + * Copyright (c) 2015-2021 Sebastien Rombauts (sebastien.rombauts@gmail.com) + * + * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt + * or copy at http://opensource.org/licenses/MIT) + */ +#include + +#include + +#include + +namespace SQLite +{ + + + ; + + +} // namespace SQLite From d9e5a747734328527889dd1120242a1e200ed556 Mon Sep 17 00:00:00 2001 From: Kacperos155 Date: Sat, 23 Jul 2022 16:07:53 +0200 Subject: [PATCH 5/8] Small improvements & code cleanup --- include/SQLiteCpp/Backup.h | 17 ++++++++++------- include/SQLiteCpp/Database.h | 12 ++++++------ include/SQLiteCpp/Savepoint.h | 8 ++++---- include/SQLiteCpp/Statement.h | 12 ++++-------- include/SQLiteCpp/Transaction.h | 4 ++-- src/Backup.cpp | 32 ++++++++++++++++---------------- src/Column.cpp | 2 +- src/Database.cpp | 13 ++++++------- src/Savepoint.cpp | 4 ++-- src/Transaction.cpp | 6 ++---- 10 files changed, 53 insertions(+), 57 deletions(-) diff --git a/include/SQLiteCpp/Backup.h b/include/SQLiteCpp/Backup.h index 21ad662..ac940cb 100644 --- a/include/SQLiteCpp/Backup.h +++ b/include/SQLiteCpp/Backup.h @@ -14,6 +14,7 @@ #include #include +#include // Forward declaration to avoid inclusion of in a header struct sqlite3_backup; @@ -95,9 +96,6 @@ public: Backup(const Backup&) = delete; Backup& operator=(const Backup&) = delete; - /// Release the SQLite Backup resource. - ~Backup(); - /** * @brief Execute a step of backup with a given number of source pages to be copied * @@ -114,14 +112,19 @@ public: int executeStep(const int aNumPage = -1); /// Return the number of source pages still to be backed up as of the most recent call to executeStep(). - int getRemainingPageCount(); + int getRemainingPageCount() const; /// Return the total number of pages in the source database as of the most recent call to executeStep(). - int getTotalPageCount(); + int getTotalPageCount() const; private: - // TODO: use std::unique_ptr with a custom deleter to call sqlite3_backup_finish() - sqlite3_backup* mpSQLiteBackup = nullptr; ///< Pointer to SQLite Database Backup Handle + // Deleter functor to use with smart pointers to close the SQLite database backup in an RAII fashion. + struct Deleter + { + void operator()(sqlite3_backup* apBackup); + }; + + std::unique_ptr mpSQLiteBackup{}; ///< Pointer to SQLite Database Backup Handle }; } // namespace SQLite diff --git a/include/SQLiteCpp/Database.h b/include/SQLiteCpp/Database.h index a331961..4071527 100644 --- a/include/SQLiteCpp/Database.h +++ b/include/SQLiteCpp/Database.h @@ -92,8 +92,8 @@ extern const int OPEN_NOFOLLOW; // SQLITE_OPEN_NOFOLLOW extern const int OK; ///< SQLITE_OK (used by check() bellow) -extern const char* VERSION; ///< SQLITE_VERSION string from the sqlite3.h used at compile time -extern const int VERSION_NUMBER; ///< SQLITE_VERSION_NUMBER from the sqlite3.h used at compile time +extern const char* const VERSION; ///< SQLITE_VERSION string from the sqlite3.h used at compile time +extern const int VERSION_NUMBER; ///< SQLITE_VERSION_NUMBER from the sqlite3.h used at compile time /// Return SQLite version string using runtime call to the compiled library const char* getLibVersion() noexcept; @@ -342,7 +342,7 @@ public: * * @return the sqlite result code. */ - int tryExec(const std::string aQueries) noexcept + int tryExec(const std::string& aQueries) noexcept { return tryExec(aQueries.c_str()); } @@ -403,7 +403,7 @@ public: * * @throw SQLite::Exception in case of error */ - bool tableExists(const char* apTableName); + bool tableExists(const char* apTableName) const; /** * @brief Shortcut to test if a table exists. @@ -416,7 +416,7 @@ public: * * @throw SQLite::Exception in case of error */ - bool tableExists(const std::string& aTableName) + bool tableExists(const std::string& aTableName) const { return tableExists(aTableName.c_str()); } @@ -566,7 +566,7 @@ public: static Header getHeaderInfo(const std::string& aFilename); // Parse SQLite header data from a database file. - Header getHeaderInfo() + Header getHeaderInfo() const { return getHeaderInfo(mFilename); } diff --git a/include/SQLiteCpp/Savepoint.h b/include/SQLiteCpp/Savepoint.h index d389720..14b25cc 100644 --- a/include/SQLiteCpp/Savepoint.h +++ b/include/SQLiteCpp/Savepoint.h @@ -66,7 +66,7 @@ class Savepoint { * Exception is thrown in case of error, then the Savepoint is NOT * initiated. */ - Savepoint(Database& aDatabase, std::string name); + Savepoint(Database& aDatabase, const std::string& name); // Savepoint is non-copyable Savepoint(const Savepoint&) = delete; @@ -88,8 +88,8 @@ class Savepoint { void rollback(); private: - Database& mDatabase; ///< Reference to the SQLite Database Connection - std::string msName; ///< Name of the Savepoint - bool mbReleased; ///< True when release has been called + Database& mDatabase; ///< Reference to the SQLite Database Connection + std::string msName; ///< Name of the Savepoint + bool mbReleased{ false }; ///< True when release has been called }; } // namespace SQLite diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index 704d7de..75ba757 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -74,18 +74,14 @@ public: Statement(aDatabase, aQuery.c_str()) {} - /** - * @brief Move an SQLite statement. - * - * @param[in] aStatement Statement to move - */ - Statement(Statement&& aStatement) noexcept; - Statement& operator=(Statement&& aStatement) noexcept = default; - // Statement is non-copyable Statement(const Statement&) = delete; Statement& operator=(const Statement&) = delete; + Statement(Statement&& aStatement) noexcept; + Statement& operator=(Statement&& aStatement) noexcept = default; + // TODO: Change Statement move constructor to default + /// Finalize and unregister the SQL query from the SQLite Database Connection. /// The finalization will be done by the destructor of the last shared pointer ~Statement() = default; diff --git a/include/SQLiteCpp/Transaction.h b/include/SQLiteCpp/Transaction.h index d7f26ca..0fdefea 100644 --- a/include/SQLiteCpp/Transaction.h +++ b/include/SQLiteCpp/Transaction.h @@ -87,8 +87,8 @@ public: void commit(); private: - Database& mDatabase; ///< Reference to the SQLite Database Connection - bool mbCommited; ///< True when commit has been called + Database& mDatabase; ///< Reference to the SQLite Database Connection + bool mbCommited{ false }; ///< True when commit has been called }; diff --git a/src/Backup.cpp b/src/Backup.cpp index 183d314..92920d8 100644 --- a/src/Backup.cpp +++ b/src/Backup.cpp @@ -24,10 +24,10 @@ Backup::Backup(Database& aDestDatabase, Database& aSrcDatabase, const char* apSrcDatabaseName) { - mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), + mpSQLiteBackup.reset(sqlite3_backup_init(aDestDatabase.getHandle(), apDestDatabaseName, aSrcDatabase.getHandle(), - apSrcDatabaseName); + apSrcDatabaseName)); if (nullptr == mpSQLiteBackup) { // If an error occurs, the error code and message are attached to the destination database connection. @@ -48,19 +48,10 @@ Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) : { } -// Release resource for SQLite database backup -Backup::~Backup() -{ - if (mpSQLiteBackup) - { - sqlite3_backup_finish(mpSQLiteBackup); - } -} - // Execute backup step with a given number of source pages to be copied int Backup::executeStep(const int aNumPage /* = -1 */) { - const int res = sqlite3_backup_step(mpSQLiteBackup, aNumPage); + const int res = sqlite3_backup_step(mpSQLiteBackup.get(), aNumPage); if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res) { throw SQLite::Exception(sqlite3_errstr(res), res); @@ -69,15 +60,24 @@ int Backup::executeStep(const int aNumPage /* = -1 */) } // Get the number of remaining source pages to be copied in this backup process -int Backup::getRemainingPageCount() +int Backup::getRemainingPageCount() const { - return sqlite3_backup_remaining(mpSQLiteBackup); + return sqlite3_backup_remaining(mpSQLiteBackup.get()); } // Get the number of total source pages to be copied in this backup process -int Backup::getTotalPageCount() +int Backup::getTotalPageCount() const { - return sqlite3_backup_pagecount(mpSQLiteBackup); + return sqlite3_backup_pagecount(mpSQLiteBackup.get()); +} + +// Release resource for SQLite database backup +void SQLite::Backup::Deleter::operator()(sqlite3_backup* apBackup) +{ + if (apBackup) + { + sqlite3_backup_finish(apBackup); + } } } // namespace SQLite diff --git a/src/Column.cpp b/src/Column.cpp index f5dc0d9..01550a0 100644 --- a/src/Column.cpp +++ b/src/Column.cpp @@ -78,7 +78,7 @@ double Column::getDouble() const noexcept const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept { auto pText = reinterpret_cast(sqlite3_column_text(mStmtPtr.get(), mIndex)); - return (pText?pText:apDefaultValue); + return (pText ? pText : apDefaultValue); } // Return a pointer to the blob value (*not* NULL terminated) of the column specified by its index starting at 0 diff --git a/src/Database.cpp b/src/Database.cpp index eb76c88..d787cf2 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -27,6 +27,7 @@ namespace SQLite { +const int OK = SQLITE_OK; const int OPEN_READONLY = SQLITE_OPEN_READONLY; const int OPEN_READWRITE = SQLITE_OPEN_READWRITE; const int OPEN_CREATE = SQLITE_OPEN_CREATE; @@ -42,10 +43,8 @@ const int OPEN_NOFOLLOW = SQLITE_OPEN_NOFOLLOW; const int OPEN_NOFOLLOW = 0; #endif -const int OK = SQLITE_OK; - -const char* VERSION = SQLITE_VERSION; -const int VERSION_NUMBER = SQLITE_VERSION_NUMBER; +const char* const VERSION = SQLITE_VERSION; +const int VERSION_NUMBER = SQLITE_VERSION_NUMBER; // Return SQLite version string using runtime call to the compiled library const char* getLibVersion() noexcept @@ -142,7 +141,7 @@ Column Database::execAndGet(const char* apQuery) } // Shortcut to test if a table exists. -bool Database::tableExists(const char* apTableName) +bool Database::tableExists(const char* apTableName) const { Statement query(*this, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?"); query.bind(1, apTableName); @@ -439,8 +438,8 @@ void Database::backup(const char* apFilename, BackupType aType) Database otherDatabase(apFilename, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); // For a 'Save' operation, data is copied from the current Database to the other. A 'Load' is the reverse. - Database& src = (aType == Save ? *this : otherDatabase); - Database& dest = (aType == Save ? otherDatabase : *this); + Database& src = (aType == BackupType::Save ? *this : otherDatabase); + Database& dest = (aType == BackupType::Save ? otherDatabase : *this); // Set up the backup procedure to copy between the "main" databases of each connection Backup bkp(dest, src); diff --git a/src/Savepoint.cpp b/src/Savepoint.cpp index b3d13a2..2475a09 100644 --- a/src/Savepoint.cpp +++ b/src/Savepoint.cpp @@ -18,8 +18,8 @@ namespace SQLite { // Begins the SQLite savepoint -Savepoint::Savepoint(Database& aDatabase, std::string aName) - : mDatabase(aDatabase), msName(aName), mbReleased(false) { +Savepoint::Savepoint(Database& aDatabase, const std::string& aName) + : mDatabase(aDatabase), msName(aName) { // workaround because you cannot bind to SAVEPOINT // escape name for use in query Statement stmt(mDatabase, "SELECT quote(?)"); diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 2a8857a..abfb9b8 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -21,8 +21,7 @@ namespace SQLite // Begins the SQLite transaction Transaction::Transaction(Database& aDatabase, TransactionBehavior behavior) : - mDatabase(aDatabase), - mbCommited(false) + mDatabase(aDatabase) { const char *stmt; switch (behavior) { @@ -43,8 +42,7 @@ Transaction::Transaction(Database& aDatabase, TransactionBehavior behavior) : // Begins the SQLite transaction Transaction::Transaction(Database &aDatabase) : - mDatabase(aDatabase), - mbCommited(false) + mDatabase(aDatabase) { mDatabase.exec("BEGIN"); } From 04a4c2e8ef8b487ba474550a00153b01078a6a4c Mon Sep 17 00:00:00 2001 From: Kacperos155 Date: Sat, 23 Jul 2022 16:12:44 +0200 Subject: [PATCH 6/8] Use transparent comparator in mColumnNames to avoid creating std::string when comparing --- include/SQLiteCpp/Statement.h | 2 +- src/Statement.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index 75ba757..4982352 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -703,7 +703,7 @@ private: bool mbDone{false}; //!< true when the last executeStep() had no more row to fetch /// Map of columns index by name (mutable so getColumnIndex can be const) - mutable std::map mColumnNames; + mutable std::map> mColumnNames{}; }; diff --git a/src/Statement.cpp b/src/Statement.cpp index 64e16d2..bef22b0 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -275,7 +275,7 @@ int Statement::getColumnIndex(const char* apName) const for (int i = 0; i < mColumnCount; ++i) { const char* pName = sqlite3_column_name(getPreparedStatement(), i); - mColumnNames[pName] = i; + mColumnNames.emplace(pName, i); } } @@ -288,7 +288,7 @@ int Statement::getColumnIndex(const char* apName) const return iIndex->second; } -const char * Statement::getColumnDeclaredType(const int aIndex) const +const char* Statement::getColumnDeclaredType(const int aIndex) const { checkIndex(aIndex); const char * result = sqlite3_column_decltype(getPreparedStatement(), aIndex); From 11f33af197094027052a387186548d95cb72c619 Mon Sep 17 00:00:00 2001 From: Kacperos155 Date: Sat, 23 Jul 2022 16:14:16 +0200 Subject: [PATCH 7/8] .gitignore: add ".vs " directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f22bfa2..e6ea691 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build example1 *.a +.vs/ .vscode/ /SQLiteCpp.sln *.ncb From accceeecb999cee40731ff6f8854a5f6f24c9872 Mon Sep 17 00:00:00 2001 From: Kacperos155 Date: Sun, 24 Jul 2022 18:54:00 +0200 Subject: [PATCH 8/8] Restore Backup destructor & small style changes --- include/SQLiteCpp/Backup.h | 11 +++----- include/SQLiteCpp/Column.h | 4 --- include/SQLiteCpp/Row.h | 47 +++++++++++++++++++++++++++++++++ include/SQLiteCpp/Savepoint.h | 2 +- include/SQLiteCpp/Statement.h | 8 +++--- include/SQLiteCpp/Transaction.h | 2 +- src/Backup.cpp | 27 ++++++++++--------- src/Row.cpp | 25 ++++++++++++++++++ 8 files changed, 96 insertions(+), 30 deletions(-) create mode 100644 include/SQLiteCpp/Row.h create mode 100644 src/Row.cpp diff --git a/include/SQLiteCpp/Backup.h b/include/SQLiteCpp/Backup.h index ac940cb..ea6f71f 100644 --- a/include/SQLiteCpp/Backup.h +++ b/include/SQLiteCpp/Backup.h @@ -96,6 +96,9 @@ public: Backup(const Backup&) = delete; Backup& operator=(const Backup&) = delete; + /// Release the SQLite Backup resource. + ~Backup(); + /** * @brief Execute a step of backup with a given number of source pages to be copied * @@ -118,13 +121,7 @@ public: int getTotalPageCount() const; private: - // Deleter functor to use with smart pointers to close the SQLite database backup in an RAII fashion. - struct Deleter - { - void operator()(sqlite3_backup* apBackup); - }; - - std::unique_ptr mpSQLiteBackup{}; ///< Pointer to SQLite Database Backup Handle + sqlite3_backup* mpSQLiteBackup = nullptr; ///< Pointer to SQLite Database Backup Handle }; } // namespace SQLite diff --git a/include/SQLiteCpp/Column.h b/include/SQLiteCpp/Column.h index bc349f9..2dee76d 100644 --- a/include/SQLiteCpp/Column.h +++ b/include/SQLiteCpp/Column.h @@ -56,10 +56,6 @@ public: */ explicit Column(const Statement::TStatementPtr& aStmtPtr, int aIndex); - // default destructor: the finalization will be done by the destructor of the last shared pointer - // default copy constructor and assignment operator are perfectly suited : - // they copy the Statement::Ptr which in turn increments the reference counter. - /** * @brief Return a pointer to the named assigned to this result column (potentially aliased) * diff --git a/include/SQLiteCpp/Row.h b/include/SQLiteCpp/Row.h new file mode 100644 index 0000000..8a20a6c --- /dev/null +++ b/include/SQLiteCpp/Row.h @@ -0,0 +1,47 @@ +/** + * @file Row.h + * @ingroup SQLiteCpp + * @brief TODO: + * + * Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com) + * Copyright (c) 2015-2021 Sebastien Rombauts (sebastien.rombauts@gmail.com) + * + * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt + * or copy at http://opensource.org/licenses/MIT) + */ +#pragma once + +#include + +#include + +// Forward declaration to avoid inclusion of in a header +struct sqlite3_stmt; +class Row; + +namespace SQLite +{ + + +class Row +{ +public: + Row(RowExecutor::TRowPtr apRow, std::size_t aID); + + /** + * @brief Test if the column value is NULL + * + * @param[in] aIndex Index of the column, starting at 0 + * + * @return true if the column value is NULL + * + * Throw an exception if the specified index is out of the [0, getColumnCount()) range. + */ + bool isColumnNull(const int aIndex) const; + +private: + RowExecutor::TRowWeakPtr mpRow; + std::size_t ID; +}; + +} // namespace SQLite diff --git a/include/SQLiteCpp/Savepoint.h b/include/SQLiteCpp/Savepoint.h index 14b25cc..681cde0 100644 --- a/include/SQLiteCpp/Savepoint.h +++ b/include/SQLiteCpp/Savepoint.h @@ -90,6 +90,6 @@ class Savepoint { private: Database& mDatabase; ///< Reference to the SQLite Database Connection std::string msName; ///< Name of the Savepoint - bool mbReleased{ false }; ///< True when release has been called + bool mbReleased = false; ///< True when release has been called }; } // namespace SQLite diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index 4982352..ce95893 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -698,12 +698,12 @@ private: std::string mQuery; //!< UTF-8 SQL Query sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle TStatementPtr mpPreparedStatement; //!< Shared Pointer to the prepared SQLite Statement Object - int mColumnCount{0}; //!< Number of columns in the result of the prepared statement - bool mbHasRow{false}; //!< true when a row has been fetched with executeStep() - bool mbDone{false}; //!< true when the last executeStep() had no more row to fetch + int mColumnCount = 0; //!< Number of columns in the result of the prepared statement + bool mbHasRow = false; //!< true when a row has been fetched with executeStep() + bool mbDone = false; //!< true when the last executeStep() had no more row to fetch /// Map of columns index by name (mutable so getColumnIndex can be const) - mutable std::map> mColumnNames{}; + mutable std::map> mColumnNames; }; diff --git a/include/SQLiteCpp/Transaction.h b/include/SQLiteCpp/Transaction.h index 0fdefea..a2198f9 100644 --- a/include/SQLiteCpp/Transaction.h +++ b/include/SQLiteCpp/Transaction.h @@ -88,7 +88,7 @@ public: private: Database& mDatabase; ///< Reference to the SQLite Database Connection - bool mbCommited{ false }; ///< True when commit has been called + bool mbCommited = false; ///< True when commit has been called }; diff --git a/src/Backup.cpp b/src/Backup.cpp index 92920d8..4c91e69 100644 --- a/src/Backup.cpp +++ b/src/Backup.cpp @@ -24,10 +24,10 @@ Backup::Backup(Database& aDestDatabase, Database& aSrcDatabase, const char* apSrcDatabaseName) { - mpSQLiteBackup.reset(sqlite3_backup_init(aDestDatabase.getHandle(), + mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), apDestDatabaseName, aSrcDatabase.getHandle(), - apSrcDatabaseName)); + apSrcDatabaseName); if (nullptr == mpSQLiteBackup) { // If an error occurs, the error code and message are attached to the destination database connection. @@ -48,10 +48,19 @@ Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) : { } +// Release resource for SQLite database backup +Backup::~Backup() +{ + if (mpSQLiteBackup) + { + sqlite3_backup_finish(mpSQLiteBackup); + } +} + // Execute backup step with a given number of source pages to be copied int Backup::executeStep(const int aNumPage /* = -1 */) { - const int res = sqlite3_backup_step(mpSQLiteBackup.get(), aNumPage); + const int res = sqlite3_backup_step(mpSQLiteBackup, aNumPage); if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res) { throw SQLite::Exception(sqlite3_errstr(res), res); @@ -62,22 +71,14 @@ int Backup::executeStep(const int aNumPage /* = -1 */) // Get the number of remaining source pages to be copied in this backup process int Backup::getRemainingPageCount() const { - return sqlite3_backup_remaining(mpSQLiteBackup.get()); + return sqlite3_backup_remaining(mpSQLiteBackup); } // Get the number of total source pages to be copied in this backup process int Backup::getTotalPageCount() const { - return sqlite3_backup_pagecount(mpSQLiteBackup.get()); + return sqlite3_backup_pagecount(mpSQLiteBackup); } -// Release resource for SQLite database backup -void SQLite::Backup::Deleter::operator()(sqlite3_backup* apBackup) -{ - if (apBackup) - { - sqlite3_backup_finish(apBackup); - } -} } // namespace SQLite diff --git a/src/Row.cpp b/src/Row.cpp new file mode 100644 index 0000000..0ddc0d1 --- /dev/null +++ b/src/Row.cpp @@ -0,0 +1,25 @@ +/** + * @file Row.cpp + * @ingroup SQLiteCpp + * @brief TODO: + * + * Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com) + * Copyright (c) 2015-2021 Sebastien Rombauts (sebastien.rombauts@gmail.com) + * + * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt + * or copy at http://opensource.org/licenses/MIT) + */ +#include + +#include + +#include + +namespace SQLite +{ + + + ; + + +} // namespace SQLite