diff --git a/CHANGELOG.md b/CHANGELOG.md index 679c9f4..bb3ff06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,157 +1,164 @@ -Mar 30 2012 -- Start of a new thin C++ SQLite wrapper - -Apr 2 2012 -- The wrapper is functionnal -- Added documentation and examples -- Publication on GitHub - -Version 0.1.0 - Apr 4 2012 -- Added a Database::exec() methode to execute simple SQL statement -- Added a version number like in sqlite3.h, starting with 0.1.0 - -Version 0.2.0 - Apr 11 2012 -- Added getLastInsertId() and setBusyTimout() -- Added bind() by name methods - -Version 0.3.0 - Apr 16 2012 -- Added an easy wrapper Database::execAngGet() - -Version 0.4.0 - Apr 23 2012 -- Added a Database::tableExists() easy to use function - -Dec 10 2012 -- Added a Statement::exec() method to execute a one-step query with no expected result - -Version 0.5.0 - March 9 2013 -- Added assert() on errors on destructors -- Added getBytes() -- Added getBlob(), getType() and isInteger/isFloat/isText/isBlob/isNull -- Added bind() for binary blob data - -Version 0.5.1 - April 7 2013 -- Added Column::getName() - -Version 0.6.0 - November 22 2013 -- Renamed Column::getName() to Column::getOriginName() -- Added Column::getName() - -Version 0.7.0 - January 9 2014 -- Added Database::createFunction() -- Added std::string version of existing APIs -- Improved CMake with more build options and Doxygen auto-detection - -Version 0.8.0 - February 26 2014 -- Database constructor support opening a database with a custom VFS (default to NULL) -- Changed Column::getText() to return empty string "" by default instead of NULL pointer (to handle std::string conversion) - -Version 1.0.0 - May 3 2015 -- Public headers file moved to include/ dir -- Added support to biicode in CMakeLists.txt -- Added Unit Tests -- Added aBusyTimeoutMs parameter to Database() constructors -- Added Database::getTotalChanges() -- Added Database::getErrorCode() -- Added Statement::clearBindings() -- Added Statement::getColumn(aName) -- Added Statement::getErrorCode() -- Added Statement::getColumnName(aIndex) -- Added Statement::getColumnOriginName(aIndex) - -Version 1.1.0 - May 18 2015 -- Fixed valgrind error on Database destructor -- Added Database::loadExtension - -Version 1.2.0 - September 9 2015 -- Fixed build with GCC 5.1.0 -- Fixed MSVC release build warning -- Fixed CppDepends warnings -- Updated documentation on installation -- Added Database::getHandle() - -Version 1.3.0 - November 1 2015 -- Fixed build with Visual Studio 2015 -- Further improvements to README -- Added Backup class - -Version 1.3.1 - February 10 2016 -- Swith Linux/Mac build to the provided SQLite3 C library -- Update SQLite3 from 3.8.8.3 to latest 3.10.2 (2016-01-20) -- Remove warnings -- Remove biicode support (defunct service, servers will shutdown the 16th of February 2016) - -Version 2.0.0 - July 25 2016 -- Update SQLite3 from 3.10.2 to latest 3.13 (2016-05-18) -- Move #include from headers to .cpp files only using forward declarations -- Add Database::VERSION to reach SQLITE_VERSION without including sqlite3.h in application code -- Add getLibVersion() and getLibVersionNumber() to get runtime version of the library -- Better exception messages when Statements fail PR #84 -- Variadic templates for bind() (C++14) PR #85 -- Add Statement::bindNoCopy() methods for strings, using SQLITE_STATIC to avoid internal copy by SQLite3 PR #86 -- Add Statement::bind() overload for uint32_t, and Column::getUint() and cast operator to uint32_t PR #86 -- Use the new SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION from SQLite 3.13 for security reason -- Rename Backup::remainingPageCount()/totalPageCount() to Backup::getRemainingPageCount()/getTotalPageCount() -- Remove Column::errmsg() method : use Database or Statement equivalents -- More unit tests, with code coverage status on the GitHub page -- Do not force MSVC to use static runtime if unit-tests are not build - -Version 2.1.0 - July 18 2017 -- Update SQLite3 from 3.13 to latest 3.19.3 (2017-06-08) -- Fixed Incompatibility in 3.19.0 (to use older SQLite version set the CMake variable SQLITE_USE_LEGACY_STRUCT) #125 -- Fixed link error (inline in cpp) and compiler warnings (unused variable...) #96 -- Added ability to open encrypted databases (using SQLCipher, eg. libsqlcipher-dev) #107 -- Added convenience functions for constructing objects from a row #114 -- Added CMake install step #118 -- Fix warnings #119 -- Make cpplint.py Python-3 compatible #120 -- Link libssp when targeted #100 -- Removed redundant const #102 - -Version 2.2.0 - Sept 19 2017 -- Update SQLite3 from 3.19.3 to latest 3.20.1 (2017-08-24) #143 -- Added tryExecuteStep and tryReset #142 -- Removed virtual keywords from destructors #140 -- Removed misplaced noexcept keyword #139 -- Improved Exception class C++ conformance #138 -- Fix warnings #134 -- Deprecated Statement::IsOk() to Statement::HasRow() - -Version 2.3.0 - March 3 2019 -- Update SQLite3 from 3.20.1 to latest 3.27.2 (2019-02-25) #183 #187 -- Add Statement binding for long int values #147 -- Allows long int for bind when used with name #148 -- More cmake instructions for Linux #151 -- Add comparison with sqlite_orm #141 -- Fix Statement::bind truncates long integer to 32 bits on x86_64 Linux #155 -- Add a move constructor to Database #157 -- Added tests for all MSVC compilers available on AppVeyor (2013, 2015, 2017) #169 -- Update VariadicBind.h #172 -- Better CMake compatibility #170 -- Add implicit cast operator to char and short types #179 #180 - -Version 2.4.0 - August 25 2019 -- Update SQLite3 from 3.27.2 to 3.29.0 (2019-07-10) #217 -- #191 CMake Warning line 299 -- #190 Implement move constructors -- #192 Add wrapper for bind parameter count -- #197 Add tuple_bind and execute_many (requested by #24) -- #199 Fix #156 misleading error message in exception from Statement::exec -- #201 Add Statement::getExpandedSQL() to get the SQL text of prepared statement with bound parameters expanded -- #211 Implement Database::backup() -- #215 Disable implicit fallthrough warning when building internal sqlite3 -- #216 Set PROJECT_VERSION to fix CMP0048 Policy warnings - -Version 2.5.0 - December 31 2019 -- Update SQLite3 from 3.29.0 to 3.30.1 (2019-10-10) -- 100% Unit Test coverage -- #212 fix sqlite3 compile properties (jzt) -- #219 Disable cast-function-type warning when building internal sqlite (zxey) -- #230 Fixed installation on other than Ubuntu GNU/Linux distributions (xvitaly) -- #228 use transitive compile definitions via cmake (BioDataAnalysis/emmenlau) -- #232 Added support of packaged GTest for running unit tests (xvitaly) -- #231 Added SOVERSION field for shared library (xvitaly) -- #229 Explicitly find and link against system sqlite library (xvitaly) -- #235 Added support for cmake dependencies and version information (BioDataAnalysis/emmenlau) -- #249 Added SQLite header parsing functionality and associated tests (patrick--) - +Mar 30 2012 +- Start of a new thin C++ SQLite wrapper + +Apr 2 2012 +- The wrapper is functionnal +- Added documentation and examples +- Publication on GitHub + +Version 0.1.0 - Apr 4 2012 +- Added a Database::exec() methode to execute simple SQL statement +- Added a version number like in sqlite3.h, starting with 0.1.0 + +Version 0.2.0 - Apr 11 2012 +- Added getLastInsertId() and setBusyTimout() +- Added bind() by name methods + +Version 0.3.0 - Apr 16 2012 +- Added an easy wrapper Database::execAngGet() + +Version 0.4.0 - Apr 23 2012 +- Added a Database::tableExists() easy to use function + +Dec 10 2012 +- Added a Statement::exec() method to execute a one-step query with no expected result + +Version 0.5.0 - March 9 2013 +- Added assert() on errors on destructors +- Added getBytes() +- Added getBlob(), getType() and isInteger/isFloat/isText/isBlob/isNull +- Added bind() for binary blob data + +Version 0.5.1 - April 7 2013 +- Added Column::getName() + +Version 0.6.0 - November 22 2013 +- Renamed Column::getName() to Column::getOriginName() +- Added Column::getName() + +Version 0.7.0 - January 9 2014 +- Added Database::createFunction() +- Added std::string version of existing APIs +- Improved CMake with more build options and Doxygen auto-detection + +Version 0.8.0 - February 26 2014 +- Database constructor support opening a database with a custom VFS (default to NULL) +- Changed Column::getText() to return empty string "" by default instead of NULL pointer (to handle std::string conversion) + +Version 1.0.0 - May 3 2015 +- Public headers file moved to include/ dir +- Added support to biicode in CMakeLists.txt +- Added Unit Tests +- Added aBusyTimeoutMs parameter to Database() constructors +- Added Database::getTotalChanges() +- Added Database::getErrorCode() +- Added Statement::clearBindings() +- Added Statement::getColumn(aName) +- Added Statement::getErrorCode() +- Added Statement::getColumnName(aIndex) +- Added Statement::getColumnOriginName(aIndex) + +Version 1.1.0 - May 18 2015 +- Fixed valgrind error on Database destructor +- Added Database::loadExtension + +Version 1.2.0 - September 9 2015 +- Fixed build with GCC 5.1.0 +- Fixed MSVC release build warning +- Fixed CppDepends warnings +- Updated documentation on installation +- Added Database::getHandle() + +Version 1.3.0 - November 1 2015 +- Fixed build with Visual Studio 2015 +- Further improvements to README +- Added Backup class + +Version 1.3.1 - February 10 2016 +- Swith Linux/Mac build to the provided SQLite3 C library +- Update SQLite3 from 3.8.8.3 to latest 3.10.2 (2016-01-20) +- Remove warnings +- Remove biicode support (defunct service, servers will shutdown the 16th of February 2016) + +Version 2.0.0 - July 25 2016 +- Update SQLite3 from 3.10.2 to latest 3.13 (2016-05-18) +- Move #include from headers to .cpp files only using forward declarations +- Add Database::VERSION to reach SQLITE_VERSION without including sqlite3.h in application code +- Add getLibVersion() and getLibVersionNumber() to get runtime version of the library +- Better exception messages when Statements fail PR #84 +- Variadic templates for bind() (C++14) PR #85 +- Add Statement::bindNoCopy() methods for strings, using SQLITE_STATIC to avoid internal copy by SQLite3 PR #86 +- Add Statement::bind() overload for uint32_t, and Column::getUint() and cast operator to uint32_t PR #86 +- Use the new SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION from SQLite 3.13 for security reason +- Rename Backup::remainingPageCount()/totalPageCount() to Backup::getRemainingPageCount()/getTotalPageCount() +- Remove Column::errmsg() method : use Database or Statement equivalents +- More unit tests, with code coverage status on the GitHub page +- Do not force MSVC to use static runtime if unit-tests are not build + +Version 2.1.0 - July 18 2017 +- Update SQLite3 from 3.13 to latest 3.19.3 (2017-06-08) +- Fixed Incompatibility in 3.19.0 (to use older SQLite version set the CMake variable SQLITE_USE_LEGACY_STRUCT) #125 +- Fixed link error (inline in cpp) and compiler warnings (unused variable...) #96 +- Added ability to open encrypted databases (using SQLCipher, eg. libsqlcipher-dev) #107 +- Added convenience functions for constructing objects from a row #114 +- Added CMake install step #118 +- Fix warnings #119 +- Make cpplint.py Python-3 compatible #120 +- Link libssp when targeted #100 +- Removed redundant const #102 + +Version 2.2.0 - Sept 19 2017 +- Update SQLite3 from 3.19.3 to latest 3.20.1 (2017-08-24) #143 +- Added tryExecuteStep and tryReset #142 +- Removed virtual keywords from destructors #140 +- Removed misplaced noexcept keyword #139 +- Improved Exception class C++ conformance #138 +- Fix warnings #134 +- Deprecated Statement::isOk() to Statement::hasRow() + +Version 2.3.0 - March 3 2019 +- Update SQLite3 from 3.20.1 to latest 3.27.2 (2019-02-25) #183 #187 +- Add Statement binding for long int values #147 +- Allows long int for bind when used with name #148 +- More cmake instructions for Linux #151 +- Add comparison with sqlite_orm #141 +- Fix Statement::bind truncates long integer to 32 bits on x86_64 Linux #155 +- Add a move constructor to Database #157 +- Added tests for all MSVC compilers available on AppVeyor (2013, 2015, 2017) #169 +- Update VariadicBind.h #172 +- Better CMake compatibility #170 +- Add implicit cast operator to char and short types #179 #180 + +Version 2.4.0 - August 25 2019 +- Update SQLite3 from 3.27.2 to 3.29.0 (2019-07-10) #217 +- #191 CMake Warning line 299 +- #190 Implement move constructors +- #192 Add wrapper for bind parameter count +- #197 Add tuple_bind and execute_many (requested by #24) +- #199 Fix #156 misleading error message in exception from Statement::exec +- #201 Add Statement::getExpandedSQL() to get the SQL text of prepared statement with bound parameters expanded +- #211 Implement Database::backup() +- #215 Disable implicit fallthrough warning when building internal sqlite3 +- #216 Set PROJECT_VERSION to fix CMP0048 Policy warnings + +Version 2.5.0 - December 31 2019 +- Update SQLite3 from 3.29.0 to 3.30.1 (2019-10-10) +- 100% Unit Test coverage +- #212 fix sqlite3 compile properties (jzt) +- #219 Disable cast-function-type warning when building internal sqlite (zxey) +- #230 Fixed installation on other than Ubuntu GNU/Linux distributions (xvitaly) +- #228 use transitive compile definitions via cmake (BioDataAnalysis/emmenlau) +- #232 Added support of packaged GTest for running unit tests (xvitaly) +- #231 Added SOVERSION field for shared library (xvitaly) +- #229 Explicitly find and link against system sqlite library (xvitaly) +- #235 Added support for cmake dependencies and version information (BioDataAnalysis/emmenlau) +- #249 Added SQLite header parsing functionality and associated tests (patrick--) + - #251 Added example for getHeaderInfo() + +Version 3.0.0 - January 1 2020 +- C++11 minimum +- CMake 3.1 minimum +- Visual Studio 2015 minimum +- Googletest 1.10 +- Remove Statement::isOk() deprecated in 2.2.0 when renamed to Statement::hasRow() diff --git a/CMakeLists.txt b/CMakeLists.txt index 31a0dd5..32e2a96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,19 +4,15 @@ # # Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt # or copy at http://opensource.org/licenses/MIT) -cmake_minimum_required(VERSION 2.8.12) # first version with add_compile_options() -if (CMAKE_VERSION VERSION_LESS 3.0) - project(SQLiteCpp) - set(PROJECT_VERSION_MAJOR 2) - set(PROJECT_VERSION_MINOR 5) - set(PROJECT_VERSION_PATCH 0) - set(PROJECT_VERSION "2.5.0") -else() - cmake_policy(SET CMP0048 NEW) - project(SQLiteCpp VERSION "2.5.0") -endif() +cmake_minimum_required(VERSION 3.1) # for "CMAKE_CXX_STANDARD" version +project(SQLiteCpp VERSION "2.99") + +# SQLiteC++ 3.x now requires C++11 compiler +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) message (STATUS "CMake version: ${CMAKE_VERSION}") +message (STATUS "Project version: ${PROJECT_VERSION}") # Define useful variables to handle OS differences: if (WIN32) @@ -39,9 +35,9 @@ if (MSVC) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") endif (SQLITECPP_BUILD_TESTS) - # Handle the (partly supported) MSVC versions prior to 2015 + # MSVC versions prior to 2015 are not supported anymore by SQLiteC++ 3.x if (MSVC_VERSION LESS 1900) # OR MSVC_TOOLSET_VERSION LESS 140) - message(WARNING "MSVC < 2015 detected: Visual Studio prior to 2015 is not fully supported. BLOB storage seems to be corrupted.") + message(ERROR "Visual Studio prior to 2015 is not supported anymore.") endif (MSVC_VERSION LESS 1900) else (MSVC) set(CPPLINT_ARG_OUTPUT "--output=eclipse") @@ -111,7 +107,6 @@ set(SQLITECPP_INC ${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Exception.h ${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Statement.h ${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Transaction.h - ${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Utils.h ${PROJECT_SOURCE_DIR}/include/SQLiteCpp/VariadicBind.h ${PROJECT_SOURCE_DIR}/include/SQLiteCpp/ExecuteMany.h ) @@ -145,9 +140,13 @@ set(SQLITECPP_DOC ) source_group(doc FILES ${SQLITECPP_DOC}) -# list of script files of the library +# list of config & script files of the library set(SQLITECPP_SCRIPT + .editorconfig + .gitbugtraq .github/workflows/actions.yml + .gitignore + .gitmodules .travis.yml appveyor.yml build.bat diff --git a/Doxyfile b/Doxyfile index 60bfb97..8a37ee4 100644 --- a/Doxyfile +++ b/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = SQLiteC++ # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2.5.0 +PROJECT_NUMBER = 3.0.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/README.md b/README.md index a4b2857..dd2f64a 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,8 @@ http://www.sqlite.org/about.html ### The goals of SQLiteC++ are: - to offer the best of the existing simple C++ SQLite wrappers -- to be elegantly written with good C++ design, STL, exceptions and RAII idiom -- to keep dependencies to a minimum (STL and SQLite3) +- to be elegantly written with good C++11 design, STL, exceptions and RAII idiom +- to keep dependencies to a minimum (C++11 STL and SQLite3) - to be portable - to be light and fast - to be thread-safe only as much as SQLite "Multi-thread" mode (see below) @@ -58,29 +58,32 @@ http://www.sqlite.org/about.html It is designed using the Resource Acquisition Is Initialization (RAII) idiom (see http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization), -and throwing exceptions in case of SQLite errors (exept in destructors, +and throwing exceptions in case of SQLite errors (except in destructors, where assert() are used instead). Each SQLiteC++ object must be constructed with a valid SQLite database connection, and then is always valid until destroyed. ### Supported platforms: -Developements and tests are done under the following OSs: -- Ubuntu 14.04 (Travis CI) +Now requires a C++11 compiler. Use branch [sqlitecpp-2.x](https://github.com/SRombauts/SQLiteCpp/tree/sqlitecpp-2.x) for latest pre-C++11 developments. + +Developments and tests are done under the following OSs: +- Ubuntu 14.04, 16.04 and 18.04 (Travis CI) - Windows 10, and Windows Server 2012 R2 & Windows Server 2016 (AppVeyor) - OS X 10.11 (Travis CI) +- Github Actions And the following IDEs/Compilers -- GCC 4.8.4, 4.9.3, 5.3.0 and 6.1.1 (C++03, C++11, C++14, C++1z) -- Clang 3.5 and 3.8 -- Xcode 8 +- GCC 4.8.4, 5.3.0 and 7.1.1 (C++11, C++14, C++17) +- Clang 5 +- Xcode 8 & 9 - Visual Studio Community 2019, 2017, and 2015 (AppVeyor) ### Dependencies -- an STL implementation (even an old one, like the one provided with VC6 should work) +- a modern C++11 STL implementation with GCC, Clang, or Visual Studio 2015 - exception support (the class Exception inherits from std::runtime_error) -- the SQLite library (3.7.15 minimum from 2012-12-12) either by linking to it dynamicaly or statically (install the libsqlite3-dev package under Debian/Ubuntu/Mint Linux), +- the SQLite library (3.7.15 minimum from 2012-12-12) either by linking to it dynamically or statically (install the libsqlite3-dev package under Debian/Ubuntu/Mint Linux), or by adding its source file in your project code base (source code provided in src/sqlite3 for Windows), with the SQLITE_ENABLE_COLUMN_METADATA macro defined (see http://www.sqlite.org/compile.html#enable_column_metadata). @@ -111,7 +114,7 @@ target_link_libraries(main dl ) ``` -Thus this SQLiteCpp repository can be directly used as a Git submoldule. +Thus this SQLiteCpp repository can be directly used as a Git submodule. See the [SQLiteCpp_Example](https://github.com/SRombauts/SQLiteCpp_Example) side repository for a standalone "from scratch" example. Under Debian/Ubuntu/Mint Linux, you can install the libsqlite3-dev package if you don't want to use the embedded sqlite3 library. @@ -128,7 +131,7 @@ git submodule update ``` #### CMake and tests -A CMake configuration file is also provided for multiplatform support and testing. +A CMake configuration file is also provided for multi-platform support and testing. Typical generic build for MS Visual Studio under Windows (from [build.bat](build.bat)): @@ -136,7 +139,7 @@ Typical generic build for MS Visual Studio under Windows (from [build.bat](build mkdir build cd build -cmake .. # cmake .. -G "Visual Studio 10" # for Visual Studio 2010 +cmake .. # cmake .. -G "Visual Studio 16 2019" # for Visual Studio 2019 @REM Generate a Visual Studio solution for latest version found cmake -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON .. @@ -169,7 +172,7 @@ ctest --output-on-failure #### Troubleshooting -Under Linux, if you get muliple linker errors like "undefined reference to sqlite3_xxx", +Under Linux, if you get multiple linker errors like "undefined reference to sqlite3_xxx", it's that you lack the "sqlite3" library: install the libsqlite3-dev package. If you get a single linker error "Column.cpp: undefined reference to sqlite3_column_origin_name", @@ -186,7 +189,7 @@ You can either recompile it yourself (seek help online) or you can comment out t This project is continuously tested under Ubuntu Linux with the gcc and clang compilers using the Travis CI community service with the above CMake building and testing procedure. It is also tested in the same way under Windows Server 2012 R2 with Visual Studio 2013 compiler -using the AppVeyor countinuous integration service. +using the AppVeyor continuous integration service. Detailed results can be seen online: - https://travis-ci.org/SRombauts/SQLiteCpp diff --git a/TODO.txt b/TODO.txt index 736868c..6af0968 100644 --- a/TODO.txt +++ b/TODO.txt @@ -7,11 +7,10 @@ Improve Github Wiki pages with the FAQ: Installation, Examples, Tutorial, How to Publish the Doxygen Documentation in the Github Pages (gh-pages branch) Missing features in v2.0.0: -- #24: executemany() like in Python https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.executemany - #34: Better type for getColumn Missing documentation in v2.0.0: -- explain the noncopyable property for RAII design +- explain the non-copyable property for RAII design - comment on returning error code instead of exception that shall not be thrown when expected (!?) Missing unit tests in v2.0.0: @@ -21,7 +20,7 @@ Advanced missing features: - #39: SAVEPOINT https://www.sqlite.org/lang_savepoint.html - Add optional usage of experimental sqlite3_trace() function to enable statistics -- Agregate ? +- Aggregate ? - support for different transaction mode ? NO: too specific - operator<< binding ? NO: redundant with bind() diff --git a/include/SQLiteCpp/Backup.h b/include/SQLiteCpp/Backup.h index 22e6ce3..70ae62f 100644 --- a/include/SQLiteCpp/Backup.h +++ b/include/SQLiteCpp/Backup.h @@ -99,6 +99,10 @@ public: Backup(Database& aDestDatabase, Database& aSrcDatabase); + // Backup is non-copyable + Backup(const Backup&) = delete; + Backup& operator=(const Backup&) = delete; + /// Release the SQLite Backup resource. ~Backup(); @@ -124,13 +128,8 @@ public: int getTotalPageCount(); private: - /// @{ Backup must be non-copyable - Backup(const Backup&); - Backup& operator=(const Backup&); - /// @} - -private: - sqlite3_backup* mpSQLiteBackup; ///< Pointer to SQLite Database Backup Handle + // TODO: use std::unique_ptr with a custom deleter to call sqlite3_backup_finish() + 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 58700b2..48a9ee8 100644 --- a/include/SQLiteCpp/Column.h +++ b/include/SQLiteCpp/Column.h @@ -52,26 +52,18 @@ public: * @param[in] aStmtPtr Shared pointer to the prepared SQLite Statement Object. * @param[in] aIndex Index of the column in the row of result, starting at 0 */ - Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept; // nothrow - /// Simple destructor - ~Column(); + Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept; + // 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. - /// Make clang happy by explicitly implementing the copy-constructor: - Column(const Column & aOther) : - mStmtPtr(aOther.mStmtPtr), - mIndex(aOther.mIndex) - { - } - /** * @brief Return a pointer to the named assigned to this result column (potentially aliased) * * @see getOriginName() to get original column name (not aliased) */ - const char* getName() const noexcept; // nothrow + const char* getName() const noexcept; #ifdef SQLITE_ENABLE_COLUMN_METADATA /** @@ -81,31 +73,31 @@ public: * - when building the SQLite library itself (which is the case for the Debian libsqlite3 binary for instance), * - and also when compiling this wrapper. */ - const char* getOriginName() const noexcept; // nothrow + const char* getOriginName() const noexcept; #endif /// Return the integer value of the column. - int getInt() const noexcept; // nothrow + int getInt() const noexcept; /// Return the 32bits unsigned integer value of the column (note that SQLite3 does not support unsigned 64bits). - unsigned getUInt() const noexcept; // nothrow + unsigned getUInt() const noexcept; /// Return the 64bits integer value of the column (note that SQLite3 does not support unsigned 64bits). - long long getInt64() const noexcept; // nothrow + long long getInt64() const noexcept; /// Return the double (64bits float) value of the column - double getDouble() const noexcept; // nothrow + double getDouble() const noexcept; /** * @brief Return a pointer to the text value (NULL terminated string) of the column. * * @warning The value pointed at is only valid while the statement is valid (ie. not finalized), * thus you must copy it before using it beyond its scope (to a std::string for instance). */ - const char* getText(const char* apDefaultValue = "") const noexcept; // nothrow + const char* getText(const char* apDefaultValue = "") const noexcept; /** * @brief Return a pointer to the binary blob value of the column. * * @warning The value pointed at is only valid while the statement is valid (ie. not finalized), * thus you must copy it before using it beyond its scope (to a std::string for instance). */ - const void* getBlob() const noexcept; // nothrow + const void* getBlob() const noexcept; /** * @brief Return a std::string for a TEXT or BLOB column. * @@ -121,30 +113,30 @@ public: * @warning After a type conversion (by a call to a getXxx on a Column of a Yyy type), * the value returned by sqlite3_column_type() is undefined. */ - int getType() const noexcept; // nothrow + int getType() const noexcept; /// Test if the column is an integer type value (meaningful only before any conversion) - inline bool isInteger() const noexcept // nothrow + bool isInteger() const noexcept { return (SQLite::INTEGER == getType()); } /// Test if the column is a floating point type value (meaningful only before any conversion) - inline bool isFloat() const noexcept // nothrow + bool isFloat() const noexcept { return (SQLite::FLOAT == getType()); } /// Test if the column is a text type value (meaningful only before any conversion) - inline bool isText() const noexcept // nothrow + bool isText() const noexcept { return (SQLite::TEXT == getType()); } /// Test if the column is a binary blob type value (meaningful only before any conversion) - inline bool isBlob() const noexcept // nothrow + bool isBlob() const noexcept { return (SQLite::BLOB == getType()); } /// Test if the column is NULL (meaningful only before any conversion) - inline bool isNull() const noexcept // nothrow + bool isNull() const noexcept { return (SQLite::Null == getType()); } @@ -161,68 +153,68 @@ public: int getBytes() const noexcept; /// Alias returning the number of bytes used by the text (or blob) value of the column - inline int size() const noexcept + int size() const noexcept { return getBytes (); } /// Inline cast operator to char - inline operator char() const + operator char() const { return static_cast(getInt()); } /// Inline cast operator to unsigned char - inline operator unsigned char() const + operator unsigned char() const { return static_cast(getInt()); } /// Inline cast operator to short - inline operator short() const + operator short() const { return static_cast(getInt()); } /// Inline cast operator to unsigned short - inline operator unsigned short() const + operator unsigned short() const { return static_cast(getInt()); } /// Inline cast operator to int - inline operator int() const + operator int() const { return getInt(); } /// Inline cast operator to 32bits unsigned integer - inline operator unsigned int() const + operator unsigned int() const { return getUInt(); } #if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW) /// Inline cast operator to 32bits long - inline operator long() const + operator long() const { return getInt(); } /// Inline cast operator to 32bits unsigned long - inline operator unsigned long() const + operator unsigned long() const { return getUInt(); } #else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS) /// Inline cast operator to 64bits long when the data model of the system is LP64 (Linux 64 bits...) - inline operator long() const + operator long() const { return getInt64(); } #endif /// Inline cast operator to 64bits integer - inline operator long long() const + operator long long() const { return getInt64(); } /// Inline cast operator to double - inline operator double() const + operator double() const { return getDouble(); } @@ -231,7 +223,7 @@ public: * * @see getText */ - inline operator const char*() const + operator const char*() const { return getText(); } @@ -240,21 +232,11 @@ public: * * @see getBlob */ - inline operator const void*() const + operator const void*() const { return getBlob(); } -#if !defined(_MSC_VER) || _MSC_VER >= 1900 - // NOTE : the following is required by GCC and Clang to cast a Column result in a std::string - // (error: conversion from ‘SQLite::Column’ to non-scalar type ‘std::string {aka std::basic_string}’) - // and also required for Microsoft Visual Studio 2015 and newer - // but is not working under Microsoft Visual Studio 2010, 2012 and 2013 - // (error C2440: 'initializing' : cannot convert from 'SQLite::Column' to 'std::basic_string<_Elem,_Traits,_Ax>' - // [...] constructor overload resolution was ambiguous) - // WARNING: without it, trying to access a binary blob with implicit cast to string - // ends up converting it to a C-style char*, damaging the data by truncating it to the first null character! - // (see https://github.com/SRombauts/SQLiteCpp/issues/189 Visual Studio 2013: unit test "Column.basis" failing) /** * @brief Inline cast operator to std::string * @@ -262,11 +244,10 @@ public: * * @see getString */ - inline operator std::string() const + operator std::string() const { return getString(); } -#endif private: Statement::Ptr mStmtPtr; ///< Shared Pointer to the prepared SQLite Statement Object @@ -285,7 +266,7 @@ private: */ std::ostream& operator<<(std::ostream& aStream, const Column& aColumn); -#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) +#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) // c++14: Visual Studio 2015 // Create an instance of T from the first N columns, see declaration in Statement.h for full details template diff --git a/include/SQLiteCpp/Database.h b/include/SQLiteCpp/Database.h index 1e8d139..6921245 100644 --- a/include/SQLiteCpp/Database.h +++ b/include/SQLiteCpp/Database.h @@ -11,7 +11,6 @@ #pragma once #include -#include // definition of nullptr for C++98/C++03 compilers #include // Forward declarations to avoid inclusion of in a header @@ -42,15 +41,15 @@ extern const int OPEN_CREATE; // SQLITE_OPEN_CREATE /// Enable URI filename interpretation, parsed according to RFC 3986 (ex. "file:data.db?mode=ro&cache=private") extern const int OPEN_URI; // SQLITE_OPEN_URI -extern const int OK; ///< SQLITE_OK (used by inline check() bellow) +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 /// Return SQLite version string using runtime call to the compiled library -const char* getLibVersion() noexcept; // nothrow +const char* getLibVersion() noexcept; /// Return SQLite version number using runtime call to the compiled library -int getLibVersionNumber() noexcept; // nothrow +int getLibVersionNumber() noexcept; // Public structure for representing all fields contained within the SQLite header. // Official documentation for fields: https://www.sqlite.org/fileformat.html#the_database_header @@ -143,21 +142,26 @@ public: Database(const std::string& aFilename, const int aFlags = SQLite::OPEN_READONLY, const int aBusyTimeoutMs = 0, - const std::string& aVfs = ""); + const std::string& aVfs = "") : + Database(aFilename.c_str(), aFlags, aBusyTimeoutMs, aVfs.empty() ? nullptr : aVfs.c_str()) + { + } -#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) /** * @brief Move an SQLite database connection. * * @param[in] aDatabase Database to move */ - inline Database(Database&& aDatabase) noexcept : + Database(Database&& aDatabase) noexcept : mpSQLite(aDatabase.mpSQLite), mFilename(std::move(aDatabase.mFilename)) { aDatabase.mpSQLite = nullptr; } -#endif + + // Database is non-copyable + Database(const Database&) = delete; + Database& operator=(const Database&) = delete; /** * @brief Close the SQLite database connection. @@ -165,6 +169,8 @@ public: * All SQLite statements must have been finalized before, * so all Statement objects must have been unregistered. * + * TODO: revisit this design, to perhaps switch to having Statement sharing a pointer to the Database? + * * @warning assert in case of error */ ~Database(); @@ -222,7 +228,7 @@ public: * * @throw SQLite::Exception in case of error */ - inline int exec(const std::string& aQueries) + int exec(const std::string& aQueries) { return exec(aQueries.c_str()); } @@ -267,7 +273,7 @@ public: * * @throw SQLite::Exception in case of error */ - inline Column execAndGet(const std::string& aQuery) + Column execAndGet(const std::string& aQuery) { return execAndGet(aQuery.c_str()); } @@ -296,7 +302,7 @@ public: * * @throw SQLite::Exception in case of error */ - inline bool tableExists(const std::string& aTableName) + bool tableExists(const std::string& aTableName) { return tableExists(aTableName.c_str()); } @@ -309,20 +315,20 @@ public: * * @return Rowid of the most recent successful INSERT into the database, or 0 if there was none. */ - long long getLastInsertRowid() const noexcept; // nothrow + long long getLastInsertRowid() const noexcept; /// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection (not DROP table). - int getTotalChanges() const noexcept; // nothrow + int getTotalChanges() const noexcept; /// Return the numeric result code for the most recent failed API call (if any). - int getErrorCode() const noexcept; // nothrow + int getErrorCode() const noexcept; /// Return the extended numeric result code for the most recent failed API call (if any). - int getExtendedErrorCode() const noexcept; // nothrow + int getExtendedErrorCode() const noexcept; /// Return UTF-8 encoded English language explanation of the most recent failed API call (if any). - const char* getErrorMsg() const noexcept; // nothrow + const char* getErrorMsg() const noexcept; /// Return the filename used to open the database. - const std::string& getFilename() const noexcept // nothrow + const std::string& getFilename() const noexcept { return mFilename; } @@ -332,7 +338,7 @@ public: * * This is often needed to mix this wrapper with other libraries or for advance usage not supported by SQLiteCpp. */ - inline sqlite3* getHandle() const noexcept // nothrow + sqlite3* getHandle() const noexcept { return mpSQLite; } @@ -384,7 +390,7 @@ public: * * @throw SQLite::Exception in case of error */ - inline void createFunction(const std::string& aFuncName, + void createFunction(const std::string& aFuncName, int aNbArg, bool abDeterministic, void* apApp, @@ -490,16 +496,10 @@ public: */ int backup(const char* zFilename, BackupType type); -private: - /// @{ Database must be non-copyable - Database(const Database&); - Database& operator=(const Database&); - /// @} - /** * @brief Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message */ - inline void check(const int aRet) const + void check(const int aRet) const { if (SQLite::OK != aRet) { @@ -508,6 +508,7 @@ private: } private: + // TODO: use std::unique_ptr with a custom deleter to call sqlite3_close() sqlite3* mpSQLite; ///< Pointer to SQLite Database Connection Handle std::string mFilename; ///< UTF-8 filename used to open the database }; diff --git a/include/SQLiteCpp/Exception.h b/include/SQLiteCpp/Exception.h index 15981af..4bd0003 100644 --- a/include/SQLiteCpp/Exception.h +++ b/include/SQLiteCpp/Exception.h @@ -16,25 +16,6 @@ // Forward declaration to avoid inclusion of in a header struct sqlite3; -/// Compatibility with non-clang compilers. -#ifndef __has_feature - #define __has_feature(x) 0 -#endif - -// Detect whether the compiler supports C++11 noexcept exception specifications. -#if ( defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4)) \ - && defined(__GXX_EXPERIMENTAL_CXX0X__)) -// GCC 4.7 and following have noexcept -#elif defined(__clang__) && __has_feature(cxx_noexcept) -// Clang 3.0 and above have noexcept -#elif defined(_MSC_VER) && _MSC_VER > 1800 -// Visual Studio 2015 and above have noexcept -#else - // Visual Studio 2013 does not support noexcept, and "throw()" is deprecated by C++11 - #define noexcept -#endif - - namespace SQLite { @@ -49,18 +30,28 @@ public: * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. * * @param[in] aErrorMessage The string message describing the SQLite error + * @param[in] ret Return value from function call that failed. */ - explicit Exception(const char* aErrorMessage); - explicit Exception(const std::string& aErrorMessage); + Exception(const char* aErrorMessage, int ret); + + Exception(const std::string& aErrorMessage, int ret) : + Exception(aErrorMessage.c_str(), ret) + { + } /** * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. * * @param[in] aErrorMessage The string message describing the SQLite error - * @param[in] ret Return value from function call that failed. */ - Exception(const char* aErrorMessage, int ret); - Exception(const std::string& aErrorMessage, int ret); + explicit Exception(const char* aErrorMessage) : + Exception(aErrorMessage, -1) // 0 would be SQLITE_OK, which doesn't make sense + { + } + explicit Exception(const std::string& aErrorMessage) : + Exception(aErrorMessage.c_str(), -1) // 0 would be SQLITE_OK, which doesn't make sense + { + } /** * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. @@ -78,19 +69,19 @@ public: Exception(sqlite3* apSQLite, int ret); /// Return the result code (if any, otherwise -1). - inline int getErrorCode() const noexcept // nothrow + int getErrorCode() const noexcept { return mErrcode; } /// Return the extended numeric result code (if any, otherwise -1). - inline int getExtendedErrorCode() const noexcept // nothrow + int getExtendedErrorCode() const noexcept { return mExtendedErrcode; } /// Return a string, solely based on the error code - const char* getErrorStr() const noexcept; // nothrow + const char* getErrorStr() const noexcept; private: int mErrcode; ///< Error code value diff --git a/include/SQLiteCpp/SQLiteCpp.h b/include/SQLiteCpp/SQLiteCpp.h index c6a53c6..4c1ee46 100644 --- a/include/SQLiteCpp/SQLiteCpp.h +++ b/include/SQLiteCpp/SQLiteCpp.h @@ -40,5 +40,5 @@ * * WARNING: shall always be updated in sync with PROJECT_VERSION in CMakeLists.txt */ -#define SQLITECPP_VERSION "2.05.00" // 2.5.0 -#define SQLITECPP_VERSION_NUMBER 2005000 // 2.5.0 +#define SQLITECPP_VERSION "3.00.00" // 3.0.0 +#define SQLITECPP_VERSION_NUMBER 3000000 // 3.0.0 diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index e8fc608..5e741d7 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -71,19 +71,24 @@ public: * * Exception is thrown in case of error, then the Statement object is NOT constructed. */ - Statement(Database& aDatabase, const std::string& aQuery); + Statement(Database &aDatabase, const std::string& aQuery) : + Statement(aDatabase, aQuery.c_str()) + {} -#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) /** * @brief Move an SQLite statement. * * @param[in] aStatement Statement to move */ Statement(Statement&& aStatement) noexcept; -#endif + + // Statement is non-copyable + Statement(const Statement&) = delete; + Statement& operator=(const Statement&) = delete; /// Finalize and unregister the SQL query from the SQLite Database Connection. - ~Statement(); + /// The finalization will be done by the destructor of the last shared pointer + ~Statement() = default; /// Reset the statement to make it ready for a new execution. Throws an exception on error. void reset(); @@ -283,14 +288,14 @@ public: /** * @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) */ - inline void bind(const std::string& aName, const int aValue) + void bind(const std::string& aName, const int aValue) { bind(aName.c_str(), aValue); } /** * @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) */ - inline void bind(const std::string& aName, const unsigned aValue) + void bind(const std::string& aName, const unsigned aValue) { bind(aName.c_str(), aValue); } @@ -315,14 +320,14 @@ public: /** * @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) */ - inline void bind(const std::string& aName, const long long aValue) + void bind(const std::string& aName, const long long aValue) { bind(aName.c_str(), aValue); } /** * @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) */ - inline void bind(const std::string& aName, const double aValue) + void bind(const std::string& aName, const double aValue) { bind(aName.c_str(), aValue); } @@ -331,7 +336,7 @@ public: * * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use */ - inline void bind(const std::string& aName, const std::string& aValue) + void bind(const std::string& aName, const std::string& aValue) { bind(aName.c_str(), aValue); } @@ -340,7 +345,7 @@ public: * * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use */ - inline void bind(const std::string& aName, const char* apValue) + void bind(const std::string& aName, const char* apValue) { bind(aName.c_str(), apValue); } @@ -349,7 +354,7 @@ public: * * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use */ - inline void bind(const std::string& aName, const void* apValue, const int aSize) + void bind(const std::string& aName, const void* apValue, const int aSize) { bind(aName.c_str(), apValue, aSize); } @@ -360,7 +365,7 @@ public: * * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. */ - inline void bindNoCopy(const std::string& aName, const std::string& aValue) + void bindNoCopy(const std::string& aName, const std::string& aValue) { bindNoCopy(aName.c_str(), aValue); } @@ -371,7 +376,7 @@ public: * * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. */ - inline void bindNoCopy(const std::string& aName, const char* apValue) + void bindNoCopy(const std::string& aName, const char* apValue) { bindNoCopy(aName.c_str(), apValue); } @@ -380,7 +385,7 @@ public: * * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. */ - inline void bindNoCopy(const std::string& aName, const void* apValue, const int aSize) + void bindNoCopy(const std::string& aName, const void* apValue, const int aSize) { bindNoCopy(aName.c_str(), apValue, aSize); } @@ -389,7 +394,7 @@ public: * * @see clearBindings() to set all bound parameters to NULL. */ - inline void bind(const std::string& aName) // bind NULL value + void bind(const std::string& aName) // bind NULL value { bind(aName.c_str()); } @@ -400,7 +405,7 @@ public: * @brief Execute a step of the prepared query to fetch one row of results. * * While true is returned, a row of results is available, and can be accessed - * thru the getColumn() method + * through the getColumn() method * * @see exec() execute a one-step prepared statement with no expected result * @see tryExecuteStep() try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code. @@ -510,7 +515,7 @@ public: */ Column getColumn(const char* apName); -#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) +#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) // c++14: Visual Studio 2015 /** * @brief Return an instance of T constructed from copies of the first N columns * @@ -622,11 +627,6 @@ public: { return mbHasRow; } - /// @deprecated, use #hasRow() - inline bool isOk() const - { - return hasRow(); - } /// true when the last executeStep() had no more row to fetch inline bool isDone() const { @@ -637,11 +637,11 @@ public: int getBindParameterCount() const noexcept; /// Return the numeric result code for the most recent failed API call (if any). - int getErrorCode() const noexcept; // nothrow + int getErrorCode() const noexcept; /// Return the extended numeric result code for the most recent failed API call (if any). - int getExtendedErrorCode() const noexcept; // nothrow + int getExtendedErrorCode() const noexcept; /// Return UTF-8 encoded English language explanation of the most recent failed API call (if any). - const char* getErrorMsg() const noexcept; // nothrow + const char* getErrorMsg() const noexcept; private: /** @@ -651,6 +651,7 @@ private: * * This is a internal class, not part of the API (hence full documentation is in the cpp). */ + // TODO Convert this whole custom pointer to a C++11 std::shared_ptr with a custom deleter class Ptr { public: @@ -659,10 +660,8 @@ private: // Copy constructor increments the ref counter Ptr(const Ptr& aPtr); -#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) // Move constructor Ptr(Ptr&& aPtr); -#endif // Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0 ~Ptr(); @@ -692,11 +691,6 @@ private: }; private: - /// @{ Statement must be non-copyable - Statement(const Statement&); - Statement& operator=(const Statement&); - /// @} - /** * @brief Check if a return code equals SQLITE_OK, else throw a SQLite::Exception with the SQLite error message * diff --git a/include/SQLiteCpp/Transaction.h b/include/SQLiteCpp/Transaction.h index 38e4fd0..b4392e5 100644 --- a/include/SQLiteCpp/Transaction.h +++ b/include/SQLiteCpp/Transaction.h @@ -52,6 +52,10 @@ public: */ explicit Transaction(Database& aDatabase); + // Transaction is non-copyable + Transaction(const Transaction&) = delete; + Transaction& operator=(const Transaction&) = delete; + /** * @brief Safely rollback the transaction if it has not been committed. */ @@ -62,12 +66,6 @@ public: */ void commit(); -private: - // Transaction must be non-copyable - Transaction(const Transaction&); - Transaction& operator=(const Transaction&); - /// @} - private: Database& mDatabase; ///< Reference to the SQLite Database Connection bool mbCommited; ///< True when commit has been called diff --git a/include/SQLiteCpp/Utils.h b/include/SQLiteCpp/Utils.h deleted file mode 100644 index 9416658..0000000 --- a/include/SQLiteCpp/Utils.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @file Utils.h - * @ingroup SQLiteCpp - * @brief Shared utility macros and functions. - * - * Copyright (c) 2013-2020 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 - -/** - * @brief A macro to disallow the copy constructor and operator= functions. - * - * This should be used in the private: declarations for a class - * - * @param[in] TypeName Class name to protect - */ -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) - -#ifdef _MSC_VER -#if _MSC_VER < 1600 -/// A macro to enable the use of the nullptr keyword (NULL on older MSVC compilers, as they do not accept "nullptr_t") -#ifndef nullptr -#define nullptr NULL -#endif // nullptr -#endif // _MSC_VER < 1600 -#elif defined(__APPLE__) // AppleClang -#elif defined(__clang__) && __has_feature(cxx_nullptr) // Clang 3.0+ -#else // GCC or older Clang -#if (__cplusplus < 201103L) && !defined(__GXX_EXPERIMENTAL_CXX0X__) // before C++11 on GCC4.7 and Visual Studio 2010 -#ifndef HAVE_NULLPTR -#define HAVE_NULLPTR ///< A macro to avoid double definition of nullptr -/** - * @brief nullptr_t is the type of the null pointer literal, nullptr. -*/ -class nullptr_t { -public: - template - inline operator T* () const { ///< convertible to any type of null non-member pointer... - return 0; - } - - template - inline operator T C::* () const { ///< convertible to any type of null member pointer... - return 0; - } - -private: - void operator&() const; ///< Can't take address of nullptr NOLINT -}; - -/** - * @brief Better way to enable nullptr on older GCC/Clang compilers -*/ -const nullptr_t nullptr = {}; -#endif // HAVE_NULLPTR -#endif // (__cplusplus < 201103L) && !defined(__GXX_EXPERIMENTAL_CXX0X__) -#endif // _MSC_VER - -// A macro for snprintf support in Visual Studio -#if defined(_MSC_VER) && _MSC_VER < 1500 -#define snprintf _snprintf -#endif diff --git a/include/SQLiteCpp/VariadicBind.h b/include/SQLiteCpp/VariadicBind.h index 0fe2515..05662dd 100644 --- a/include/SQLiteCpp/VariadicBind.h +++ b/include/SQLiteCpp/VariadicBind.h @@ -12,8 +12,6 @@ */ #pragma once -#if (__cplusplus >= 201103L) || ( defined(_MSC_VER) && (_MSC_VER >= 1800) ) // c++11: Visual Studio 2013 - #include #if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015 @@ -98,5 +96,3 @@ void bind(SQLite::Statement& query, const std::tuple &tuple, std::inde #endif // c++14 } // namespace SQLite - -#endif // c++11 diff --git a/src/Backup.cpp b/src/Backup.cpp index 4fe2950..17a13e2 100644 --- a/src/Backup.cpp +++ b/src/Backup.cpp @@ -22,57 +22,36 @@ namespace SQLite Backup::Backup(Database& aDestDatabase, const char* apDestDatabaseName, Database& aSrcDatabase, - const char* apSrcDatabaseName) : - mpSQLiteBackup(NULL) + const char* apSrcDatabaseName) { mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), apDestDatabaseName, aSrcDatabase.getHandle(), apSrcDatabaseName); - if (NULL == mpSQLiteBackup) + if (nullptr == mpSQLiteBackup) { // If an error occurs, the error code and message are attached to the destination database connection. throw SQLite::Exception(aDestDatabase.getHandle()); } } -// Initialize resource for SQLite database backup Backup::Backup(Database& aDestDatabase, const std::string& aDestDatabaseName, Database& aSrcDatabase, const std::string& aSrcDatabaseName) : - mpSQLiteBackup(NULL) + Backup(aDestDatabase, aDestDatabaseName.c_str(), aSrcDatabase, aSrcDatabaseName.c_str()) { - mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), - aDestDatabaseName.c_str(), - aSrcDatabase.getHandle(), - aSrcDatabaseName.c_str()); - if (NULL == mpSQLiteBackup) - { - // If an error occurs, the error code and message are attached to the destination database connection. - throw SQLite::Exception(aDestDatabase.getHandle()); - } } -// Initialize resource for SQLite database backup Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) : - mpSQLiteBackup(NULL) + Backup(aDestDatabase, "main", aSrcDatabase, "main") { - mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), - "main", - aSrcDatabase.getHandle(), - "main"); - if (NULL == mpSQLiteBackup) - { - // If an error occurs, the error code and message are attached to the destination database connection. - throw SQLite::Exception(aDestDatabase.getHandle()); - } } // Release resource for SQLite database backup Backup::~Backup() { - if (NULL != mpSQLiteBackup) + if (mpSQLiteBackup) { sqlite3_backup_finish(mpSQLiteBackup); } diff --git a/src/Column.cpp b/src/Column.cpp index 6d45f25..b3960fe 100644 --- a/src/Column.cpp +++ b/src/Column.cpp @@ -26,65 +26,59 @@ const int Null = SQLITE_NULL; // Encapsulation of a Column in a row of the result pointed by the prepared Statement. -Column::Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept : // nothrow +Column::Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept : mStmtPtr(aStmtPtr), mIndex(aIndex) { } -// Finalize and unregister the SQL query from the SQLite Database Connection. -Column::~Column() -{ - // the finalization will be done by the destructor of the last shared pointer -} - // Return the named assigned to this result column (potentially aliased) -const char* Column::getName() const noexcept // nothrow +const char* Column::getName() const noexcept { return sqlite3_column_name(mStmtPtr, mIndex); } #ifdef SQLITE_ENABLE_COLUMN_METADATA // Return the name of the table column that is the origin of this result column -const char* Column::getOriginName() const noexcept // nothrow +const char* Column::getOriginName() const noexcept { return sqlite3_column_origin_name(mStmtPtr, mIndex); } #endif // Return the integer value of the column specified by its index starting at 0 -int Column::getInt() const noexcept // nothrow +int Column::getInt() const noexcept { return sqlite3_column_int(mStmtPtr, mIndex); } // Return the unsigned integer value of the column specified by its index starting at 0 -unsigned Column::getUInt() const noexcept // nothrow +unsigned Column::getUInt() const noexcept { return static_cast(getInt64()); } // Return the 64bits integer value of the column specified by its index starting at 0 -long long Column::getInt64() const noexcept // nothrow +long long Column::getInt64() const noexcept { return sqlite3_column_int64(mStmtPtr, mIndex); } // Return the double value of the column specified by its index starting at 0 -double Column::getDouble() const noexcept // nothrow +double Column::getDouble() const noexcept { return sqlite3_column_double(mStmtPtr, mIndex); } // Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0 -const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept // nothrow +const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept { const char* pText = reinterpret_cast(sqlite3_column_text(mStmtPtr, mIndex)); return (pText?pText:apDefaultValue); } // Return a pointer to the blob value (*not* NULL terminated) of the column specified by its index starting at 0 -const void* Column::getBlob() const noexcept // nothrow +const void* Column::getBlob() const noexcept { return sqlite3_column_blob(mStmtPtr, mIndex); } @@ -102,13 +96,13 @@ std::string Column::getString() const } // Return the type of the value of the column -int Column::getType() const noexcept // nothrow +int Column::getType() const noexcept { return sqlite3_column_type(mStmtPtr, mIndex); } // Return the number of bytes used by the text value of the column -int Column::getBytes() const noexcept // nothrow +int Column::getBytes() const noexcept { return sqlite3_column_bytes(mStmtPtr, mIndex); } diff --git a/src/Database.cpp b/src/Database.cpp index a3e728a..bb27c12 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -37,13 +37,13 @@ const char* 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 // nothrow +const char* getLibVersion() noexcept { return sqlite3_libversion(); } // Return SQLite version number using runtime call to the compiled library -int getLibVersionNumber() noexcept // nothrow +int getLibVersionNumber() noexcept { return sqlite3_libversion_number(); } @@ -70,27 +70,6 @@ Database::Database(const char* apFilename, } } -// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags. -Database::Database(const std::string& aFilename, - const int aFlags /* = SQLite::OPEN_READONLY*/, - const int aBusyTimeoutMs /* = 0 */, - const std::string& aVfs /* = "" */) : - mpSQLite(nullptr), - mFilename(aFilename) -{ - const int ret = sqlite3_open_v2(aFilename.c_str(), &mpSQLite, aFlags, aVfs.empty() ? nullptr : aVfs.c_str()); - if (SQLITE_OK != ret) - { - const SQLite::Exception exception(mpSQLite, ret); // must create before closing - sqlite3_close(mpSQLite); // close is required even in case of error on opening - throw exception; - } - if (aBusyTimeoutMs > 0) - { - setBusyTimeout(aBusyTimeoutMs); - } -} - // Close the SQLite database connection. Database::~Database() { @@ -156,31 +135,31 @@ bool Database::tableExists(const char* apTableName) } // Get the rowid of the most recent successful INSERT into the database from the current connection. -long long Database::getLastInsertRowid() const noexcept // nothrow +long long Database::getLastInsertRowid() const noexcept { return sqlite3_last_insert_rowid(mpSQLite); } // Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection. -int Database::getTotalChanges() const noexcept // nothrow +int Database::getTotalChanges() const noexcept { return sqlite3_total_changes(mpSQLite); } // Return the numeric result code for the most recent failed API call (if any). -int Database::getErrorCode() const noexcept // nothrow +int Database::getErrorCode() const noexcept { return sqlite3_errcode(mpSQLite); } // Return the extended numeric result code for the most recent failed API call (if any). -int Database::getExtendedErrorCode() const noexcept // nothrow +int Database::getExtendedErrorCode() const noexcept { return sqlite3_extended_errcode(mpSQLite); } // Return UTF-8 encoded English language explanation of the most recent failed API call (if any). -const char* Database::getErrorMsg() const noexcept // nothrow +const char* Database::getErrorMsg() const noexcept { return sqlite3_errmsg(mpSQLite); } diff --git a/src/Exception.cpp b/src/Exception.cpp index d00a045..2840787 100644 --- a/src/Exception.cpp +++ b/src/Exception.cpp @@ -16,19 +16,6 @@ namespace SQLite { -Exception::Exception(const char* aErrorMessage) : - std::runtime_error(aErrorMessage), - mErrcode(-1), // 0 would be SQLITE_OK, which doesn't make sense - mExtendedErrcode(-1) -{ -} -Exception::Exception(const std::string& aErrorMessage) : - std::runtime_error(aErrorMessage), - mErrcode(-1), // 0 would be SQLITE_OK, which doesn't make sense - mExtendedErrcode(-1) -{ -} - Exception::Exception(const char* aErrorMessage, int ret) : std::runtime_error(aErrorMessage), mErrcode(ret), @@ -36,13 +23,6 @@ Exception::Exception(const char* aErrorMessage, int ret) : { } -Exception::Exception(const std::string& aErrorMessage, int ret) : - std::runtime_error(aErrorMessage), - mErrcode(ret), - mExtendedErrcode(-1) -{ -} - Exception::Exception(sqlite3* apSQLite) : std::runtime_error(sqlite3_errmsg(apSQLite)), mErrcode(sqlite3_errcode(apSQLite)), @@ -58,7 +38,7 @@ Exception::Exception(sqlite3* apSQLite, int ret) : } // Return a string, solely based on the error code -const char* Exception::getErrorStr() const noexcept // nothrow +const char* Exception::getErrorStr() const noexcept { return sqlite3_errstr(mErrcode); } diff --git a/src/Statement.cpp b/src/Statement.cpp index 8bbd365..e7b379f 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -20,7 +20,6 @@ namespace SQLite { -// Compile and register the SQL query for the provided SQLite Database Connection Statement::Statement(Database &aDatabase, const char* apQuery) : mQuery(apQuery), mStmtPtr(aDatabase.mpSQLite, mQuery), // prepare the SQL query, and ref count (needs Database friendship) @@ -31,18 +30,6 @@ Statement::Statement(Database &aDatabase, const char* apQuery) : mColumnCount = sqlite3_column_count(mStmtPtr); } -// Compile and register the SQL query for the provided SQLite Database Connection -Statement::Statement(Database &aDatabase, const std::string& aQuery) : - mQuery(aQuery), - mStmtPtr(aDatabase.mpSQLite, mQuery), // prepare the SQL query, and ref count (needs Database friendship) - mColumnCount(0), - mbHasRow(false), - mbDone(false) -{ - mColumnCount = sqlite3_column_count(mStmtPtr); -} - -#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) Statement::Statement(Statement&& aStatement) noexcept : mQuery(std::move(aStatement.mQuery)), mStmtPtr(std::move(aStatement.mStmtPtr)), @@ -54,13 +41,6 @@ Statement::Statement(Statement&& aStatement) noexcept : aStatement.mbHasRow = false; aStatement.mbDone = false; } -#endif - -// Finalize and unregister the SQL query from the SQLite Database Connection. -Statement::~Statement() -{ - // the finalization will be done by the destructor of the last shared pointer -} // Reset the statement to make it ready for a new execution (see also #clearBindings() bellow) void Statement::reset() @@ -408,19 +388,19 @@ int Statement::getBindParameterCount() const noexcept } // Return the numeric result code for the most recent failed API call (if any). -int Statement::getErrorCode() const noexcept // nothrow +int Statement::getErrorCode() const noexcept { return sqlite3_errcode(mStmtPtr); } // Return the extended numeric result code for the most recent failed API call (if any). -int Statement::getExtendedErrorCode() const noexcept // nothrow +int Statement::getExtendedErrorCode() const noexcept { return sqlite3_extended_errcode(mStmtPtr); } // Return UTF-8 encoded English language explanation of the most recent failed API call (if any). -const char* Statement::getErrorMsg() const noexcept // nothrow +const char* Statement::getErrorMsg() const noexcept { return sqlite3_errmsg(mStmtPtr); } @@ -477,7 +457,6 @@ Statement::Ptr::Ptr(const Statement::Ptr& aPtr) : ++(*mpRefCount); } -#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) Statement::Ptr::Ptr(Ptr&& aPtr) : mpSQLite(aPtr.mpSQLite), mpStmt(aPtr.mpStmt), @@ -487,7 +466,6 @@ Statement::Ptr::Ptr(Ptr&& aPtr) : aPtr.mpStmt = NULL; aPtr.mpRefCount = NULL; } -#endif /** * @brief Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0 diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 388cabb..6f7d5b0 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -3,7 +3,7 @@ * @ingroup SQLiteCpp * @brief A Transaction is way to group multiple SQL statements into an atomic secured operation. * - * Copyright (c) 2012-2013 Sebastien Rombauts (sebastien.rombauts@gmail.com) + * Copyright (c) 2012-2019 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)