├── example ├── bin │ └── data │ │ ├── .gitkeep │ │ └── example.sqlite ├── addons.make └── src │ ├── main.cpp │ ├── ofApp.h │ └── ofApp.cpp ├── example-blobs ├── bin │ └── data │ │ ├── .gitkeep │ │ └── blank-1-3.mbtiles ├── addons.make └── src │ ├── main.cpp │ ├── ofApp.h │ └── ofApp.cpp ├── example-insert ├── bin │ └── data │ │ ├── .gitkeep │ │ └── example.sqlite ├── addons.make └── src │ ├── ofApp.h │ ├── main.cpp │ └── ofApp.cpp ├── example-object ├── bin │ └── data │ │ ├── .gitkeep │ │ ├── logo.png │ │ └── example.sqlite ├── addons.make └── src │ ├── main.cpp │ ├── ofApp.h │ ├── ofApp.cpp │ └── MyObject.h ├── example-raii ├── bin │ └── data │ │ └── .gitkeep ├── addons.make └── src │ ├── main.cpp │ ├── ofApp.h │ └── ofApp.cpp ├── addon_config.mk ├── src ├── SQLiteConnectionPool.cpp ├── ofxSQLiteCpp.h ├── SQLiteUtils.cpp ├── SQLiteUtils.h ├── SQLiteJSON.h ├── SQLiteConnection.cpp ├── SQLiteJSON.cpp ├── SQLiteConnectionPool.h └── SQLiteConnection.h ├── libs └── SQLiteCpp │ ├── sqlite3 │ ├── README.md │ └── CMakeLists.txt │ ├── LICENSE.txt │ ├── src │ ├── Transaction.cpp │ ├── Exception.cpp │ ├── Backup.cpp │ ├── Column.cpp │ ├── Database.cpp │ └── Statement.cpp │ ├── include │ └── SQLiteCpp │ │ ├── Assertion.h │ │ ├── SQLiteCpp.h │ │ ├── Utils.h │ │ ├── Transaction.h │ │ ├── ExecuteMany.h │ │ ├── VariadicBind.h │ │ ├── Exception.h │ │ ├── Backup.h │ │ ├── Column.h │ │ ├── Database.h │ │ └── Statement.h │ └── README.md ├── .travis.yml ├── .appveyor.yml ├── LICENSE.md ├── scripts └── ci │ ├── install.sh │ └── common │ └── install_required_addons.py ├── README.md └── .gitignore /example/bin/data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example-blobs/bin/data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example-insert/bin/data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example-object/bin/data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example-raii/bin/data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/addons.make: -------------------------------------------------------------------------------- 1 | ofxIO 2 | ofxPoco 3 | ofxSQLiteCpp 4 | -------------------------------------------------------------------------------- /example-raii/addons.make: -------------------------------------------------------------------------------- 1 | ofxIO 2 | ofxPoco 3 | ofxSQLiteCpp 4 | -------------------------------------------------------------------------------- /example-blobs/addons.make: -------------------------------------------------------------------------------- 1 | ofxIO 2 | ofxPoco 3 | ofxSQLiteCpp 4 | -------------------------------------------------------------------------------- /example-insert/addons.make: -------------------------------------------------------------------------------- 1 | ofxIO 2 | ofxPoco 3 | ofxSQLiteCpp 4 | -------------------------------------------------------------------------------- /example-object/addons.make: -------------------------------------------------------------------------------- 1 | ofxIO 2 | ofxPoco 3 | ofxSQLiteCpp 4 | -------------------------------------------------------------------------------- /example/bin/data/example.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakercp/ofxSQLiteCpp/HEAD/example/bin/data/example.sqlite -------------------------------------------------------------------------------- /example-object/bin/data/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakercp/ofxSQLiteCpp/HEAD/example-object/bin/data/logo.png -------------------------------------------------------------------------------- /example-insert/bin/data/example.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakercp/ofxSQLiteCpp/HEAD/example-insert/bin/data/example.sqlite -------------------------------------------------------------------------------- /example-object/bin/data/example.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakercp/ofxSQLiteCpp/HEAD/example-object/bin/data/example.sqlite -------------------------------------------------------------------------------- /example-blobs/bin/data/blank-1-3.mbtiles: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bakercp/ofxSQLiteCpp/HEAD/example-blobs/bin/data/blank-1-3.mbtiles -------------------------------------------------------------------------------- /addon_config.mk: -------------------------------------------------------------------------------- 1 | meta: 2 | ADDON_NAME = ofxSQLiteCpp 3 | ADDON_DESCRIPTION = A thin wrapper for the SQLiteCpp library. 4 | ADDON_AUTHOR = bakercp 5 | ADDON_TAGS = "sqlite" 6 | ADDON_URL = http://github.com/bakercp/ofxSQLiteCpp 7 | common: 8 | ADDON_DEPENDENCIES = ofxPoco ofxIO 9 | -------------------------------------------------------------------------------- /src/SQLiteConnectionPool.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "SQLiteConnectionPool.h" 9 | 10 | 11 | namespace SQLite { 12 | 13 | 14 | } // nampace SQLite 15 | -------------------------------------------------------------------------------- /example-raii/src/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "ofApp.h" 9 | 10 | 11 | int main() 12 | { 13 | ofSetupOpenGL(250, 50, OF_WINDOW); 14 | return ofRunApp(std::make_shared()); 15 | } 16 | -------------------------------------------------------------------------------- /example/src/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | 9 | #include "ofApp.h" 10 | 11 | 12 | int main() 13 | { 14 | ofSetupOpenGL(250, 50, OF_WINDOW); 15 | return ofRunApp(std::make_shared()); 16 | } 17 | -------------------------------------------------------------------------------- /example-blobs/src/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "ofApp.h" 9 | 10 | 11 | int main() 12 | { 13 | ofSetupOpenGL(256, 256, OF_WINDOW); 14 | return ofRunApp(std::make_shared()); 15 | } 16 | -------------------------------------------------------------------------------- /example-object/src/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "ofApp.h" 9 | 10 | 11 | int main() 12 | { 13 | ofSetupOpenGL(250, 50, OF_WINDOW); 14 | return ofRunApp(std::make_shared()); 15 | } 16 | -------------------------------------------------------------------------------- /src/ofxSQLiteCpp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #pragma once 9 | 10 | 11 | #include "SQLiteUtils.h" 12 | #include "SQLiteConnection.h" 13 | #include "SQLiteConnectionPool.h" 14 | #include "SQLiteCpp/SQLiteCpp.h" 15 | -------------------------------------------------------------------------------- /example/src/ofApp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #pragma once 9 | 10 | 11 | #include "ofMain.h" 12 | #include "SQLiteCpp.h" 13 | 14 | 15 | class ofApp: public ofBaseApp 16 | { 17 | public: 18 | void setup() override; 19 | void draw() override; 20 | 21 | }; 22 | -------------------------------------------------------------------------------- /example-insert/src/ofApp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #pragma once 9 | 10 | 11 | #include "ofMain.h" 12 | #include "SQLiteCpp.h" 13 | 14 | 15 | class ofApp: public ofBaseApp 16 | { 17 | public: 18 | void setup() override; 19 | void draw() override; 20 | 21 | }; 22 | -------------------------------------------------------------------------------- /example-raii/src/ofApp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #pragma once 9 | 10 | 11 | #include "ofMain.h" 12 | #include "SQLiteCpp.h" 13 | 14 | 15 | class ofApp: public ofBaseApp 16 | { 17 | public: 18 | void setup() override; 19 | void draw() override; 20 | 21 | }; 22 | -------------------------------------------------------------------------------- /example-insert/src/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "ofApp.h" 9 | #include "ofAppNoWindow.h" 10 | 11 | 12 | int main() 13 | { 14 | ofAppNoWindow window; 15 | ofSetupOpenGL(&window, 0, 0, OF_WINDOW); 16 | return ofRunApp(std::make_shared()); 17 | } 18 | -------------------------------------------------------------------------------- /src/SQLiteUtils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "SQLiteUtils.h" 9 | #include "SQLiteJSON.h" 10 | 11 | 12 | namespace SQLite { 13 | 14 | 15 | ofJson SQLiteUtils::execute(Statement& query) 16 | { 17 | return SQLiteJSON::execute(query); 18 | } 19 | 20 | 21 | } // nampace SQLite 22 | -------------------------------------------------------------------------------- /example-blobs/src/ofApp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #pragma once 9 | 10 | 11 | #include "ofMain.h" 12 | #include "SQLiteCpp.h" 13 | 14 | 15 | class ofApp: public ofBaseApp 16 | { 17 | public: 18 | void setup() override; 19 | void draw() override; 20 | 21 | ofImage img; 22 | 23 | }; 24 | -------------------------------------------------------------------------------- /example-object/src/ofApp.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #pragma once 9 | 10 | 11 | #include "ofMain.h" 12 | #include "SQLiteCpp.h" 13 | #include "MyObject.h" 14 | 15 | 16 | class ofApp: public ofBaseApp 17 | { 18 | public: 19 | void setup() override; 20 | void draw() override; 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /src/SQLiteUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #pragma once 9 | 10 | 11 | #include "ofConstants.h" 12 | #include "SQLiteCpp/Statement.h" 13 | #include "ofJson.h" 14 | 15 | 16 | namespace SQLite { 17 | 18 | 19 | class SQLiteUtils 20 | { 21 | public: 22 | OF_DEPRECATED_MSG("Use SQLiteJSON::execute instead.", static ofJson execute(Statement& query)); 23 | 24 | }; 25 | 26 | 27 | } // nampace SQLite 28 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/sqlite3/README.md: -------------------------------------------------------------------------------- 1 | sqlite3 2 | ------- 3 | 4 | "sqlite3.c" and "sqlite3.h" files from sqlite-amalgamation-3120200.zip (SQLite 3.12.2 2016-04-18) 5 | 6 | Those files are provided for easy setup and compatibility under Windows/Linux/MacOS. 7 | They are used by default by the CMake build. 8 | 9 | Use -DSQLITECPP_INTERNAL_SQLITE=OFF to link against the Linux "libsqlite3-dev" package instead. 10 | 11 | ### License: 12 | 13 | All of the code and documentation in SQLite has been dedicated to the public domain by the authors. 14 | 15 | -------------------------------------------------------------------------------- /src/SQLiteJSON.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #pragma once 9 | 10 | 11 | #include "SQLiteCpp/Statement.h" 12 | #include "ofJson.h" 13 | 14 | 15 | namespace SQLite { 16 | 17 | 18 | class SQLiteJSON 19 | { 20 | public: 21 | static ofJson execute(Database& aDatabase, const std::string& aQuery); 22 | 23 | /// \brief Export SQLite results as JSON. 24 | /// 25 | /// Encodes BLOBs using BASE64. 26 | /// 27 | /// \throws Various exceptions. 28 | static ofJson execute(Statement& query); 29 | 30 | 31 | }; 32 | 33 | 34 | } // nampace SQLite 35 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/sqlite3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake file for compiling the sqlite3 static library under Windows (for ease of use) 2 | # 3 | # Copyright (c) 2012-2016 Sebastien Rombauts (sebastien.rombauts@gmail.com) 4 | # 5 | # Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 6 | # or copy at http://opensource.org/licenses/MIT) 7 | 8 | # add sources of the "sqlite3" static library 9 | add_library(sqlite3 10 | sqlite3.c 11 | sqlite3.h 12 | ) 13 | 14 | if (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")) 15 | set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-fPIC") 16 | endif (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")) 17 | 18 | if (UNIX AND CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0) 19 | target_compile_options(sqlite3 PRIVATE "-Wimplicit-fallthrough=0") 20 | endif() 21 | -------------------------------------------------------------------------------- /example-object/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "ofApp.h" 9 | 10 | 11 | void ofApp::setup() 12 | { 13 | ofSetFrameRate(30); 14 | ofEnableAlphaBlending(); 15 | 16 | // Example database. 17 | std::string exampleDB = ofToDataPath("example.sqlite", true); 18 | 19 | try 20 | { 21 | // Open the database and compile the query. 22 | MyObject example(exampleDB); 23 | 24 | // Demonstrate the way to use the same query with different parameter values. 25 | example.listGreaterThan(8); 26 | example.listGreaterThan(6); 27 | example.listGreaterThan(2); 28 | } 29 | catch (const std::exception& e) 30 | { 31 | ofLogError("ofApp::setup()") << "SQLite exception: " << e.what(); 32 | } 33 | 34 | } 35 | 36 | 37 | void ofApp::draw() 38 | { 39 | ofBackgroundGradient(ofColor::white, ofColor::black); 40 | ofDrawBitmapStringHighlight("See console for output.", ofPoint(30, 30)); 41 | } 42 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c++ 2 | compiler: gcc 3 | sudo: true 4 | matrix: 5 | include: 6 | # fully specify builds, include can't dynamically expand matrix entries 7 | # relative order of sudo and env is important so that addons: is recognized 8 | 9 | # Linux 64bit, OF master 10 | - os: linux 11 | dist: trusty 12 | sudo: required 13 | env: TARGET="linux64" OF_BRANCH="master" 14 | addons: 15 | apt: 16 | sources: 17 | - ubuntu-toolchain-r-test 18 | packages: 19 | - gcc-4.9 20 | - g++-4.9 21 | - gdb 22 | 23 | # OSX, OF master 24 | - os: osx 25 | osx_image: xcode8 26 | compiler: clang 27 | env: TARGET="osx" OF_BRANCH="master" 28 | 29 | # Exclude the default build that would otherwise be generated 30 | # see https://github.com/travis-ci/travis-ci/issues/1228 31 | exclude: 32 | - compiler: gcc 33 | before_install: 34 | - curl -SLsO https://raw.githubusercontent.com/bakercp/ofxAddonScripts/${OF_BRANCH}/scripts/ci/tools/install.sh 35 | - source install.sh 36 | install: 37 | - do_install 38 | script: 39 | - do_script 40 | 41 | git: 42 | depth: 10 43 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | os: Visual Studio 2015 RC 3 | 4 | environment: 5 | global: 6 | APPVEYOR_OS_NAME: windows 7 | matrix: 8 | #MSYS2 Building 9 | - platform: x86 10 | BUILDER: MSYS2 11 | 12 | #VisualStudio Building 13 | - platform: x86 14 | BUILDER : VS 15 | BITS: 32 16 | - platform: x64 17 | BUILDER : VS 18 | BITS: 64 19 | 20 | configuration: Debug 21 | shallow_clone: true 22 | clone_depth: 10 23 | init: 24 | - set MAKEFLAGS=-s 25 | - set MSYS2_PATH=c:\msys64 26 | - set CHERE_INVOKING=1 27 | - if "%BUILDER%_%PLATFORM%"=="MSYS2_x86" set MSYSTEM=MINGW32 28 | - if "%BUILDER%_%PLATFORM%"=="MSYS2_x64" set MSYSTEM=MINGW64 29 | - if "%BUILDER%"=="VS" set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH% 30 | - cd %APPVEYOR_BUILD_FOLDER%\..\ 31 | - set OF_ROOT=%CD%\openFrameworks 32 | - set OF_ADDON_NAME=%APPVEYOR_PROJECT_NAME% 33 | install: 34 | - git clone --depth=1 --branch=CI-TESTS https://github.com/bakercp/openFrameworks %OF_ROOT% 35 | - cd %OF_ROOT% 36 | - call scripts\ci\addons\install.cmd 37 | build_script: 38 | - cd %OF_ROOT% 39 | - call scripts\ci\addons\build.cmd 40 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is furnished 10 | to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 20 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Christopher Baker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | --- 24 | 25 | # Included libraries 26 | - `SQLiteCpp` [MIT](https://opensource.org/licenses/LGPL-3.0) 27 | -------------------------------------------------------------------------------- /scripts/ci/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | OF_ROOT=$( cd "$(dirname "$0")/../../../.." ; pwd -P ) 5 | 6 | # Default addon github info. 7 | GH_USERNAME='bakercp' 8 | GH_BRANCH='master' 9 | GH_DEPTH=1 10 | 11 | # An array of required addons that will be gathered below. 12 | REQUIRED_ADDONS=() 13 | 14 | # Extract ADDON_DEPENDENCIES from addon_config.mk file. 15 | if [ -f ${OF_ROOT}/addons/${OF_ADDON_NAME}/addon_config.mk ]; then 16 | while read line; do 17 | if [[ $line == ADDON_DEPENDENCIES* ]] ; 18 | then 19 | line=${line#*=} 20 | IFS=' ' read -ra ADDR <<< "$line" 21 | for i in "${ADDR[@]}"; do 22 | REQUIRED_ADDONS+=($i) 23 | done 24 | fi 25 | done < ${OF_ROOT}/addons/${OF_ADDON_NAME}/addon_config.mk 26 | fi 27 | 28 | # Gather addons from all examples. 29 | for addons_make in ${OF_ROOT}/addons/${OF_ADDON_NAME}/example*/addons.make; do 30 | while read addon; do 31 | if [ ${addon} != ${OF_ADDON_NAME} ] ; 32 | then 33 | REQUIRED_ADDONS+=($addon) 34 | fi 35 | done < $addons_make 36 | done 37 | 38 | # We aren't de-duplicating array to keep it pure bash. 39 | for addon in "${REQUIRED_ADDONS[@]}" 40 | do 41 | if [ ! -d ${OF_ROOT}/addons/${addon} ]; then 42 | git clone --depth=$GH_DEPTH https://github.com/$GH_USERNAME/$addon.git ${OF_ROOT}/addons/${addon} 43 | fi 44 | done 45 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/src/Transaction.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Transaction.cpp 3 | * @ingroup SQLiteCpp 4 | * @brief A Transaction is way to group multiple SQL statements into an atomic secured operation. 5 | * 6 | * Copyright (c) 2012-2013 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | 17 | namespace SQLite 18 | { 19 | 20 | 21 | // Begins the SQLite transaction 22 | Transaction::Transaction(Database& aDatabase) : 23 | mDatabase(aDatabase), 24 | mbCommited(false) 25 | { 26 | mDatabase.exec("BEGIN"); 27 | } 28 | 29 | // Safely rollback the transaction if it has not been committed. 30 | Transaction::~Transaction() 31 | { 32 | if (false == mbCommited) 33 | { 34 | try 35 | { 36 | mDatabase.exec("ROLLBACK"); 37 | } 38 | catch (SQLite::Exception&) 39 | { 40 | // Never throw an exception in a destructor: error if already rollbacked, but no harm is caused by this. 41 | } 42 | } 43 | } 44 | 45 | // Commit the transaction. 46 | void Transaction::commit() 47 | { 48 | if (false == mbCommited) 49 | { 50 | mDatabase.exec("COMMIT"); 51 | mbCommited = true; 52 | } 53 | else 54 | { 55 | throw SQLite::Exception("Transaction already commited."); 56 | } 57 | } 58 | 59 | 60 | } // namespace SQLite 61 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/Assertion.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Assertion.h 3 | * @ingroup SQLiteCpp 4 | * @brief Definition of the SQLITECPP_ASSERT() macro. 5 | * 6 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | 16 | /** 17 | * SQLITECPP_ASSERT SQLITECPP_ASSERT() is used in destructors, where exceptions shall not be thrown 18 | * 19 | * Define SQLITECPP_ENABLE_ASSERT_HANDLER at the project level 20 | * and define a SQLite::assertion_failed() assertion handler 21 | * to tell SQLiteC++ to use it instead of assert() when an assertion fail. 22 | */ 23 | #ifdef SQLITECPP_ENABLE_ASSERT_HANDLER 24 | 25 | // if an assert handler is provided by user code, use it instead of assert() 26 | namespace SQLite 27 | { 28 | // declaration of the assert handler to define in user code 29 | void assertion_failed(const char* apFile, const long apLine, const char* apFunc, 30 | const char* apExpr, const char* apMsg); 31 | 32 | #ifdef _MSC_VER 33 | #define __func__ __FUNCTION__ 34 | #endif 35 | // call the assert handler provided by user code 36 | #define SQLITECPP_ASSERT(expression, message) \ 37 | if (!(expression)) SQLite::assertion_failed(__FILE__, __LINE__, __func__, #expression, message) 38 | } // namespace SQLite 39 | 40 | #else 41 | 42 | // if no assert handler provided by user code, use standard assert() 43 | // (note: in release mode assert() does nothing) 44 | #define SQLITECPP_ASSERT(expression, message) assert(expression && message) 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /example-object/src/MyObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include 9 | #include "SQLiteCpp.h" 10 | #include "ofLog.h" 11 | 12 | 13 | class MyObject 14 | { 15 | public: 16 | // Constructor 17 | MyObject(const std::string& dbFile): 18 | // Open a database file in readonly mode 19 | _db(dbFile), 20 | // Compile a SQL query, containing one parameter (index 1) 21 | _query(_db, "SELECT * FROM test WHERE weight > :min_weight") 22 | { 23 | } 24 | 25 | virtual ~MyObject() 26 | { 27 | } 28 | 29 | /// \brief List the rows where the "weight" column is greater than the provided \p aParamValue. 30 | /// \param aParamValue The value 31 | void listGreaterThan(int aParamValue) 32 | { 33 | ofLogNotice("MyObject::listGreaterThan") << "ListGreaterThan (" << aParamValue << ")"; 34 | 35 | // Bind the integer value provided to the first parameter of the SQL query 36 | _query.bind(":min_weight", aParamValue); // same as mQuery.bind(1, aParamValue); 37 | 38 | // Loop to execute the query step by step, to get one a row of results at a time 39 | while (_query.executeStep()) 40 | { 41 | ofLogNotice("MyObject::listGreaterThan") << "row (" << _query.getColumn(0) << ", \"" << _query.getColumn(1) << "\", " << _query.getColumn(2) << ")"; 42 | } 43 | 44 | // Reset the query to be able to use it again later 45 | _query.reset(); 46 | } 47 | 48 | private: 49 | /// \brief Database connection. 50 | SQLite::Database _db; 51 | 52 | /// \brief Database prepared SQL query. 53 | SQLite::Statement _query; 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/SQLiteCpp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SQLiteCpp.h 3 | * @ingroup SQLiteCpp 4 | * @brief SQLiteC++ is a smart and simple C++ SQLite3 wrapper. This file is only "easy include" for other files. 5 | * 6 | * Include this main header file in your project to gain access to all functionality provided by the wrapper. 7 | * 8 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 9 | * 10 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 11 | * or copy at http://opensource.org/licenses/MIT) 12 | */ 13 | /** 14 | * @defgroup SQLiteCpp SQLiteC++ 15 | * @brief SQLiteC++ is a smart and simple C++ SQLite3 wrapper. This file is only "easy include" for other files. 16 | */ 17 | #pragma once 18 | 19 | 20 | // Include useful headers of SQLiteC++ 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | /** 30 | * @brief Version numbers for SQLiteC++ are provided in the same way as sqlite3.h 31 | * 32 | * The [SQLITECPP_VERSION] C preprocessor macro in the SQLiteC++.h header 33 | * evaluates to a string literal that is the SQLite version in the 34 | * format "X.Y.Z" where X is the major version number 35 | * and Y is the minor version number and Z is the release number. 36 | * 37 | * The [SQLITECPP_VERSION_NUMBER] C preprocessor macro resolves to an integer 38 | * with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same 39 | * numbers used in [SQLITECPP_VERSION]. 40 | * 41 | * WARNING: shall always be updated in sync with PROJECT_VERSION in CMakeLists.txt 42 | */ 43 | #define SQLITECPP_VERSION "2.04.00" // 2.4.0 44 | #define SQLITECPP_VERSION_NUMBER 2004000 // 2.4.0 45 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/src/Exception.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Exception.cpp 3 | * @ingroup SQLiteCpp 4 | * @brief Encapsulation of the error message from SQLite3 on a std::runtime_error. 5 | * 6 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #include 12 | 13 | #include 14 | 15 | 16 | namespace SQLite 17 | { 18 | 19 | Exception::Exception(const char* aErrorMessage) : 20 | std::runtime_error(aErrorMessage), 21 | mErrcode(-1), // 0 would be SQLITE_OK, which doesn't make sense 22 | mExtendedErrcode(-1) 23 | { 24 | } 25 | Exception::Exception(const std::string& aErrorMessage) : 26 | std::runtime_error(aErrorMessage), 27 | mErrcode(-1), // 0 would be SQLITE_OK, which doesn't make sense 28 | mExtendedErrcode(-1) 29 | { 30 | } 31 | 32 | Exception::Exception(const char* aErrorMessage, int ret) : 33 | std::runtime_error(aErrorMessage), 34 | mErrcode(ret), 35 | mExtendedErrcode(-1) 36 | { 37 | } 38 | 39 | Exception::Exception(const std::string& aErrorMessage, int ret) : 40 | std::runtime_error(aErrorMessage), 41 | mErrcode(ret), 42 | mExtendedErrcode(-1) 43 | { 44 | } 45 | 46 | Exception::Exception(sqlite3* apSQLite) : 47 | std::runtime_error(sqlite3_errmsg(apSQLite)), 48 | mErrcode(sqlite3_errcode(apSQLite)), 49 | mExtendedErrcode(sqlite3_extended_errcode(apSQLite)) 50 | { 51 | } 52 | 53 | Exception::Exception(sqlite3* apSQLite, int ret) : 54 | std::runtime_error(sqlite3_errmsg(apSQLite)), 55 | mErrcode(ret), 56 | mExtendedErrcode(sqlite3_extended_errcode(apSQLite)) 57 | { 58 | } 59 | 60 | // Return a string, solely based on the error code 61 | const char* Exception::getErrorStr() const noexcept // nothrow 62 | { 63 | return sqlite3_errstr(mErrcode); 64 | } 65 | 66 | 67 | } // namespace SQLite 68 | -------------------------------------------------------------------------------- /src/SQLiteConnection.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "SQLiteConnection.h" 9 | #include "ofUtils.h" 10 | #include "ofFileUtils.h" 11 | 12 | 13 | namespace SQLite { 14 | 15 | 16 | SQLiteConnection::SQLiteConnection(const std::string& filename, 17 | Mode mode, 18 | uint64_t databaseTimeoutMilliseconds, 19 | std::size_t index): 20 | _mode(mode), 21 | _database(ofToDataPath(filename, true), 22 | _toAccessFlag(_mode), 23 | databaseTimeoutMilliseconds), 24 | _index(index) 25 | { 26 | } 27 | 28 | 29 | SQLiteConnection::~SQLiteConnection() 30 | { 31 | } 32 | 33 | 34 | Database& SQLiteConnection::database() 35 | { 36 | return _database; 37 | } 38 | 39 | 40 | const Database& SQLiteConnection::database() const 41 | { 42 | return _database; 43 | } 44 | 45 | 46 | bool SQLiteConnection::hasStatement(const std::string& query) const 47 | { 48 | return _statements.find(query) != _statements.end(); 49 | } 50 | 51 | 52 | Statement& SQLiteConnection::getStatement(const std::string& query) const 53 | { 54 | auto iter = _statements.find(query); 55 | 56 | if (iter != _statements.end()) 57 | { 58 | iter->second->reset(); 59 | iter->second->clearBindings(); 60 | return *iter->second.get(); 61 | } 62 | 63 | // Insert and retern a reference. 64 | return *_statements.insert(std::make_pair(query, std::make_unique(_database, query))).first->second.get(); 65 | } 66 | 67 | 68 | int SQLiteConnection::_toAccessFlag(Mode mode) 69 | { 70 | switch (mode) 71 | { 72 | case Mode::READ_ONLY: 73 | return OPEN_READONLY; 74 | case Mode::READ_WRITE: 75 | return OPEN_READWRITE; 76 | case Mode::READ_WRITE_CREATE: 77 | return OPEN_READWRITE | OPEN_CREATE; 78 | } 79 | 80 | return OPEN_READONLY; 81 | } 82 | 83 | 84 | } // nampace SQLite 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ofxSQLiteCpp 2 | ============ 3 | 4 | ## Description 5 | 6 | A very thin wrapper (hardly even a wrapper) around the amazing [SQLiteCpp](https://github.com/SRombauts/SQLiteCpp) project. 7 | 8 | ## Features 9 | 10 | See the examples. 11 | 12 | ## Getting Started 13 | 14 | To get started, generate the example project files using the openFrameworks [Project Generator](http://openframeworks.cc/learning/01_basics/how_to_add_addon_to_project/). 15 | 16 | ## Documentation 17 | 18 | API documentation can be found here. 19 | 20 | ## Build Status 21 | 22 | Linux, macOS [![Build Status](https://travis-ci.org/bakercp/ofxSQLiteCpp.svg?branch=master)](https://travis-ci.org/bakercp/ofxSQLiteCpp) 23 | 24 | Visual Studio, MSYS [![Build status](https://ci.appveyor.com/api/projects/status/vojvulwcrhrlbog4/branch/master?svg=true)](https://ci.appveyor.com/project/bakercp/ofxsqlitecpp/branch/master) 25 | 26 | ## Compatibility 27 | 28 | The `stable` branch of this repository is meant to be compatible with the openFrameworks [stable branch](https://github.com/openframeworks/openFrameworks/tree/stable), which corresponds to the latest official openFrameworks release. 29 | 30 | The `master` branch of this repository is meant to be compatible with the openFrameworks [master branch](https://github.com/openframeworks/openFrameworks/tree/master). 31 | 32 | Some past openFrameworks releases are supported via tagged versions, but only `stable` and `master` branches are actively supported. 33 | 34 | ### Requirements 35 | - ofxPoco (included with openFrameworks) 36 | - [ofxIO](https://github.com/bakercp/ofxIO) 37 | 38 | ## Versioning 39 | 40 | This project uses Semantic Versioning, although strict adherence will only come into effect at version 1.0.0. 41 | 42 | ## Licensing 43 | 44 | See `LICENSE.md`. 45 | 46 | ## Contributing 47 | 48 | Pull Requests are always welcome, so if you make any improvements please feel free to float them back upstream :) 49 | 50 | 1. Fork this repository. 51 | 2. Create your feature branch (`git checkout -b my-new-feature`). 52 | 3. Commit your changes (`git commit -am 'Add some feature'`). 53 | 4. Push to the branch (`git push origin my-new-feature`). 54 | 5. Create new Pull Request. 55 | -------------------------------------------------------------------------------- /example-insert/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "ofApp.h" 9 | 10 | 11 | void ofApp::setup() 12 | { 13 | ofSetFrameRate(30); 14 | ofEnableAlphaBlending(); 15 | 16 | // Example database. 17 | std::string exampleDB = ofToDataPath("example.sqlite", true); 18 | 19 | try 20 | { 21 | // Open a database file in create/write mode. 22 | SQLite::Database db(exampleDB, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); 23 | 24 | ofLogNotice("ofApp::setup()") << "SQLite database file '" << db.getFilename() << "' opened successfully"; 25 | 26 | if (db.tableExists("test")) 27 | { 28 | db.exec("DROP TABLE test"); 29 | } 30 | 31 | db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"); 32 | 33 | // first row 34 | int nb = db.exec("INSERT INTO test VALUES (NULL, \"test\")"); 35 | 36 | ofLogNotice("ofApp::setup()") << "INSERT INTO test VALUES (NULL, \"test\")\", returned " << nb; 37 | 38 | // second row 39 | nb = db.exec("INSERT INTO test VALUES (NULL, \"second\")"); 40 | 41 | ofLogNotice("ofApp::setup()") << "INSERT INTO test VALUES (NULL, \"second\")\", returned " << nb; 42 | 43 | // update the second row 44 | nb = db.exec("UPDATE test SET value=\"second-updated\" WHERE id='2'"); 45 | 46 | ofLogNotice("ofApp::setup()") << "UPDATE test SET value=\"second-updated\" WHERE id='2', returned " << nb; 47 | 48 | // Check the results : expect two row of result 49 | SQLite::Statement query(db, "SELECT * FROM test"); 50 | 51 | ofLogNotice("ofApp::setup()") << "SELECT * FROM test :"; 52 | 53 | while (query.executeStep()) 54 | { 55 | ofLogNotice("ofApp::setup()") << "row (" << query.getColumn(0) << ", \"" << query.getColumn(1) << "\")"; 56 | } 57 | 58 | db.exec("DROP TABLE test"); 59 | } 60 | catch (const std::exception& e) 61 | { 62 | ofLogError() << "SQLite exception: " << e.what(); 63 | } 64 | } 65 | 66 | 67 | void ofApp::draw() 68 | { 69 | ofBackgroundGradient(ofColor::white, ofColor::black); 70 | ofDrawBitmapStringHighlight("See console for output.", ofPoint(30, 30)); 71 | } 72 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/Utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Utils.h 3 | * @ingroup SQLiteCpp 4 | * @brief Shared utility macros and functions. 5 | * 6 | * Copyright (c) 2013-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | /** 16 | * @brief A macro to disallow the copy constructor and operator= functions. 17 | * 18 | * This should be used in the private: declarations for a class 19 | * 20 | * @param[in] TypeName Class name to protect 21 | */ 22 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 23 | TypeName(const TypeName&); \ 24 | void operator=(const TypeName&) 25 | 26 | #ifdef _MSC_VER 27 | #if _MSC_VER < 1600 28 | /// A macro to enable the use of the nullptr keyword (NULL on older MSVC compilers, as they do not accept "nullptr_t") 29 | #ifndef nullptr 30 | #define nullptr NULL 31 | #endif // nullptr 32 | #endif // _MSC_VER < 1600 33 | #elif defined(__APPLE__) // AppleClang 34 | #elif defined(__clang__) && __has_feature(cxx_nullptr) // Clang 3.0+ 35 | #else // GCC or older Clang 36 | #if (__cplusplus < 201103L) && !defined(__GXX_EXPERIMENTAL_CXX0X__) // before C++11 on GCC4.7 and Visual Studio 2010 37 | #ifndef HAVE_NULLPTR 38 | #define HAVE_NULLPTR ///< A macro to avoid double definition of nullptr 39 | /** 40 | * @brief nullptr_t is the type of the null pointer literal, nullptr. 41 | */ 42 | class nullptr_t { 43 | public: 44 | template 45 | inline operator T* () const { ///< convertible to any type of null non-member pointer... 46 | return 0; 47 | } 48 | 49 | template 50 | inline operator T C::* () const { ///< convertible to any type of null member pointer... 51 | return 0; 52 | } 53 | 54 | private: 55 | void operator&() const; ///< Can't take address of nullptr NOLINT 56 | }; 57 | 58 | /** 59 | * @brief Better way to enable nullptr on older GCC/Clang compilers 60 | */ 61 | const nullptr_t nullptr = {}; 62 | #endif // HAVE_NULLPTR 63 | #endif // (__cplusplus < 201103L) && !defined(__GXX_EXPERIMENTAL_CXX0X__) 64 | #endif // _MSC_VER 65 | 66 | // A macro for snprintf support in Visual Studio 67 | #if defined(_MSC_VER) && _MSC_VER < 1500 68 | #define snprintf _snprintf 69 | #endif 70 | -------------------------------------------------------------------------------- /example-blobs/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "ofApp.h" 9 | 10 | 11 | void ofApp::setup() 12 | { 13 | ofSetFrameRate(30); 14 | ofEnableAlphaBlending(); 15 | 16 | // Example database. 17 | std::string mbTilesFilename = ofToDataPath("blank-1-3.mbtiles", true); 18 | 19 | try 20 | { 21 | // Open a database file in readonly mode 22 | SQLite::Database db(mbTilesFilename); // SQLITE_OPEN_READONLY 23 | 24 | int zoomLevel = 1; 25 | int tileColumn = 0; 26 | int tileRow = 0; 27 | 28 | // We use string stream to create a long query string, but one 29 | // could just as easily use a string with the += operator. It's style. 30 | std::stringstream ss; 31 | 32 | ss << "SELECT zoom_level, tile_column, tile_row, tile_data "; 33 | ss << "FROM tiles "; 34 | ss << "WHERE zoom_level = ? "; 35 | ss << "AND tile_column = ? "; 36 | ss << "AND tile_row = ?"; 37 | 38 | // Create the query with the database. 39 | SQLite::Statement query(db, ss.str()); 40 | 41 | query.bind(1, zoomLevel); // Bind the zoom level to the first ? in the query. 42 | query.bind(2, tileColumn); // Bind the tile column to the second ? in the query. 43 | query.bind(3, tileRow); // Bind the tile row to the third ? in the query. 44 | 45 | // Loop to execute the query step by step, to get one a row of results at a time 46 | while (query.executeStep()) 47 | { 48 | SQLite::Column colBlob = query.getColumn(3); // We know that column 3 is the image bytes 49 | const void* blob = colBlob.getBlob(); // Get a pointer to the bytes. 50 | std::size_t size = colBlob.getBytes(); // Get the number of bytes. 51 | ofBuffer buffer(static_cast(blob), size); // Create a buffer with those bytes. 52 | 53 | img.load(buffer); // Load the image from the buffer. 54 | } 55 | 56 | } 57 | catch (const std::exception& e) 58 | { 59 | ofLogError("ofApp::setup") << "SQLite exception: " << e.what(); 60 | } 61 | } 62 | 63 | 64 | void ofApp::draw() 65 | { 66 | ofBackgroundGradient(ofColor::white, ofColor::black); 67 | 68 | // Draw the tile image. 69 | img.draw(0, 0); 70 | } 71 | -------------------------------------------------------------------------------- /src/SQLiteJSON.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "SQLiteJSON.h" 9 | #include "SQLiteCpp/Column.h" 10 | #include "Poco/Base64Encoder.h" 11 | #include 12 | #include 13 | 14 | 15 | namespace SQLite { 16 | 17 | 18 | ofJson SQLiteJSON::execute(Database& aDatabase, const std::string& aQuery) 19 | { 20 | Statement statement(aDatabase, aQuery); 21 | return execute(statement); 22 | } 23 | 24 | 25 | ofJson SQLiteJSON::execute(Statement& query) 26 | { 27 | ofJson columns; 28 | 29 | while (query.executeStep()) 30 | { 31 | ofJson row; 32 | 33 | for (auto i = 0; i < query.getColumnCount(); ++i) 34 | { 35 | const Column& column = query.getColumn(i); 36 | 37 | switch (column.getType()) 38 | { 39 | case SQLITE_INTEGER: 40 | { 41 | row[column.getName()] = column.getInt64(); 42 | break; 43 | } 44 | case SQLITE_FLOAT: 45 | { 46 | row[column.getName()] = column.getDouble(); 47 | break; 48 | } 49 | case SQLITE_NULL: 50 | { 51 | row[column.getName()] = nullptr; 52 | break; 53 | } 54 | case SQLITE_TEXT: 55 | { 56 | row[column.getName()] = column.getText(); 57 | break; 58 | } 59 | case SQLITE_BLOB: 60 | { 61 | // Encode blob w/ base64. 62 | const char* pBlob = static_cast(column.getBlob()); 63 | int nBytes = column.getBytes(); 64 | std::ostringstream ss; 65 | Poco::Base64Encoder _encoder(ss); 66 | _encoder.write(pBlob, nBytes); 67 | _encoder.close(); // Flush bytes. 68 | row[column.getName()] = ss.str(); 69 | break; 70 | } 71 | default: 72 | { 73 | ofLogWarning("SQLiteUtils::execute") << "Unknonwn SQLITE type: " << column.getType() << ", using SQLITE_TEXT"; 74 | row[column.getName()] = column.getText(); 75 | } 76 | } 77 | } 78 | 79 | columns.push_back(row); 80 | } 81 | 82 | // Reset the query to use it again. 83 | query.reset(); 84 | 85 | return columns; 86 | } 87 | 88 | 89 | 90 | } // nampace SQLite 91 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/Transaction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Transaction.h 3 | * @ingroup SQLiteCpp 4 | * @brief A Transaction is way to group multiple SQL statements into an atomic secured operation. 5 | * 6 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | 16 | namespace SQLite 17 | { 18 | 19 | 20 | // Forward declaration 21 | class Database; 22 | 23 | /** 24 | * @brief RAII encapsulation of a SQLite Transaction. 25 | * 26 | * A Transaction is a way to group multiple SQL statements into an atomic secured operation; 27 | * either it succeeds, with all the changes committed to the database file, 28 | * or if it fails, all the changes are rolled back to the initial state. 29 | * 30 | * Resource Acquisition Is Initialization (RAII) means that the Transaction 31 | * begins in the constructor and is rollbacked in the destructor, so that there is 32 | * no need to worry about memory management or the validity of the underlying SQLite Connection. 33 | * 34 | * This method also offers big performances improvements compared to individually executed statements. 35 | * 36 | * Thread-safety: a Transaction object shall not be shared by multiple threads, because : 37 | * 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads 38 | * provided that no single database connection is used simultaneously in two or more threads." 39 | * 2) the SQLite "Serialized" mode is not supported by SQLiteC++, 40 | * because of the way it shares the underling SQLite precompiled statement 41 | * in a custom shared pointer (See the inner class "Statement::Ptr"). 42 | */ 43 | class Transaction 44 | { 45 | public: 46 | /** 47 | * @brief Begins the SQLite transaction 48 | * 49 | * @param[in] aDatabase the SQLite Database Connection 50 | * 51 | * Exception is thrown in case of error, then the Transaction is NOT initiated. 52 | */ 53 | explicit Transaction(Database& aDatabase); 54 | 55 | /** 56 | * @brief Safely rollback the transaction if it has not been committed. 57 | */ 58 | ~Transaction(); 59 | 60 | /** 61 | * @brief Commit the transaction. 62 | */ 63 | void commit(); 64 | 65 | private: 66 | // Transaction must be non-copyable 67 | Transaction(const Transaction&); 68 | Transaction& operator=(const Transaction&); 69 | /// @} 70 | 71 | private: 72 | Database& mDatabase; ///< Reference to the SQLite Database Connection 73 | bool mbCommited; ///< True when commit has been called 74 | }; 75 | 76 | 77 | } // namespace SQLite 78 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/ExecuteMany.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ExecuteMany.h 3 | * @ingroup SQLiteCpp 4 | * @brief Convenience function to execute a Statement with multiple Parameter sets 5 | * 6 | * Copyright (c) 2019 Maximilian Bachmann (contact@maxbachmann.de) 7 | * Copyright (c) 2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 8 | * 9 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 10 | * or copy at http://opensource.org/licenses/MIT) 11 | */ 12 | #pragma once 13 | 14 | #if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015 15 | 16 | #include 17 | #include 18 | 19 | /// @cond 20 | #include 21 | #include 22 | #include 23 | 24 | namespace SQLite 25 | { 26 | /// @endcond 27 | 28 | /** 29 | * \brief Convenience function to execute a Statement with multiple Parameter sets once for each parameter set given. 30 | * 31 | * 32 | * This feature requires a c++14 capable compiler. 33 | * 34 | * \code{.cpp} 35 | * execute_many(db, "INSERT INTO test VALUES (?, ?)", 36 | * 1, 37 | * std::make_tuple(2), 38 | * std::make_tuple(3, "three") 39 | * ); 40 | * \endcode 41 | * @param aDatabase Database to use 42 | * @param apQuery Query to use with all parameter sets 43 | * @param aArg first tuple with parameters 44 | * @param aParams the following tuples with parameters 45 | */ 46 | template 47 | void execute_many(Database& aDatabase, const char* apQuery, Arg&& aArg, Types&&... aParams) 48 | { 49 | SQLite::Statement query(aDatabase, apQuery); 50 | bind_exec(query, std::forward(aArg)); 51 | (void)std::initializer_list 52 | { 53 | ((void)reset_bind_exec(query, std::forward(aParams)), 0)... 54 | }; 55 | } 56 | 57 | /** 58 | * \brief Convenience function to reset a statement and call bind_exec to 59 | * bind new values to the statement and execute it 60 | * 61 | * This feature requires a c++14 capable compiler. 62 | * 63 | * @param apQuery Query to use 64 | * @param aTuple Tuple to bind 65 | */ 66 | template 67 | void reset_bind_exec(Statement& apQuery, TupleT&& aTuple) 68 | { 69 | apQuery.reset(); 70 | bind_exec(apQuery, std::forward(aTuple)); 71 | } 72 | 73 | /** 74 | * \brief Convenience function to bind values a the statement and execute it 75 | * 76 | * This feature requires a c++14 capable compiler. 77 | * 78 | * @param apQuery Query to use 79 | * @param aTuple Tuple to bind 80 | */ 81 | template 82 | void bind_exec(Statement& apQuery, TupleT&& aTuple) 83 | { 84 | SQLite::bind(apQuery, std::forward(aTuple)); 85 | while (apQuery.executeStep()) {} 86 | } 87 | 88 | } // namespace SQLite 89 | 90 | #endif // c++14 91 | -------------------------------------------------------------------------------- /scripts/ci/common/install_required_addons.py: -------------------------------------------------------------------------------- 1 | """This thing ... """ 2 | 3 | import argparse 4 | import os 5 | import subprocess 6 | from pathlib import Path 7 | 8 | PARSER = argparse.ArgumentParser() 9 | 10 | # parser.add_argument("--addon_path", help="The path of the addon.") 11 | PARSER.add_argument("--of_root", help="The OF_ROOT directory.") 12 | # parser.add_argument("--of_addons", help="The OF_ADDONS directory.") 13 | PARSER.add_argument("--username", help="The default github username.") 14 | PARSER.add_argument("--branch", help="The default github branch.") 15 | PARSER.add_argument("--depth", help="The default github clone depth.") 16 | 17 | ARGS = PARSER.parse_args() 18 | 19 | 20 | # These paths assume that this file is located in 21 | # OF_ROOT/addons/ADDON_NAME/ci/common/install_dependencies.py 22 | 23 | ADDON_PATH = Path(__file__).parent / '../../..' 24 | ADDON_NAME = ADDON_PATH.resolve().name 25 | 26 | if ARGS.of_root: 27 | OF_ROOT = Path(ARGS.of_root).expanduser() 28 | elif os.getenv('OF_ROOT'): 29 | OF_ROOT = Path(os.getenv('OF_ROOT')).expanduser() 30 | else: 31 | OF_ROOT = Path('../../../../..').resolve() 32 | 33 | OF_ADDONS = OF_ROOT / 'addons' 34 | 35 | GH_USERNAME = ARGS.username if ARGS.username else 'bakercp' 36 | GH_BRANCH = ARGS.branch if ARGS.branch else 'master' 37 | GH_DEPTH = ARGS.depth if ARGS.depth else 1 38 | 39 | print(ADDON_PATH.resolve()) 40 | print(ADDON_NAME) 41 | print(OF_ROOT) 42 | print(OF_ADDONS) 43 | 44 | # print(ADDON_PATH) 45 | # print(ADDON_NAME) 46 | # print(OF_ADDONS) 47 | # print(OF_ROOT) 48 | 49 | REQUIRED_ADDONS = set([]) 50 | 51 | ADDON_CONFIG_MK = Path(ADDON_PATH, 'addon_config.mk') 52 | 53 | # Collect any required dependencies from the ADDON_CONFIG.mk file. 54 | if ADDON_CONFIG_MK.exists(): 55 | for line in ADDON_CONFIG_MK.open().readlines(): 56 | if 'ADDON_DEPENDENCIES' in line: 57 | addons = line[line.index('=') + 1:].strip().split() 58 | for addon in addons: 59 | REQUIRED_ADDONS.add(addon) 60 | else: 61 | print("Could not find {}".format(ADDON_CONFIG_MK)) 62 | 63 | print(REQUIRED_ADDONS) 64 | 65 | # Collect any required dependencies from the example*/addons.make files. 66 | for addon_mk in ADDON_PATH.glob("example*/addons.make"): 67 | for addon in addon_mk.open().readlines(): 68 | REQUIRED_ADDONS.add(addon.strip()) 69 | 70 | print(REQUIRED_ADDONS) 71 | 72 | # Remove this addon from the list. 73 | try: 74 | REQUIRED_ADDONS.remove(ADDON_NAME) 75 | except KeyError as err: 76 | print("Error removing {}".format(err)) 77 | 78 | for required_addon in REQUIRED_ADDONS: 79 | required_addon_path = OF_ADDONS.resolve() / required_addon 80 | print("Checking " + str(required_addon_path)) 81 | if not required_addon_path.exists(): 82 | repository = "https://github.com/" + GH_USERNAME + "/" + required_addon + ".git" 83 | print("cloning " + repository + " into " + str(required_addon_path)) 84 | subprocess.call(["git", "clone", repository, str(required_addon_path)]) 85 | print("done") 86 | -------------------------------------------------------------------------------- /example-raii/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "ofApp.h" 9 | 10 | 11 | void ofApp::setup() 12 | { 13 | ofSetFrameRate(30); 14 | ofEnableAlphaBlending(); 15 | 16 | // Example database. 17 | std::string transactionDb = ofToDataPath("transaction.sqlite", true); 18 | 19 | try 20 | { 21 | // Open a database file in create/write mode. 22 | SQLite::Database db(transactionDb, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); 23 | 24 | ofLogNotice("ofApp::setup()") << "SQLite database file '" << db.getFilename() << "' opened successfully."; 25 | 26 | db.exec("DROP TABLE IF EXISTS test"); 27 | 28 | // Example of a successful transaction : 29 | try 30 | { 31 | // Begin transaction 32 | SQLite::Transaction transaction(db); 33 | 34 | db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"); 35 | 36 | int nb = db.exec("INSERT INTO test VALUES (NULL, \"test\")"); 37 | 38 | ofLogNotice("ofApp::setup()") << "INSERT INTO test VALUES (NULL, \"test\")\", returned " << nb; 39 | 40 | // Commit transaction 41 | transaction.commit(); 42 | } 43 | catch (const std::exception& e) 44 | { 45 | ofLogError("ofApp::setup()") << "SQLite exception: " << e.what(); 46 | } 47 | 48 | // Example of a rollbacked transaction : 49 | try 50 | { 51 | // Begin transaction 52 | SQLite::Transaction transaction(db); 53 | 54 | int nb = db.exec("INSERT INTO test VALUES (NULL, \"second\")"); 55 | 56 | ofLogNotice("ofApp::setup()") << "INSERT INTO test VALUES (NULL, \"second\")\", returned " << nb; 57 | 58 | nb = db.exec("INSERT INTO test ObviousError"); 59 | 60 | ofLogNotice("ofApp::setup()") << "INSERT INTO test \"error\", returned " << nb; 61 | 62 | ofLogNotice("ofApp::setup()") << "SQLite SHOULD have exited ... "; 63 | 64 | // Commit transaction 65 | transaction.commit(); 66 | } 67 | catch (const std::exception& e) 68 | { 69 | ofLogError("ofApp::setup()") << "INTENTIONAL EXCEPTION: SQLite exception: " << e.what(); 70 | // expected error, see above 71 | } 72 | 73 | // Check the results (expect only one row of result, as the second one has been rollbacked by the error) 74 | SQLite::Statement query(db, "SELECT * FROM test"); 75 | 76 | ofLogNotice("ofApp::setup()") << "SELECT * FROM test :"; 77 | 78 | while (query.executeStep()) 79 | { 80 | ofLogNotice("ofApp::setup()") << "row (" << query.getColumn(0) << ", \"" << query.getColumn(1) << "\")"; 81 | } 82 | } 83 | catch (const std::exception& e) 84 | { 85 | ofLogError("ofApp::setup()") << "SQLite exception: " << e.what(); 86 | } 87 | 88 | // Clean up. 89 | ofFile::removeFile(transactionDb); 90 | } 91 | 92 | 93 | void ofApp::draw() 94 | { 95 | ofBackgroundGradient(ofColor::white, ofColor::black); 96 | 97 | ofDrawBitmapStringHighlight("See console for output.", ofPoint(30, 30)); 98 | 99 | } 100 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/VariadicBind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file VariadicBind.h 3 | * @ingroup SQLiteCpp 4 | * @brief Convenience function for Statement::bind(...) 5 | * 6 | * Copyright (c) 2016 Paul Dreik (github@pauldreik.se) 7 | * Copyright (c) 2016-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 8 | * Copyright (c) 2019 Maximilian Bachmann (contact@maxbachmann.de) 9 | * 10 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 11 | * or copy at http://opensource.org/licenses/MIT) 12 | */ 13 | #pragma once 14 | 15 | #if (__cplusplus >= 201103L) || ( defined(_MSC_VER) && (_MSC_VER >= 1800) ) // c++11: Visual Studio 2013 16 | 17 | #include 18 | 19 | #if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015 20 | #include 21 | #endif // c++14 22 | 23 | /// @cond 24 | #include 25 | #include 26 | 27 | namespace SQLite 28 | { 29 | /// @endcond 30 | 31 | /** 32 | * \brief Convenience function for calling Statement::bind(...) once for each argument given. 33 | * 34 | * This takes care of incrementing the index between each calls to bind. 35 | * 36 | * This feature requires a c++11 capable compiler. 37 | * 38 | * \code{.cpp} 39 | * SQLite::Statement stm("SELECT * FROM MyTable WHERE colA>? && colB=? && colC 50 | void bind(SQLite::Statement& query, const Args& ... args) 51 | { 52 | int pos = 0; 53 | (void)std::initializer_list{ 54 | ((void)query.bind(++pos, std::forward(args)), 0)... 55 | }; 56 | } 57 | 58 | #if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015 59 | 60 | /** 61 | * \brief Convenience function for calling Statement::bind(...) once for each parameter of a tuple, 62 | * by forwarding them to the variadic template 63 | * 64 | * This feature requires a c++14 capable compiler. 65 | * 66 | * \code{.cpp} 67 | * SQLite::Statement stm("SELECT * FROM MyTable WHERE colA>? && colB=? && colC 78 | void bind(SQLite::Statement& query, const std::tuple &tuple) 79 | { 80 | bind(query, tuple, std::index_sequence_for()); 81 | } 82 | 83 | /** 84 | * \brief Convenience function for calling Statement::bind(...) once for each parameter of a tuple, 85 | * by forwarding them to the variadic template. This function is just needed to convert the tuples 86 | * to parameter packs 87 | * 88 | * This feature requires a c++14 capable compiler. 89 | * 90 | * @param query statement 91 | * @param tuple tuple with values to bind 92 | */ 93 | template 94 | void bind(SQLite::Statement& query, const std::tuple &tuple, std::index_sequence) 95 | { 96 | bind(query, std::get(tuple)...); 97 | } 98 | #endif // c++14 99 | 100 | } // namespace SQLite 101 | 102 | #endif // c++11 103 | -------------------------------------------------------------------------------- /src/SQLiteConnectionPool.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #pragma once 9 | 10 | 11 | #include "ofTypes.h" 12 | #include 13 | #include "ofx/ObjectPool.h" 14 | #include "SQLiteConnection.h" 15 | 16 | 17 | namespace SQLite { 18 | 19 | 20 | template 21 | class SQLiteConnectionPoolFactory 22 | { 23 | public: 24 | SQLiteConnectionPoolFactory(const std::string& filename, 25 | SQLiteConnection::Mode mode, 26 | uint64_t databaseTimeoutMilliseconds): 27 | _filename(filename), 28 | _mode(mode), 29 | _databaseTimeoutMilliseconds(databaseTimeoutMilliseconds) 30 | { 31 | } 32 | 33 | SQLiteConnectionPoolFactory(const SQLiteConnectionPoolFactory& factory): 34 | _filename(factory._filename), 35 | _mode(factory._mode), 36 | _databaseTimeoutMilliseconds(factory._databaseTimeoutMilliseconds) 37 | { 38 | } 39 | 40 | std::shared_ptr createObject() 41 | { 42 | return std::make_shared(_filename, 43 | _mode, 44 | _databaseTimeoutMilliseconds, 45 | currentIndex++); 46 | } 47 | 48 | bool validateObject(std::shared_ptr _connection) 49 | { 50 | return true; 51 | } 52 | 53 | void activateObject(std::shared_ptr _connection) 54 | { 55 | _connection->increment(); 56 | } 57 | 58 | void deactivateObject(std::shared_ptr _connection) 59 | { 60 | } 61 | 62 | void destroyObject(std::shared_ptr _connection) 63 | { 64 | } 65 | 66 | private: 67 | std::string _filename; 68 | SQLiteConnection::Mode _mode; 69 | uint64_t _databaseTimeoutMilliseconds = 0; 70 | 71 | std::size_t currentIndex = 0; 72 | 73 | }; 74 | 75 | 76 | 77 | template 78 | class SQLiteConnectionPool_: public ofx::ObjectPool, SQLiteConnectionPoolFactory> 79 | { 80 | public: 81 | SQLiteConnectionPool_(const std::string& filename, 82 | SQLiteConnection::Mode mode = SQLiteConnection::Mode::READ_ONLY, 83 | uint64_t databaseTimeoutMilliseconds = 0, 84 | std::size_t capacity = DEFAULT_CAPACITY, 85 | std::size_t peakCapacity = DEFAULT_PEAK_CAPACITY): 86 | ofx::ObjectPool, SQLiteConnectionPoolFactory>(SQLiteConnectionPoolFactory(filename, mode, databaseTimeoutMilliseconds), capacity, peakCapacity) 87 | { 88 | } 89 | 90 | enum 91 | { 92 | DEFAULT_CAPACITY = 100, 93 | DEFAULT_PEAK_CAPACITY = 200 94 | }; 95 | 96 | std::string toString() const 97 | { 98 | std::stringstream ss; 99 | ss << "Capacity: " << this->capacity() << " Peak Capacity: " << this->peakCapacity() << " Size: " << this->size() << " Available: " << this->available(); 100 | return ss.str(); 101 | } 102 | }; 103 | 104 | 105 | typedef SQLiteConnectionPool_ SQLiteConnectionPool; 106 | 107 | 108 | 109 | } // nampace SQLite 110 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | docs/html 2 | docs/tagfile.xml 3 | docs/*.tag 4 | 5 | _*/ 6 | 7 | raw/ 8 | *.qbs 9 | 10 | build* 11 | exampl*/.compiler* 12 | exampl*/config.make 13 | exampl*/Makefile 14 | exampl*/Project.xcconfig 15 | exampl*/*.xcodeproj 16 | exampl*/*.plist 17 | 18 | *.sln 19 | *.vcxproj 20 | *.vcxproj.filters 21 | icon.rc 22 | 23 | *.mode1v3 24 | 25 | # xcode 26 | *.pbxuser 27 | *.perspectivev3 28 | xcuserdata 29 | build 30 | *.app 31 | #*.a 32 | 33 | # OSX 34 | .DS_Store 35 | .AppleDouble 36 | 37 | # codeblocks 38 | *.layout 39 | example/obj 40 | 41 | # Win 42 | *.exe 43 | *.dll 44 | ## Ignore Visual Studio temporary files, build results, and 45 | ## files generated by popular Visual Studio add-ons. 46 | 47 | # User-specific files 48 | *.suo 49 | *.user 50 | *.sln.docstates 51 | 52 | # Build results 53 | 54 | [Dd]ebug/ 55 | [Rr]elease/ 56 | x64/ 57 | build/ 58 | [Bb]in/ 59 | [Oo]bj/ 60 | 61 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 62 | !packages/*/build/ 63 | 64 | # MSTest test Results 65 | [Tt]est[Rr]esult*/ 66 | [Bb]uild[Ll]og.* 67 | 68 | *_i.c 69 | *_p.c 70 | *.ilk 71 | *.meta 72 | *.obj 73 | *.pch 74 | *.pdb 75 | *.pgc 76 | *.pgd 77 | *.rsp 78 | *.sbr 79 | *.tlb 80 | *.tli 81 | *.tlh 82 | *.tmp 83 | *.tmp_proj 84 | *.log 85 | *.vspscc 86 | *.vssscc 87 | .builds 88 | *.pidb 89 | *.log 90 | *.scc 91 | 92 | # Visual C++ cache files 93 | ipch/ 94 | *.aps 95 | *.ncb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | 100 | # Visual Studio profiler 101 | *.psess 102 | *.vsp 103 | *.vspx 104 | 105 | # Guidance Automation Toolkit 106 | *.gpState 107 | 108 | # ReSharper is a .NET coding add-in 109 | _ReSharper*/ 110 | *.[Rr]e[Ss]harper 111 | 112 | # TeamCity is a build add-in 113 | _TeamCity* 114 | 115 | # DotCover is a Code Coverage Tool 116 | *.dotCover 117 | 118 | # NCrunch 119 | *.ncrunch* 120 | .*crunch*.local.xml 121 | 122 | # Installshield output folder 123 | [Ee]xpress/ 124 | 125 | # DocProject is a documentation generator add-in 126 | DocProject/buildhelp/ 127 | DocProject/Help/*.HxT 128 | DocProject/Help/*.HxC 129 | DocProject/Help/*.hhc 130 | DocProject/Help/*.hhk 131 | DocProject/Help/*.hhp 132 | DocProject/Help/Html2 133 | DocProject/Help/html 134 | 135 | # Click-Once directory 136 | publish/ 137 | 138 | # Publish Web Output 139 | *.Publish.xml 140 | *.pubxml 141 | 142 | # NuGet Packages Directory 143 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 144 | #packages/ 145 | 146 | # Windows Azure Build Output 147 | csx 148 | *.build.csdef 149 | 150 | # Windows Store app package directory 151 | AppPackages/ 152 | 153 | # Others 154 | sql/ 155 | *.Cache 156 | ClientBin/ 157 | [Ss]tyle[Cc]op.* 158 | ~$* 159 | *~ 160 | *.dbmdl 161 | *.[Pp]ublish.xml 162 | *.pfx 163 | *.publishsettings 164 | 165 | # RIA/Silverlight projects 166 | Generated_Code/ 167 | 168 | # Backup & report files from converting an old project file to a newer 169 | # Visual Studio version. Backup files are not needed, because we have git ;-) 170 | _UpgradeReport_Files/ 171 | Backup*/ 172 | UpgradeLog*.XML 173 | UpgradeLog*.htm 174 | 175 | # SQL Server files 176 | App_Data/*.mdf 177 | App_Data/*.ldf 178 | 179 | # ========================= 180 | # Windows detritus 181 | # ========================= 182 | 183 | # Windows image file caches 184 | Thumbs.db 185 | ehthumbs.db 186 | 187 | # Folder config file 188 | Desktop.ini 189 | 190 | # Recycle Bin used on file shares 191 | $RECYCLE.BIN/ 192 | 193 | # Mac crap 194 | .DS_Store 195 | -------------------------------------------------------------------------------- /src/SQLiteConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #pragma once 9 | 10 | 11 | #include "SQLiteCpp.h" 12 | #include "ofConstants.h" 13 | 14 | 15 | namespace SQLite { 16 | 17 | 18 | /// \brief An SQLite connection that can cache Statements. 19 | /// 20 | /// This connection should not be accessed simultaneously by more than one 21 | /// thread. Connections are ideally accessed by a thread safe 22 | /// SQLiteConnectionPool. 23 | class SQLiteConnection 24 | { 25 | public: 26 | enum class Mode 27 | { 28 | /// \brief Read only mode. 29 | READ_ONLY, 30 | /// \brief Write mode, will not create a new file. 31 | READ_WRITE, 32 | /// \brief Write mode will create a new file if it doesn't exist. 33 | READ_WRITE_CREATE 34 | }; 35 | 36 | /// \brief Construct an SQLiteConnection with the given database and mode. 37 | /// \param filename The filename of the sqlite database. 38 | /// \param mode The access mode used during this connection. 39 | /// \param databaseTimeoutMilliseconds the SQLite setBusy value. 40 | /// \param index The index value for pool use. 41 | SQLiteConnection(const std::string& filename, 42 | Mode mode = Mode::READ_ONLY, 43 | uint64_t databaseTimeoutMilliseconds = 0, 44 | std::size_t index = 0); 45 | 46 | /// \brief Destroy the SQLiteConnection. 47 | virtual ~SQLiteConnection(); 48 | 49 | /// \returns a reference to the database. 50 | Database& database(); 51 | 52 | /// \returns a const reference to the database. 53 | const Database& database() const; 54 | 55 | /// \brief Query whether the prepared statement exists. 56 | /// \param query The query key to search for. 57 | /// \returns true if the given statement exists. 58 | bool hasStatement(const std::string& query) const; 59 | 60 | /// \brief Get a cached statement by string. 61 | /// 62 | /// Statements are stored in a map with the query as the unique key. 63 | /// 64 | /// If the statement was used previously, it will be reset and the bindings 65 | /// will be cleared before returning it. 66 | /// 67 | /// \query The query to use that defines the prepared Statement. 68 | /// \returns a reference to the prepared statement. 69 | Statement& getStatement(const std::string& query) const; 70 | 71 | std::size_t useCount() const 72 | { 73 | return _useCount; 74 | } 75 | 76 | std::size_t index() const 77 | { 78 | return _index; 79 | } 80 | 81 | void increment() 82 | { 83 | _useCount++; 84 | } 85 | 86 | protected: 87 | /// \brief Convert the SQLiteConnection::Mode to the native sqlite flags. 88 | /// \param mode The mode to convert. 89 | /// \returns the sqlite access flags. 90 | static int _toAccessFlag(Mode mode); 91 | 92 | /// \brief The connection access mode. 93 | Mode _mode = Mode::READ_ONLY; 94 | 95 | /// \brief The database to access. 96 | mutable Database _database; 97 | 98 | /// \brief A collection of prepared statements for this connection. 99 | /// 100 | /// These will be destroyed when the connection is destroyed. 101 | mutable std::map> _statements; 102 | 103 | std::size_t _useCount = 0; 104 | std::size_t _index = 0; 105 | }; 106 | 107 | 108 | } // nampace SQLite 109 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/Exception.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Exception.h 3 | * @ingroup SQLiteCpp 4 | * @brief Encapsulation of the error message from SQLite3 on a std::runtime_error. 5 | * 6 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #pragma once 12 | 13 | #include 14 | #include 15 | 16 | // Forward declaration to avoid inclusion of in a header 17 | struct sqlite3; 18 | 19 | /// Compatibility with non-clang compilers. 20 | #ifndef __has_feature 21 | #define __has_feature(x) 0 22 | #endif 23 | 24 | // Detect whether the compiler supports C++11 noexcept exception specifications. 25 | #if ( defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4)) \ 26 | && defined(__GXX_EXPERIMENTAL_CXX0X__)) 27 | // GCC 4.7 and following have noexcept 28 | #elif defined(__clang__) && __has_feature(cxx_noexcept) 29 | // Clang 3.0 and above have noexcept 30 | #elif defined(_MSC_VER) && _MSC_VER > 1800 31 | // Visual Studio 2015 and above have noexcept 32 | #else 33 | // Visual Studio 2013 does not support noexcept, and "throw()" is deprecated by C++11 34 | #define noexcept 35 | #endif 36 | 37 | 38 | namespace SQLite 39 | { 40 | 41 | 42 | /** 43 | * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. 44 | */ 45 | class Exception : public std::runtime_error 46 | { 47 | public: 48 | /** 49 | * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. 50 | * 51 | * @param[in] aErrorMessage The string message describing the SQLite error 52 | */ 53 | explicit Exception(const char* aErrorMessage); 54 | explicit Exception(const std::string& aErrorMessage); 55 | 56 | /** 57 | * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. 58 | * 59 | * @param[in] aErrorMessage The string message describing the SQLite error 60 | * @param[in] ret Return value from function call that failed. 61 | */ 62 | Exception(const char* aErrorMessage, int ret); 63 | Exception(const std::string& aErrorMessage, int ret); 64 | 65 | /** 66 | * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. 67 | * 68 | * @param[in] apSQLite The SQLite object, to obtain detailed error messages from. 69 | */ 70 | explicit Exception(sqlite3* apSQLite); 71 | 72 | /** 73 | * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. 74 | * 75 | * @param[in] apSQLite The SQLite object, to obtain detailed error messages from. 76 | * @param[in] ret Return value from function call that failed. 77 | */ 78 | Exception(sqlite3* apSQLite, int ret); 79 | 80 | /// Return the result code (if any, otherwise -1). 81 | inline int getErrorCode() const noexcept // nothrow 82 | { 83 | return mErrcode; 84 | } 85 | 86 | /// Return the extended numeric result code (if any, otherwise -1). 87 | inline int getExtendedErrorCode() const noexcept // nothrow 88 | { 89 | return mExtendedErrcode; 90 | } 91 | 92 | /// Return a string, solely based on the error code 93 | const char* getErrorStr() const noexcept; // nothrow 94 | 95 | private: 96 | int mErrcode; ///< Error code value 97 | int mExtendedErrcode; ///< Detailed error code if any 98 | }; 99 | 100 | 101 | } // namespace SQLite 102 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/src/Backup.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Backup.cpp 3 | * @ingroup SQLiteCpp 4 | * @brief Backup is used to backup a database file in a safe and online way. 5 | * 6 | * Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com) 7 | * Copyright (c) 2015-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 8 | * 9 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 10 | * or copy at http://opensource.org/licenses/MIT) 11 | */ 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | 18 | namespace SQLite 19 | { 20 | 21 | // Initialize resource for SQLite database backup 22 | Backup::Backup(Database& aDestDatabase, 23 | const char* apDestDatabaseName, 24 | Database& aSrcDatabase, 25 | const char* apSrcDatabaseName) : 26 | mpSQLiteBackup(NULL) 27 | { 28 | mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), 29 | apDestDatabaseName, 30 | aSrcDatabase.getHandle(), 31 | apSrcDatabaseName); 32 | if (NULL == mpSQLiteBackup) 33 | { 34 | // If an error occurs, the error code and message are attached to the destination database connection. 35 | throw SQLite::Exception(aDestDatabase.getHandle()); 36 | } 37 | } 38 | 39 | // Initialize resource for SQLite database backup 40 | Backup::Backup(Database& aDestDatabase, 41 | const std::string& aDestDatabaseName, 42 | Database& aSrcDatabase, 43 | const std::string& aSrcDatabaseName) : 44 | mpSQLiteBackup(NULL) 45 | { 46 | mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), 47 | aDestDatabaseName.c_str(), 48 | aSrcDatabase.getHandle(), 49 | aSrcDatabaseName.c_str()); 50 | if (NULL == mpSQLiteBackup) 51 | { 52 | // If an error occurs, the error code and message are attached to the destination database connection. 53 | throw SQLite::Exception(aDestDatabase.getHandle()); 54 | } 55 | } 56 | 57 | // Initialize resource for SQLite database backup 58 | Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) : 59 | mpSQLiteBackup(NULL) 60 | { 61 | mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), 62 | "main", 63 | aSrcDatabase.getHandle(), 64 | "main"); 65 | if (NULL == mpSQLiteBackup) 66 | { 67 | // If an error occurs, the error code and message are attached to the destination database connection. 68 | throw SQLite::Exception(aDestDatabase.getHandle()); 69 | } 70 | } 71 | 72 | // Release resource for SQLite database backup 73 | Backup::~Backup() 74 | { 75 | if (NULL != mpSQLiteBackup) 76 | { 77 | sqlite3_backup_finish(mpSQLiteBackup); 78 | } 79 | } 80 | 81 | // Execute backup step with a given number of source pages to be copied 82 | int Backup::executeStep(const int aNumPage /* = -1 */) 83 | { 84 | const int res = sqlite3_backup_step(mpSQLiteBackup, aNumPage); 85 | if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res) 86 | { 87 | throw SQLite::Exception(sqlite3_errstr(res), res); 88 | } 89 | return res; 90 | } 91 | 92 | // Get the number of remaining source pages to be copied in this backup process 93 | int Backup::getRemainingPageCount() 94 | { 95 | return sqlite3_backup_remaining(mpSQLiteBackup); 96 | } 97 | 98 | // Get the number of total source pages to be copied in this backup process 99 | int Backup::getTotalPageCount() 100 | { 101 | return sqlite3_backup_pagecount(mpSQLiteBackup); 102 | } 103 | 104 | } // namespace SQLite 105 | -------------------------------------------------------------------------------- /example/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Christopher Baker 3 | // 4 | // SPDX-License-Identifier: MIT 5 | // 6 | 7 | 8 | #include "ofApp.h" 9 | 10 | 11 | void ofApp::setup() 12 | { 13 | ofSetFrameRate(30); 14 | ofEnableAlphaBlending(); 15 | 16 | // Example database. 17 | std::string exampleDB = ofToDataPath("example.sqlite", true); 18 | 19 | try 20 | { 21 | // Open a database file in readonly mode 22 | SQLite::Database db(exampleDB); // SQLITE_OPEN_READONLY 23 | 24 | // Test if the 'test' table exists 25 | bool testExists = db.tableExists("test"); 26 | 27 | if (testExists) 28 | { 29 | ofLogNotice("ofApp::setup()") << "Test table did exist!"; 30 | } 31 | else 32 | { 33 | ofLogNotice("ofApp::setup()") << "Test table did NOT exist!"; 34 | } 35 | 36 | 37 | // Get a single value result with an easy to use shortcut 38 | std::string value = db.execAndGet("SELECT value FROM test WHERE id = 2"); 39 | 40 | ofLogNotice("ofApp::setup()") << "Value was: " << value; 41 | 42 | std::string queryString = ""; 43 | queryString += "SELECT id AS test_id, value AS test_val, weight AS test_weight "; 44 | queryString += "FROM test "; 45 | queryString += "WHERE weight > ?"; // We will bind a variable to the ?. 46 | 47 | // Compile a SQL query, containing one parameter (index 1) 48 | SQLite::Statement query(db, queryString); 49 | 50 | // See how many columns are in our prepared statement: 51 | 52 | ofLogNotice("ofApp::setup()") << "SQLite statement '" << query.getQuery() << "' compiled (" << query.getColumnCount() << " columns in the result)"; 53 | 54 | // Bind the integer value 2 to the first parameter of the SQL query 55 | query.bind(1, 2); 56 | 57 | // Loop to execute the query step by step, to get one a row of results at a time 58 | while (query.executeStep()) 59 | { 60 | // Demonstrate how to get some typed column value (and the equivalent explicit call) 61 | int id = query.getColumn(0); // = query.getColumn(0).getInt() 62 | std::string value2 = query.getColumn(1); // = query.getColumn(1).getText() 63 | int bytes = query.getColumn(1).getBytes(); 64 | double weight = query.getColumn(2); // = query.getColumn(2).getInt() 65 | 66 | static bool bFirst = true; 67 | if (bFirst) 68 | { 69 | // Show how to get the aliased names of the result columns. 70 | std::string name0 = query.getColumn(0).getName(); 71 | std::string name1 = query.getColumn(1).getName(); 72 | std::string name2 = query.getColumn(2).getName(); 73 | 74 | ofLogNotice("ofApp::setup()") << "aliased result [\"" << name0 << "\", \"" << name1 << "\", \"" << name2 << "\"]"; 75 | 76 | bFirst = false; 77 | } 78 | 79 | ofLogNotice("ofApp::setup()") << "row (" << id << ", \"" << value2 << "\" " << bytes << " bytes, " << weight << ")"; 80 | } 81 | 82 | // Reset the query to use it again. 83 | query.reset(); 84 | 85 | // Bind the string value "6" to the first parameter of the SQL query 86 | query.bind(1, "6"); 87 | 88 | while (query.executeStep()) 89 | { 90 | // Demonstrate that inserting column value in a std:ostream is natural 91 | ofLogNotice("ofApp::setup()") << "row (" << query.getColumn(0) << ", \"" << query.getColumn(1) << "\", " << query.getColumn(2) << ")"; 92 | } 93 | } 94 | catch (const std::exception& e) 95 | { 96 | ofLogError("ofApp::setup()") << "SQLite exception: " << e.what(); 97 | } 98 | 99 | } 100 | 101 | 102 | void ofApp::draw() 103 | { 104 | ofBackgroundGradient(ofColor::white, ofColor::black); 105 | ofDrawBitmapStringHighlight("See console for output.", ofPoint(30, 30)); 106 | } 107 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/src/Column.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Column.cpp 3 | * @ingroup SQLiteCpp 4 | * @brief Encapsulation of a Column in a row of the result pointed by the prepared SQLite::Statement. 5 | * 6 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | 18 | namespace SQLite 19 | { 20 | 21 | const int INTEGER = SQLITE_INTEGER; 22 | const int FLOAT = SQLITE_FLOAT; 23 | const int TEXT = SQLITE_TEXT; 24 | const int BLOB = SQLITE_BLOB; 25 | const int Null = SQLITE_NULL; 26 | 27 | 28 | // Encapsulation of a Column in a row of the result pointed by the prepared Statement. 29 | Column::Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept : // nothrow 30 | mStmtPtr(aStmtPtr), 31 | mIndex(aIndex) 32 | { 33 | } 34 | 35 | // Finalize and unregister the SQL query from the SQLite Database Connection. 36 | Column::~Column() 37 | { 38 | // the finalization will be done by the destructor of the last shared pointer 39 | } 40 | 41 | // Return the named assigned to this result column (potentially aliased) 42 | const char* Column::getName() const noexcept // nothrow 43 | { 44 | return sqlite3_column_name(mStmtPtr, mIndex); 45 | } 46 | 47 | #ifdef SQLITE_ENABLE_COLUMN_METADATA 48 | // Return the name of the table column that is the origin of this result column 49 | const char* Column::getOriginName() const noexcept // nothrow 50 | { 51 | return sqlite3_column_origin_name(mStmtPtr, mIndex); 52 | } 53 | #endif 54 | 55 | // Return the integer value of the column specified by its index starting at 0 56 | int Column::getInt() const noexcept // nothrow 57 | { 58 | return sqlite3_column_int(mStmtPtr, mIndex); 59 | } 60 | 61 | // Return the unsigned integer value of the column specified by its index starting at 0 62 | unsigned Column::getUInt() const noexcept // nothrow 63 | { 64 | return static_cast(getInt64()); 65 | } 66 | 67 | // Return the 64bits integer value of the column specified by its index starting at 0 68 | long long Column::getInt64() const noexcept // nothrow 69 | { 70 | return sqlite3_column_int64(mStmtPtr, mIndex); 71 | } 72 | 73 | // Return the double value of the column specified by its index starting at 0 74 | double Column::getDouble() const noexcept // nothrow 75 | { 76 | return sqlite3_column_double(mStmtPtr, mIndex); 77 | } 78 | 79 | // Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0 80 | const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept // nothrow 81 | { 82 | const char* pText = reinterpret_cast(sqlite3_column_text(mStmtPtr, mIndex)); 83 | return (pText?pText:apDefaultValue); 84 | } 85 | 86 | // Return a pointer to the blob value (*not* NULL terminated) of the column specified by its index starting at 0 87 | const void* Column::getBlob() const noexcept // nothrow 88 | { 89 | return sqlite3_column_blob(mStmtPtr, mIndex); 90 | } 91 | 92 | // Return a std::string to a TEXT or BLOB column 93 | std::string Column::getString() const 94 | { 95 | // Note: using sqlite3_column_blob and not sqlite3_column_text 96 | // - no need for sqlite3_column_text to add a \0 on the end, as we're getting the bytes length directly 97 | const char *data = static_cast(sqlite3_column_blob(mStmtPtr, mIndex)); 98 | 99 | // SQLite docs: "The safest policy is to invoke… sqlite3_column_blob() followed by sqlite3_column_bytes()" 100 | // Note: std::string is ok to pass nullptr as first arg, if length is 0 101 | return std::string(data, sqlite3_column_bytes(mStmtPtr, mIndex)); 102 | } 103 | 104 | // Return the type of the value of the column 105 | int Column::getType() const noexcept // nothrow 106 | { 107 | return sqlite3_column_type(mStmtPtr, mIndex); 108 | } 109 | 110 | // Return the number of bytes used by the text value of the column 111 | int Column::getBytes() const noexcept // nothrow 112 | { 113 | return sqlite3_column_bytes(mStmtPtr, mIndex); 114 | } 115 | 116 | // Standard std::ostream inserter 117 | std::ostream& operator<<(std::ostream& aStream, const Column& aColumn) 118 | { 119 | aStream.write(aColumn.getText(), aColumn.getBytes()); 120 | return aStream; 121 | } 122 | 123 | 124 | } // namespace SQLite 125 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/Backup.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Backup.h 3 | * @ingroup SQLiteCpp 4 | * @brief Backup is used to backup a database file in a safe and online way. 5 | * 6 | * Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com) 7 | * Copyright (c) 2015-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 8 | * 9 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 10 | * or copy at http://opensource.org/licenses/MIT) 11 | */ 12 | #pragma once 13 | 14 | #include 15 | 16 | #include 17 | 18 | // Forward declaration to avoid inclusion of in a header 19 | struct sqlite3_backup; 20 | 21 | namespace SQLite 22 | { 23 | 24 | /** 25 | * @brief RAII encapsulation of a SQLite Database Backup process. 26 | * 27 | * A Backup object is used to backup a source database file to a destination database file 28 | * in a safe and online way. 29 | * 30 | * Resource Acquisition Is Initialization (RAII) means that the Backup Resource 31 | * is allocated in the constructor and released in the destructor, so that there is 32 | * no need to worry about memory management or the validity of the underlying SQLite Backup. 33 | * 34 | * Thread-safety: a Backup object shall not be shared by multiple threads, because : 35 | * 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads 36 | * provided that no single database connection is used simultaneously in two or more threads." 37 | * 2) the SQLite "Serialized" mode is not supported by SQLiteC++, 38 | * because of the way it shares the underling SQLite precompiled statement 39 | * in a custom shared pointer (See the inner class "Statement::Ptr"). 40 | */ 41 | class Backup 42 | { 43 | public: 44 | /** 45 | * @brief Initialize a SQLite Backup object. 46 | * 47 | * Initialize a SQLite Backup object for the source database and destination database. 48 | * The database name is "main" for the main database, "temp" for the temporary database, 49 | * or the name specified after the AS keyword in an ATTACH statement for an attached database. 50 | * 51 | * Exception is thrown in case of error, then the Backup object is NOT constructed. 52 | * 53 | * @param[in] aDestDatabase Destination database connection 54 | * @param[in] apDestDatabaseName Destination database name 55 | * @param[in] aSrcDatabase Source database connection 56 | * @param[in] apSrcDatabaseName Source database name 57 | * 58 | * @throw SQLite::Exception in case of error 59 | */ 60 | Backup(Database& aDestDatabase, 61 | const char* apDestDatabaseName, 62 | Database& aSrcDatabase, 63 | const char* apSrcDatabaseName); 64 | 65 | /** 66 | * @brief Initialize a SQLite Backup object. 67 | * 68 | * Initialize a SQLite Backup object for source database and destination database. 69 | * The database name is "main" for the main database, "temp" for the temporary database, 70 | * or the name specified after the AS keyword in an ATTACH statement for an attached database. 71 | * 72 | * Exception is thrown in case of error, then the Backup object is NOT constructed. 73 | * 74 | * @param[in] aDestDatabase Destination database connection 75 | * @param[in] aDestDatabaseName Destination database name 76 | * @param[in] aSrcDatabase Source database connection 77 | * @param[in] aSrcDatabaseName Source database name 78 | * 79 | * @throw SQLite::Exception in case of error 80 | */ 81 | Backup(Database& aDestDatabase, 82 | const std::string& aDestDatabaseName, 83 | Database& aSrcDatabase, 84 | const std::string& aSrcDatabaseName); 85 | 86 | /** 87 | * @brief Initialize a SQLite Backup object for main databases. 88 | * 89 | * Initialize a SQLite Backup object for source database and destination database. 90 | * Backup the main databases between the source and the destination. 91 | * 92 | * Exception is thrown in case of error, then the Backup object is NOT constructed. 93 | * 94 | * @param[in] aDestDatabase Destination database connection 95 | * @param[in] aSrcDatabase Source database connection 96 | * 97 | * @throw SQLite::Exception in case of error 98 | */ 99 | Backup(Database& aDestDatabase, 100 | Database& aSrcDatabase); 101 | 102 | /// Release the SQLite Backup resource. 103 | ~Backup(); 104 | 105 | /** 106 | * @brief Execute a step of backup with a given number of source pages to be copied 107 | * 108 | * Exception is thrown when SQLITE_IOERR_XXX, SQLITE_NOMEM, or SQLITE_READONLY is returned 109 | * in sqlite3_backup_step(). These errors are considered fatal, so there is no point 110 | * in retrying the call to executeStep(). 111 | * 112 | * @param[in] aNumPage The number of source pages to be copied, with a negative value meaning all remaining source pages 113 | * 114 | * @return SQLITE_OK/SQLITE_DONE/SQLITE_BUSY/SQLITE_LOCKED 115 | * 116 | * @throw SQLite::Exception in case of error 117 | */ 118 | int executeStep(const int aNumPage = -1); 119 | 120 | /// Return the number of source pages still to be backed up as of the most recent call to executeStep(). 121 | int getRemainingPageCount(); 122 | 123 | /// Return the total number of pages in the source database as of the most recent call to executeStep(). 124 | int getTotalPageCount(); 125 | 126 | private: 127 | /// @{ Backup must be non-copyable 128 | Backup(const Backup&); 129 | Backup& operator=(const Backup&); 130 | /// @} 131 | 132 | private: 133 | sqlite3_backup* mpSQLiteBackup; ///< Pointer to SQLite Database Backup Handle 134 | }; 135 | 136 | } // namespace SQLite 137 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/Column.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Column.h 3 | * @ingroup SQLiteCpp 4 | * @brief Encapsulation of a Column in a row of the result pointed by the prepared SQLite::Statement. 5 | * 6 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #pragma once 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include // For INT_MAX 18 | 19 | 20 | namespace SQLite 21 | { 22 | 23 | extern const int INTEGER; ///< SQLITE_INTEGER 24 | extern const int FLOAT; ///< SQLITE_FLOAT 25 | extern const int TEXT; ///< SQLITE_TEXT 26 | extern const int BLOB; ///< SQLITE_BLOB 27 | extern const int Null; ///< SQLITE_NULL 28 | 29 | 30 | /** 31 | * @brief Encapsulation of a Column in a row of the result pointed by the prepared Statement. 32 | * 33 | * A Column is a particular field of SQLite data in the current row of result 34 | * of the Statement : it points to a single cell. 35 | * 36 | * Its value can be expressed as a text, and, when applicable, as a numeric 37 | * (integer or floating point) or a binary blob. 38 | * 39 | * Thread-safety: a Column object shall not be shared by multiple threads, because : 40 | * 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads 41 | * provided that no single database connection is used simultaneously in two or more threads." 42 | * 2) the SQLite "Serialized" mode is not supported by SQLiteC++, 43 | * because of the way it shares the underling SQLite precompiled statement 44 | * in a custom shared pointer (See the inner class "Statement::Ptr"). 45 | */ 46 | class Column 47 | { 48 | public: 49 | /** 50 | * @brief Encapsulation of a Column in a Row of the result. 51 | * 52 | * @param[in] aStmtPtr Shared pointer to the prepared SQLite Statement Object. 53 | * @param[in] aIndex Index of the column in the row of result, starting at 0 54 | */ 55 | Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept; // nothrow 56 | /// Simple destructor 57 | ~Column(); 58 | 59 | // default copy constructor and assignment operator are perfectly suited : 60 | // they copy the Statement::Ptr which in turn increments the reference counter. 61 | 62 | /// Make clang happy by explicitly implementing the copy-constructor: 63 | Column(const Column & aOther) : 64 | mStmtPtr(aOther.mStmtPtr), 65 | mIndex(aOther.mIndex) 66 | { 67 | } 68 | 69 | /** 70 | * @brief Return a pointer to the named assigned to this result column (potentially aliased) 71 | * 72 | * @see getOriginName() to get original column name (not aliased) 73 | */ 74 | const char* getName() const noexcept; // nothrow 75 | 76 | #ifdef SQLITE_ENABLE_COLUMN_METADATA 77 | /** 78 | * @brief Return a pointer to the table column name that is the origin of this result column 79 | * 80 | * Require definition of the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro : 81 | * - when building the SQLite library itself (which is the case for the Debian libsqlite3 binary for instance), 82 | * - and also when compiling this wrapper. 83 | */ 84 | const char* getOriginName() const noexcept; // nothrow 85 | #endif 86 | 87 | /// Return the integer value of the column. 88 | int getInt() const noexcept; // nothrow 89 | /// Return the 32bits unsigned integer value of the column (note that SQLite3 does not support unsigned 64bits). 90 | unsigned getUInt() const noexcept; // nothrow 91 | /// Return the 64bits integer value of the column (note that SQLite3 does not support unsigned 64bits). 92 | long long getInt64() const noexcept; // nothrow 93 | /// Return the double (64bits float) value of the column 94 | double getDouble() const noexcept; // nothrow 95 | /** 96 | * @brief Return a pointer to the text value (NULL terminated string) of the column. 97 | * 98 | * @warning The value pointed at is only valid while the statement is valid (ie. not finalized), 99 | * thus you must copy it before using it beyond its scope (to a std::string for instance). 100 | */ 101 | const char* getText(const char* apDefaultValue = "") const noexcept; // nothrow 102 | /** 103 | * @brief Return a pointer to the binary blob value of the column. 104 | * 105 | * @warning The value pointed at is only valid while the statement is valid (ie. not finalized), 106 | * thus you must copy it before using it beyond its scope (to a std::string for instance). 107 | */ 108 | const void* getBlob() const noexcept; // nothrow 109 | /** 110 | * @brief Return a std::string for a TEXT or BLOB column. 111 | * 112 | * Note this correctly handles strings that contain null bytes. 113 | */ 114 | std::string getString() const; 115 | 116 | /** 117 | * @brief Return the type of the value of the column 118 | * 119 | * Return either SQLite::INTEGER, SQLite::FLOAT, SQLite::TEXT, SQLite::BLOB, or SQLite::Null. 120 | * 121 | * @warning After a type conversion (by a call to a getXxx on a Column of a Yyy type), 122 | * the value returned by sqlite3_column_type() is undefined. 123 | */ 124 | int getType() const noexcept; // nothrow 125 | 126 | /// Test if the column is an integer type value (meaningful only before any conversion) 127 | inline bool isInteger() const noexcept // nothrow 128 | { 129 | return (SQLite::INTEGER == getType()); 130 | } 131 | /// Test if the column is a floating point type value (meaningful only before any conversion) 132 | inline bool isFloat() const noexcept // nothrow 133 | { 134 | return (SQLite::FLOAT == getType()); 135 | } 136 | /// Test if the column is a text type value (meaningful only before any conversion) 137 | inline bool isText() const noexcept // nothrow 138 | { 139 | return (SQLite::TEXT == getType()); 140 | } 141 | /// Test if the column is a binary blob type value (meaningful only before any conversion) 142 | inline bool isBlob() const noexcept // nothrow 143 | { 144 | return (SQLite::BLOB == getType()); 145 | } 146 | /// Test if the column is NULL (meaningful only before any conversion) 147 | inline bool isNull() const noexcept // nothrow 148 | { 149 | return (SQLite::Null == getType()); 150 | } 151 | 152 | /** 153 | * @brief Return the number of bytes used by the text (or blob) value of the column 154 | * 155 | * Return either : 156 | * - size in bytes (not in characters) of the string returned by getText() without the '\0' terminator 157 | * - size in bytes of the string representation of the numerical value (integer or double) 158 | * - size in bytes of the binary blob returned by getBlob() 159 | * - 0 for a NULL value 160 | */ 161 | int getBytes() const noexcept; 162 | 163 | /// Alias returning the number of bytes used by the text (or blob) value of the column 164 | inline int size() const noexcept 165 | { 166 | return getBytes (); 167 | } 168 | 169 | /// Inline cast operator to char 170 | inline operator char() const 171 | { 172 | return static_cast(getInt()); 173 | } 174 | /// Inline cast operator to unsigned char 175 | inline operator unsigned char() const 176 | { 177 | return static_cast(getInt()); 178 | } 179 | /// Inline cast operator to short 180 | inline operator short() const 181 | { 182 | return static_cast(getInt()); 183 | } 184 | /// Inline cast operator to unsigned short 185 | inline operator unsigned short() const 186 | { 187 | return static_cast(getInt()); 188 | } 189 | 190 | /// Inline cast operator to int 191 | inline operator int() const 192 | { 193 | return getInt(); 194 | } 195 | /// Inline cast operator to 32bits unsigned integer 196 | inline operator unsigned int() const 197 | { 198 | return getUInt(); 199 | } 200 | #if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW) 201 | /// Inline cast operator to 32bits long 202 | inline operator long() const 203 | { 204 | return getInt(); 205 | } 206 | /// Inline cast operator to 32bits unsigned long 207 | inline operator unsigned long() const 208 | { 209 | return getUInt(); 210 | } 211 | #else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS) 212 | /// Inline cast operator to 64bits long when the data model of the system is LP64 (Linux 64 bits...) 213 | inline operator long() const 214 | { 215 | return getInt64(); 216 | } 217 | #endif 218 | 219 | /// Inline cast operator to 64bits integer 220 | inline operator long long() const 221 | { 222 | return getInt64(); 223 | } 224 | /// Inline cast operator to double 225 | inline operator double() const 226 | { 227 | return getDouble(); 228 | } 229 | /** 230 | * @brief Inline cast operator to char* 231 | * 232 | * @see getText 233 | */ 234 | inline operator const char*() const 235 | { 236 | return getText(); 237 | } 238 | /** 239 | * @brief Inline cast operator to void* 240 | * 241 | * @see getBlob 242 | */ 243 | inline operator const void*() const 244 | { 245 | return getBlob(); 246 | } 247 | 248 | #if !defined(_MSC_VER) || _MSC_VER >= 1900 249 | // NOTE : the following is required by GCC and Clang to cast a Column result in a std::string 250 | // (error: conversion from ‘SQLite::Column’ to non-scalar type ‘std::string {aka std::basic_string}’) 251 | // and also required for Microsoft Visual Studio 2015 and newer 252 | // but is not working under Microsoft Visual Studio 2010, 2012 and 2013 253 | // (error C2440: 'initializing' : cannot convert from 'SQLite::Column' to 'std::basic_string<_Elem,_Traits,_Ax>' 254 | // [...] constructor overload resolution was ambiguous) 255 | // WARNING: without it, trying to access a binary blob with implicit cast to string 256 | // ends up converting it to a C-style char*, damaging the data by truncating it to the first null character! 257 | // (see https://github.com/SRombauts/SQLiteCpp/issues/189 Visual Studio 2013: unit test "Column.basis" failing) 258 | /** 259 | * @brief Inline cast operator to std::string 260 | * 261 | * Handles BLOB or TEXT, which may contain null bytes within 262 | * 263 | * @see getString 264 | */ 265 | inline operator std::string() const 266 | { 267 | return getString(); 268 | } 269 | #endif 270 | 271 | private: 272 | Statement::Ptr mStmtPtr; ///< Shared Pointer to the prepared SQLite Statement Object 273 | int mIndex; ///< Index of the column in the row of result, starting at 0 274 | }; 275 | 276 | /** 277 | * @brief Standard std::ostream text inserter 278 | * 279 | * Insert the text value of the Column object, using getText(), into the provided stream. 280 | * 281 | * @param[in] aStream Stream to use 282 | * @param[in] aColumn Column object to insert into the provided stream 283 | * 284 | * @return Reference to the stream used 285 | */ 286 | std::ostream& operator<<(std::ostream& aStream, const Column& aColumn); 287 | 288 | #if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) 289 | 290 | // Create an instance of T from the first N columns, see declaration in Statement.h for full details 291 | template 292 | T Statement::getColumns() 293 | { 294 | checkRow(); 295 | checkIndex(N - 1); 296 | return getColumns(std::make_integer_sequence{}); 297 | } 298 | 299 | // Helper function called by getColums 300 | template 301 | T Statement::getColumns(const std::integer_sequence) 302 | { 303 | return T{Column(mStmtPtr, Is)...}; 304 | } 305 | 306 | #endif 307 | 308 | } // namespace SQLite 309 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/src/Database.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Database.cpp 3 | * @ingroup SQLiteCpp 4 | * @brief Management of a SQLite Database Connection. 5 | * 6 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #ifndef SQLITE_DETERMINISTIC 22 | #define SQLITE_DETERMINISTIC 0x800 23 | #endif // SQLITE_DETERMINISTIC 24 | 25 | 26 | namespace SQLite 27 | { 28 | 29 | const int OPEN_READONLY = SQLITE_OPEN_READONLY; 30 | const int OPEN_READWRITE = SQLITE_OPEN_READWRITE; 31 | const int OPEN_CREATE = SQLITE_OPEN_CREATE; 32 | const int OPEN_URI = SQLITE_OPEN_URI; 33 | 34 | const int OK = SQLITE_OK; 35 | 36 | const char* VERSION = SQLITE_VERSION; 37 | const int VERSION_NUMBER = SQLITE_VERSION_NUMBER; 38 | 39 | // Return SQLite version string using runtime call to the compiled library 40 | const char* getLibVersion() noexcept // nothrow 41 | { 42 | return sqlite3_libversion(); 43 | } 44 | 45 | // Return SQLite version number using runtime call to the compiled library 46 | int getLibVersionNumber() noexcept // nothrow 47 | { 48 | return sqlite3_libversion_number(); 49 | } 50 | 51 | 52 | // Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags. 53 | Database::Database(const char* apFilename, 54 | const int aFlags /* = SQLite::OPEN_READONLY*/, 55 | const int aBusyTimeoutMs /* = 0 */, 56 | const char* apVfs /* = nullptr*/) : 57 | mpSQLite(nullptr), 58 | mFilename(apFilename) 59 | { 60 | const int ret = sqlite3_open_v2(apFilename, &mpSQLite, aFlags, apVfs); 61 | if (SQLITE_OK != ret) 62 | { 63 | const SQLite::Exception exception(mpSQLite, ret); // must create before closing 64 | sqlite3_close(mpSQLite); // close is required even in case of error on opening 65 | throw exception; 66 | } 67 | if (aBusyTimeoutMs > 0) 68 | { 69 | setBusyTimeout(aBusyTimeoutMs); 70 | } 71 | } 72 | 73 | // Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags. 74 | Database::Database(const std::string& aFilename, 75 | const int aFlags /* = SQLite::OPEN_READONLY*/, 76 | const int aBusyTimeoutMs /* = 0 */, 77 | const std::string& aVfs /* = "" */) : 78 | mpSQLite(nullptr), 79 | mFilename(aFilename) 80 | { 81 | const int ret = sqlite3_open_v2(aFilename.c_str(), &mpSQLite, aFlags, aVfs.empty() ? nullptr : aVfs.c_str()); 82 | if (SQLITE_OK != ret) 83 | { 84 | const SQLite::Exception exception(mpSQLite, ret); // must create before closing 85 | sqlite3_close(mpSQLite); // close is required even in case of error on opening 86 | throw exception; 87 | } 88 | if (aBusyTimeoutMs > 0) 89 | { 90 | setBusyTimeout(aBusyTimeoutMs); 91 | } 92 | } 93 | 94 | // Close the SQLite database connection. 95 | Database::~Database() 96 | { 97 | const int ret = sqlite3_close(mpSQLite); 98 | 99 | // Avoid unreferenced variable warning when build in release mode 100 | (void) ret; 101 | 102 | // Only case of error is SQLITE_BUSY: "database is locked" (some statements are not finalized) 103 | // Never throw an exception in a destructor : 104 | SQLITECPP_ASSERT(SQLITE_OK == ret, "database is locked"); // See SQLITECPP_ENABLE_ASSERT_HANDLER 105 | } 106 | 107 | /** 108 | * @brief Set a busy handler that sleeps for a specified amount of time when a table is locked. 109 | * 110 | * This is useful in multithreaded program to handle case where a table is locked for writting by a thread. 111 | * Any other thread cannot access the table and will receive a SQLITE_BUSY error: 112 | * setting a timeout will wait and retry up to the time specified before returning this SQLITE_BUSY error. 113 | * Reading the value of timeout for current connection can be done with SQL query "PRAGMA busy_timeout;". 114 | * Default busy timeout is 0ms. 115 | * 116 | * @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY 117 | * 118 | * @throw SQLite::Exception in case of error 119 | */ 120 | void Database::setBusyTimeout(const int aBusyTimeoutMs) 121 | { 122 | const int ret = sqlite3_busy_timeout(mpSQLite, aBusyTimeoutMs); 123 | check(ret); 124 | } 125 | 126 | // Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...). 127 | int Database::exec(const char* apQueries) 128 | { 129 | const int ret = sqlite3_exec(mpSQLite, apQueries, nullptr, nullptr, nullptr); 130 | check(ret); 131 | 132 | // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only) 133 | return sqlite3_changes(mpSQLite); 134 | } 135 | 136 | // Shortcut to execute a one step query and fetch the first column of the result. 137 | // WARNING: Be very careful with this dangerous method: you have to 138 | // make a COPY OF THE result, else it will be destroy before the next line 139 | // (when the underlying temporary Statement and Column objects are destroyed) 140 | // this is an issue only for pointer type result (ie. char* and blob) 141 | // (use the Column copy-constructor) 142 | Column Database::execAndGet(const char* apQuery) 143 | { 144 | Statement query(*this, apQuery); 145 | (void)query.executeStep(); // Can return false if no result, which will throw next line in getColumn() 146 | return query.getColumn(0); 147 | } 148 | 149 | // Shortcut to test if a table exists. 150 | bool Database::tableExists(const char* apTableName) 151 | { 152 | Statement query(*this, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?"); 153 | query.bind(1, apTableName); 154 | (void)query.executeStep(); // Cannot return false, as the above query always return a result 155 | return (1 == query.getColumn(0).getInt()); 156 | } 157 | 158 | // Get the rowid of the most recent successful INSERT into the database from the current connection. 159 | long long Database::getLastInsertRowid() const noexcept // nothrow 160 | { 161 | return sqlite3_last_insert_rowid(mpSQLite); 162 | } 163 | 164 | // Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection. 165 | int Database::getTotalChanges() const noexcept // nothrow 166 | { 167 | return sqlite3_total_changes(mpSQLite); 168 | } 169 | 170 | // Return the numeric result code for the most recent failed API call (if any). 171 | int Database::getErrorCode() const noexcept // nothrow 172 | { 173 | return sqlite3_errcode(mpSQLite); 174 | } 175 | 176 | // Return the extended numeric result code for the most recent failed API call (if any). 177 | int Database::getExtendedErrorCode() const noexcept // nothrow 178 | { 179 | return sqlite3_extended_errcode(mpSQLite); 180 | } 181 | 182 | // Return UTF-8 encoded English language explanation of the most recent failed API call (if any). 183 | const char* Database::getErrorMsg() const noexcept // nothrow 184 | { 185 | return sqlite3_errmsg(mpSQLite); 186 | } 187 | 188 | // Attach a custom function to your sqlite database. Assumes UTF8 text representation. 189 | // Parameter details can be found here: http://www.sqlite.org/c3ref/create_function.html 190 | void Database::createFunction(const char* apFuncName, 191 | int aNbArg, 192 | bool abDeterministic, 193 | void* apApp, 194 | void (*apFunc)(sqlite3_context *, int, sqlite3_value **), 195 | void (*apStep)(sqlite3_context *, int, sqlite3_value **), 196 | void (*apFinal)(sqlite3_context *), // NOLINT(readability/casting) 197 | void (*apDestroy)(void *)) 198 | { 199 | int TextRep = SQLITE_UTF8; 200 | // optimization if deterministic function (e.g. of nondeterministic function random()) 201 | if (abDeterministic) 202 | { 203 | TextRep = TextRep|SQLITE_DETERMINISTIC; 204 | } 205 | const int ret = sqlite3_create_function_v2(mpSQLite, apFuncName, aNbArg, TextRep, 206 | apApp, apFunc, apStep, apFinal, apDestroy); 207 | check(ret); 208 | } 209 | 210 | // Load an extension into the sqlite database. Only affects the current connection. 211 | // Parameter details can be found here: http://www.sqlite.org/c3ref/load_extension.html 212 | void Database::loadExtension(const char* apExtensionName, const char *apEntryPointName) 213 | { 214 | #ifdef SQLITE_OMIT_LOAD_EXTENSION 215 | // Unused 216 | (void)apExtensionName; 217 | (void)apEntryPointName; 218 | 219 | throw std::runtime_error("sqlite extensions are disabled"); 220 | #else 221 | #ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION // Since SQLite 3.13 (2016-05-18): 222 | // Security warning: 223 | // It is recommended that the SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION method be used to enable only this interface. 224 | // The use of the sqlite3_enable_load_extension() interface should be avoided to keep the SQL load_extension() 225 | // disabled and prevent SQL injections from giving attackers access to extension loading capabilities. 226 | // (NOTE: not using nullptr: cannot pass object of non-POD type 'std::__1::nullptr_t' through variadic function) 227 | int ret = sqlite3_db_config(mpSQLite, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL); // NOTE: not using nullptr 228 | #else 229 | int ret = sqlite3_enable_load_extension(mpSQLite, 1); 230 | #endif 231 | check(ret); 232 | 233 | ret = sqlite3_load_extension(mpSQLite, apExtensionName, apEntryPointName, 0); 234 | check(ret); 235 | #endif 236 | } 237 | 238 | // Set the key for the current sqlite database instance. 239 | void Database::key(const std::string& aKey) const 240 | { 241 | int passLen = static_cast(aKey.length()); 242 | #ifdef SQLITE_HAS_CODEC 243 | if (passLen > 0) 244 | { 245 | const int ret = sqlite3_key(mpSQLite, aKey.c_str(), passLen); 246 | check(ret); 247 | } 248 | #else // SQLITE_HAS_CODEC 249 | if (passLen > 0) 250 | { 251 | const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable."); 252 | throw exception; 253 | } 254 | #endif // SQLITE_HAS_CODEC 255 | } 256 | 257 | // Reset the key for the current sqlite database instance. 258 | void Database::rekey(const std::string& aNewKey) const 259 | { 260 | #ifdef SQLITE_HAS_CODEC 261 | int passLen = aNewKey.length(); 262 | if (passLen > 0) 263 | { 264 | const int ret = sqlite3_rekey(mpSQLite, aNewKey.c_str(), passLen); 265 | check(ret); 266 | } 267 | else 268 | { 269 | const int ret = sqlite3_rekey(mpSQLite, nullptr, 0); 270 | check(ret); 271 | } 272 | #else // SQLITE_HAS_CODEC 273 | static_cast(aNewKey); // silence unused parameter warning 274 | const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable."); 275 | throw exception; 276 | #endif // SQLITE_HAS_CODEC 277 | } 278 | 279 | // Test if a file contains an unencrypted database. 280 | bool Database::isUnencrypted(const std::string& aFilename) 281 | { 282 | if (aFilename.length() > 0) 283 | { 284 | std::ifstream fileBuffer(aFilename.c_str(), std::ios::in | std::ios::binary); 285 | char header[16]; 286 | if (fileBuffer.is_open()) 287 | { 288 | fileBuffer.seekg(0, std::ios::beg); 289 | fileBuffer.getline(header, 16); 290 | fileBuffer.close(); 291 | } 292 | else 293 | { 294 | const SQLite::Exception exception("Error opening file: " + aFilename); 295 | throw exception; 296 | } 297 | return strncmp(header, "SQLite format 3\000", 16) == 0; 298 | } 299 | const SQLite::Exception exception("Could not open database, the aFilename parameter was empty."); 300 | throw exception; 301 | } 302 | 303 | // This is a reference implementation of live backup taken from the official sit: 304 | // https://www.sqlite.org/backup.html 305 | 306 | int Database::backup(const char* zFilename, BackupType type) { 307 | /* Open the database file identified by zFilename. Exit early if this fails. */ 308 | sqlite3* pFile; 309 | int rc = sqlite3_open(zFilename, &pFile); 310 | if (rc == SQLITE_OK) 311 | { 312 | /* If this is a 'load' operation (isSave==0), then data is copied 313 | ** from the database file just opened to database mpSQLite. 314 | ** Otherwise, if this is a 'save' operation (isSave==1), then data 315 | ** is copied from mpSQLite to pFile. Set the variables pFrom and 316 | ** pTo accordingly. */ 317 | sqlite3* pFrom = (type == Save ? mpSQLite : pFile); 318 | sqlite3* pTo = (type == Save ? pFile : mpSQLite); 319 | 320 | /* Set up the backup procedure to copy from the "main" database of 321 | ** connection pFile to the main database of connection mpSQLite. 322 | ** If something goes wrong, pBackup will be set to NULL and an error 323 | ** code and message left in connection pTo. 324 | ** 325 | ** If the backup object is successfully created, call backup_step() 326 | ** to copy data from pFile to mpSQLite. Then call backup_finish() 327 | ** to release resources associated with the pBackup object. If an 328 | ** error occurred, then an error code and message will be left in 329 | ** connection pTo. If no error occurred, then the error code belonging 330 | ** to pTo is set to SQLITE_OK. 331 | */ 332 | sqlite3_backup *pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main"); 333 | if (pBackup) 334 | { 335 | sqlite3_backup_step(pBackup, -1); 336 | sqlite3_backup_finish(pBackup); 337 | } 338 | rc = sqlite3_errcode(pTo); 339 | } 340 | 341 | /* Close the database connection opened on database file zFilename 342 | ** and return the result of this function. */ 343 | sqlite3_close(pFile); 344 | return rc; 345 | } 346 | 347 | } // namespace SQLite 348 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/README.md: -------------------------------------------------------------------------------- 1 | SQLiteC++ 2 | --------- 3 | 4 | [![release](https://img.shields.io/github/release/SRombauts/SQLiteCpp.svg)](https://github.com/SRombauts/SQLiteCpp/releases) 5 | [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/SRombauts/SQLiteCpp/blob/master/LICENSE.txt) 6 | [![Travis CI Linux Build Status](https://travis-ci.org/SRombauts/SQLiteCpp.svg)](https://travis-ci.org/SRombauts/SQLiteCpp "Travis CI Linux Build Status") 7 | [![AppVeyor Windows Build status](https://ci.appveyor.com/api/projects/status/github/SRombauts/SQLiteCpp?svg=true)](https://ci.appveyor.com/project/SbastienRombauts/SQLiteCpp "AppVeyor Windows Build status") 8 | [![Coveralls](https://img.shields.io/coveralls/SRombauts/SQLiteCpp.svg)](https://coveralls.io/github/SRombauts/SQLiteCpp "Coveralls test coverage") 9 | [![Coverity](https://img.shields.io/coverity/scan/14508.svg)](https://scan.coverity.com/projects/srombauts-sqlitecpp "Coverity Scan Build Status") 10 | [![Join the chat at https://gitter.im/SRombauts/SQLiteCpp](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/SRombauts/SQLiteCpp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 11 | 12 | SQLiteC++ (SQLiteCpp) is a smart and easy to use C++ SQLite3 wrapper. 13 | 14 | Keywords: sqlite, sqlite3, C, library, wrapper C++ 15 | 16 | ## About SQLiteC++: 17 | 18 | SQLiteC++ offers an encapsulation around the native C APIs of SQLite, 19 | with a few intuitive and well documented C++ classes. 20 | 21 | ### License: 22 | 23 | Copyright (c) 2012-2019 Sébastien Rombauts (sebastien.rombauts@gmail.com) 24 | 25 | 26 | Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 27 | or copy at http://opensource.org/licenses/MIT) 28 | 29 | #### Note on redistribution of SQLite source files 30 | 31 | As stated by the MIT License, you are welcome to reuse, modify, and redistribute the SQLiteCpp source code 32 | the way you want it to, be it a git submodule, a subdirectory, or a selection of some source files. 33 | 34 | I would love a mention in your README, a web link to the SQLite repository, and a mention of the author, 35 | but none of those are mandatory. 36 | 37 | ### About SQLite underlying library: 38 | 39 | SQLite is a library that implements a serverless transactional SQL database engine. 40 | It is the most widely deployed SQL database engine in the world. 41 | All of the code and documentation in SQLite has been dedicated to the public domain by the authors. 42 | http://www.sqlite.org/about.html 43 | 44 | ### The goals of SQLiteC++ are: 45 | 46 | - to offer the best of the existing simple C++ SQLite wrappers 47 | - to be elegantly written with good C++ design, STL, exceptions and RAII idiom 48 | - to keep dependencies to a minimum (STL and SQLite3) 49 | - to be portable 50 | - to be light and fast 51 | - to be thread-safe only as much as SQLite "Multi-thread" mode (see below) 52 | - to have a good unit test coverage 53 | - to use API names sticking with those of the SQLite library 54 | - to be well documented with Doxygen tags, and with some good examples 55 | - to be well maintained 56 | - to use a permissive MIT license, similar to BSD or Boost, for proprietary/commercial usage 57 | 58 | It is designed using the Resource Acquisition Is Initialization (RAII) idiom 59 | (see http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization), 60 | and throwing exceptions in case of SQLite errors (exept in destructors, 61 | where assert() are used instead). 62 | Each SQLiteC++ object must be constructed with a valid SQLite database connection, 63 | and then is always valid until destroyed. 64 | 65 | ### Supported platforms: 66 | 67 | Developements and tests are done under the following OSs: 68 | - Ubuntu 14.04 (Travis CI) 69 | - Windows 10, and Windows Server 2012 R2 & Windows Server 2016 (AppVeyor) 70 | - OS X 10.11 (Travis CI) 71 | 72 | And the following IDEs/Compilers 73 | - GCC 4.8.4, 4.9.3, 5.3.0 and 6.1.1 (C++03, C++11, C++14, C++1z) 74 | - Clang 3.5 and 3.8 75 | - Xcode 8 76 | - Visual Studio Community 2017, and VS 2013 & 2015 (AppVeyor) 77 | 78 | ### Dependencies 79 | 80 | - an STL implementation (even an old one, like the one provided with VC6 should work) 81 | - exception support (the class Exception inherits from std::runtime_error) 82 | - 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), 83 | or by adding its source file in your project code base (source code provided in src/sqlite3 for Windows), 84 | with the SQLITE_ENABLE_COLUMN_METADATA macro defined (see http://www.sqlite.org/compile.html#enable_column_metadata). 85 | 86 | ## Getting started 87 | ### Installation 88 | 89 | To use this wrapper, you need to add the SQLiteC++ source files from the src/ directory 90 | in your project code base, and compile/link against the sqlite library. 91 | 92 | The easiest way to do this is to add the wrapper as a library. 93 | The "CMakeLists.txt" file defining the static library is provided in the root directory, 94 | so you simply have to add_subdirectory(SQLiteCpp) to you main CMakeLists.txt 95 | and link to the "SQLiteCpp" wrapper library. 96 | 97 | Example for Linux: 98 | ```cmake 99 | add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp) 100 | 101 | include_directories( 102 | ${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp/include 103 | ) 104 | 105 | add_executable(main src/main.cpp) 106 | target_link_libraries(main 107 | SQLiteCpp 108 | sqlite3 109 | pthread 110 | dl 111 | ) 112 | ``` 113 | Thus this SQLiteCpp repository can be directly used as a Git submoldule. 114 | See the [SQLiteCpp_Example](https://github.com/SRombauts/SQLiteCpp_Example) side repository for a standalone "from scratch" example. 115 | 116 | Under Debian/Ubuntu/Mint Linux, you can install the libsqlite3-dev package if you don't want to use the embedded sqlite3 library. 117 | 118 | ### Building example and unit-tests: 119 | 120 | Use git to clone the repository. Then init and update submodule "googletest". 121 | 122 | ```Shell 123 | git clone https://github.com/SRombauts/SQLiteCpp.git 124 | cd SQLiteCpp 125 | git submodule init 126 | git submodule update 127 | ``` 128 | 129 | #### CMake and tests 130 | A CMake configuration file is also provided for multiplatform support and testing. 131 | 132 | Typical generic build for MS Visual Studio under Windows (from [build.bat](build.bat)): 133 | 134 | ```Batchfile 135 | mkdir build 136 | cd build 137 | 138 | cmake .. # cmake .. -G "Visual Studio 10" # for Visual Studio 2010 139 | @REM Generate a Visual Studio solution for latest version found 140 | cmake -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON .. 141 | 142 | @REM Build default configuration (ie 'Debug') 143 | cmake --build . 144 | 145 | @REM Build and run tests 146 | ctest --output-on-failure 147 | ``` 148 | 149 | Generating the Linux Makefile, building in Debug and executing the tests (from [build.sh](build.sh)): 150 | 151 | ```Shell 152 | mkdir Debug 153 | cd Debug 154 | 155 | # Generate a Makefile for GCC (or Clang, depanding on CC/CXX envvar) 156 | cmake -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON .. 157 | 158 | # Build (ie 'make') 159 | cmake --build . 160 | 161 | # Build and run unit-tests (ie 'make test') 162 | ctest --output-on-failure 163 | ``` 164 | 165 | #### CMake options 166 | 167 | * For more options on customizing the build, see the [CMakeLists.txt](https://github.com/SRombauts/SQLiteCpp/blob/master/CMakeLists.txt) file. 168 | 169 | #### Troubleshooting 170 | 171 | Under Linux, if you get muliple linker errors like "undefined reference to sqlite3_xxx", 172 | it's that you lack the "sqlite3" library: install the libsqlite3-dev package. 173 | 174 | If you get a single linker error "Column.cpp: undefined reference to sqlite3_column_origin_name", 175 | it's that your "sqlite3" library was not compiled with 176 | the SQLITE_ENABLE_COLUMN_METADATA macro defined (see http://www.sqlite.org/compile.html#enable_column_metadata). 177 | You can either recompile it yourself (seek help online) or you can comment out the following line in src/Column.h: 178 | 179 | ```C++ 180 | #define SQLITE_ENABLE_COLUMN_METADATA 181 | ``` 182 | 183 | ### Continuous Integration 184 | 185 | This project is continuously tested under Ubuntu Linux with the gcc and clang compilers 186 | using the Travis CI community service with the above CMake building and testing procedure. 187 | It is also tested in the same way under Windows Server 2012 R2 with Visual Studio 2013 compiler 188 | using the AppVeyor countinuous integration service. 189 | 190 | Detailed results can be seen online: 191 | - https://travis-ci.org/SRombauts/SQLiteCpp 192 | - https://ci.appveyor.com/project/SbastienRombauts/SQLiteCpp 193 | 194 | ### Thread-safety 195 | 196 | SQLite supports three modes of thread safety, as describe in "SQLite And Multiple Threads": 197 | see http://www.sqlite.org/threadsafe.html 198 | 199 | This SQLiteC++ wrapper does no add any locks (no mutexes) nor any other thread-safety mechanism 200 | above the SQLite library itself, by design, for lightness and speed. 201 | 202 | Thus, SQLiteC++ naturally supports the "Multi Thread" mode of SQLite: 203 | "In this mode, SQLite can be safely used by multiple threads 204 | provided that no single database connection is used simultaneously in two or more threads." 205 | 206 | But SQLiteC++ does not support the fully thread-safe "Serialized" mode of SQLite, 207 | because of the way it shares the underlying SQLite precompiled statement 208 | in a custom shared pointer (See the inner class "Statement::Ptr"). 209 | 210 | ## Examples 211 | ### The first sample demonstrates how to query a database and get results: 212 | 213 | ```C++ 214 | try 215 | { 216 | // Open a database file 217 | SQLite::Database db("example.db3"); 218 | 219 | // Compile a SQL query, containing one parameter (index 1) 220 | SQLite::Statement query(db, "SELECT * FROM test WHERE size > ?"); 221 | 222 | // Bind the integer value 6 to the first parameter of the SQL query 223 | query.bind(1, 6); 224 | 225 | // Loop to execute the query step by step, to get rows of result 226 | while (query.executeStep()) 227 | { 228 | // Demonstrate how to get some typed column value 229 | int id = query.getColumn(0); 230 | const char* value = query.getColumn(1); 231 | int size = query.getColumn(2); 232 | 233 | std::cout << "row: " << id << ", " << value << ", " << size << std::endl; 234 | } 235 | } 236 | catch (std::exception& e) 237 | { 238 | std::cout << "exception: " << e.what() << std::endl; 239 | } 240 | ``` 241 | 242 | ### The second sample shows how to manage a transaction: 243 | 244 | ```C++ 245 | try 246 | { 247 | SQLite::Database db("transaction.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE); 248 | 249 | db.exec("DROP TABLE IF EXISTS test"); 250 | 251 | // Begin transaction 252 | SQLite::Transaction transaction(db); 253 | 254 | db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"); 255 | 256 | int nb = db.exec("INSERT INTO test VALUES (NULL, \"test\")"); 257 | std::cout << "INSERT INTO test VALUES (NULL, \"test\")\", returned " << nb << std::endl; 258 | 259 | // Commit transaction 260 | transaction.commit(); 261 | } 262 | catch (std::exception& e) 263 | { 264 | std::cout << "exception: " << e.what() << std::endl; 265 | } 266 | ``` 267 | 268 | ### How to handle assertion in SQLiteC++: 269 | Exceptions shall not be used in destructors, so SQLiteC++ uses SQLITECPP_ASSERT() to check for errors in destructors. 270 | If you don't want assert() to be called, you have to enable and define an assert handler as shown below, 271 | and by setting the flag SQLITECPP_ENABLE_ASSERT_HANDLER when compiling the lib. 272 | 273 | ```C++ 274 | #ifdef SQLITECPP_ENABLE_ASSERT_HANDLER 275 | namespace SQLite 276 | { 277 | /// definition of the assertion handler enabled when SQLITECPP_ENABLE_ASSERT_HANDLER is defined in the project (CMakeList.txt) 278 | void assertion_failed(const char* apFile, const long apLine, const char* apFunc, const char* apExpr, const char* apMsg) 279 | { 280 | // Print a message to the standard error output stream, and abort the program. 281 | std::cerr << apFile << ":" << apLine << ":" << " error: assertion failed (" << apExpr << ") in " << apFunc << "() with message \"" << apMsg << "\"\n"; 282 | std::abort(); 283 | } 284 | } 285 | #endif 286 | ``` 287 | 288 | ## How to contribute 289 | ### GitHub website 290 | The most efficient way to help and contribute to this wrapper project is to 291 | use the tools provided by GitHub: 292 | - please fill bug reports and feature requests here: https://github.com/SRombauts/SQLiteCpp/issues 293 | - fork the repository, make some small changes and submit them with pull-request 294 | 295 | ### Contact 296 | You can also email me directly, I will try to answer questions and requests whenever I get the time for it. 297 | 298 | ### Coding Style Guidelines 299 | The source code use the CamelCase naming style variant where: 300 | - type names (class, struct, typedef, enums...) begin with a capital letter 301 | - files (.cpp/.h) are named like the class they contain 302 | - function and variable names begin with a lower case letter 303 | - member variables begin with a 'm', function arguments begin with a 'a', booleans with a 'b', pointers with a 'p' 304 | - each file, class, method and member variable is documented using Doxygen tags 305 | - braces on their own line 306 | See also http://www.appinf.com/download/CppCodingStyleGuide.pdf for good guidelines 307 | 308 | ## See also - Some other simple C++ SQLite wrappers: 309 | 310 | See bellow a short comparison of other wrappers done at the time of writing: 311 | - [sqdbcpp](http://code.google.com/p/sqdbcpp/): RAII design, simple, no dependencies, UTF-8/UTF-16, new BSD license 312 | - [sqlite3cc](http://ed.am/dev/sqlite3cc): uses boost, modern design, LPGPL 313 | - [sqlite3pp](https://github.com/iwongu/sqlite3pp): modern design inspired by boost, MIT License 314 | - [SQLite++](http://sqlitepp.berlios.de/): uses boost build system, Boost License 1.0 315 | - [CppSQLite](http://www.codeproject.com/Articles/6343/CppSQLite-C-Wrapper-for-SQLite/): famous Code Project but old design, BSD License 316 | - [easySQLite](http://code.google.com/p/easysqlite/): manages table as structured objects, complex 317 | - [sqlite_modern_cpp](https://github.com/keramer/sqlite_modern_cpp): modern C++11, all in one file, MIT license 318 | - [sqlite_orm](https://github.com/fnc12/sqlite_orm): modern C++14, header only all in one file, no raw string queries, BSD-3 license 319 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/src/Statement.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Statement.cpp 3 | * @ingroup SQLiteCpp 4 | * @brief A prepared SQLite Statement is a compiled SQL query ready to be executed, pointing to a row of result. 5 | * 6 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | namespace SQLite 21 | { 22 | 23 | // Compile and register the SQL query for the provided SQLite Database Connection 24 | Statement::Statement(Database &aDatabase, const char* apQuery) : 25 | mQuery(apQuery), 26 | mStmtPtr(aDatabase.mpSQLite, mQuery), // prepare the SQL query, and ref count (needs Database friendship) 27 | mColumnCount(0), 28 | mbHasRow(false), 29 | mbDone(false) 30 | { 31 | mColumnCount = sqlite3_column_count(mStmtPtr); 32 | } 33 | 34 | // Compile and register the SQL query for the provided SQLite Database Connection 35 | Statement::Statement(Database &aDatabase, const std::string& aQuery) : 36 | mQuery(aQuery), 37 | mStmtPtr(aDatabase.mpSQLite, mQuery), // prepare the SQL query, and ref count (needs Database friendship) 38 | mColumnCount(0), 39 | mbHasRow(false), 40 | mbDone(false) 41 | { 42 | mColumnCount = sqlite3_column_count(mStmtPtr); 43 | } 44 | 45 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) 46 | Statement::Statement(Statement&& aStatement) noexcept : 47 | mQuery(std::move(aStatement.mQuery)), 48 | mStmtPtr(std::move(aStatement.mStmtPtr)), 49 | mColumnCount(aStatement.mColumnCount), 50 | mbHasRow(aStatement.mbHasRow), 51 | mbDone(aStatement.mbDone) 52 | { 53 | aStatement.mColumnCount = 0; 54 | aStatement.mbHasRow = false; 55 | aStatement.mbDone = false; 56 | } 57 | #endif 58 | 59 | // Finalize and unregister the SQL query from the SQLite Database Connection. 60 | Statement::~Statement() 61 | { 62 | // the finalization will be done by the destructor of the last shared pointer 63 | } 64 | 65 | // Reset the statement to make it ready for a new execution (see also #clearBindings() bellow) 66 | void Statement::reset() 67 | { 68 | const int ret = tryReset(); 69 | check(ret); 70 | } 71 | 72 | int Statement::tryReset() noexcept 73 | { 74 | mbHasRow = false; 75 | mbDone = false; 76 | return sqlite3_reset(mStmtPtr); 77 | } 78 | 79 | // Clears away all the bindings of a prepared statement (can be associated with #reset() above). 80 | void Statement::clearBindings() 81 | { 82 | const int ret = sqlite3_clear_bindings(mStmtPtr); 83 | check(ret); 84 | } 85 | 86 | // Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 87 | void Statement::bind(const int aIndex, const int aValue) 88 | { 89 | const int ret = sqlite3_bind_int(mStmtPtr, aIndex, aValue); 90 | check(ret); 91 | } 92 | 93 | // Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 94 | void Statement::bind(const int aIndex, const unsigned aValue) 95 | { 96 | const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue); 97 | check(ret); 98 | } 99 | 100 | // Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 101 | void Statement::bind(const int aIndex, const long long aValue) 102 | { 103 | const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue); 104 | check(ret); 105 | } 106 | 107 | // Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 108 | void Statement::bind(const int aIndex, const double aValue) 109 | { 110 | const int ret = sqlite3_bind_double(mStmtPtr, aIndex, aValue); 111 | check(ret); 112 | } 113 | 114 | // Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 115 | void Statement::bind(const int aIndex, const std::string& aValue) 116 | { 117 | const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(), 118 | static_cast(aValue.size()), SQLITE_TRANSIENT); 119 | check(ret); 120 | } 121 | 122 | // Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 123 | void Statement::bind(const int aIndex, const char* apValue) 124 | { 125 | const int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_TRANSIENT); 126 | check(ret); 127 | } 128 | 129 | // Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 130 | void Statement::bind(const int aIndex, const void* apValue, const int aSize) 131 | { 132 | const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_TRANSIENT); 133 | check(ret); 134 | } 135 | 136 | // Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 137 | void Statement::bindNoCopy(const int aIndex, const std::string& aValue) 138 | { 139 | const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(), 140 | static_cast(aValue.size()), SQLITE_STATIC); 141 | check(ret); 142 | } 143 | 144 | // Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 145 | void Statement::bindNoCopy(const int aIndex, const char* apValue) 146 | { 147 | const int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_STATIC); 148 | check(ret); 149 | } 150 | 151 | // Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 152 | void Statement::bindNoCopy(const int aIndex, const void* apValue, const int aSize) 153 | { 154 | const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_STATIC); 155 | check(ret); 156 | } 157 | 158 | // Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 159 | void Statement::bind(const int aIndex) 160 | { 161 | const int ret = sqlite3_bind_null(mStmtPtr, aIndex); 162 | check(ret); 163 | } 164 | 165 | 166 | // Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 167 | void Statement::bind(const char* apName, const int aValue) 168 | { 169 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 170 | const int ret = sqlite3_bind_int(mStmtPtr, index, aValue); 171 | check(ret); 172 | } 173 | 174 | // Bind a 32bits unsigned int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 175 | void Statement::bind(const char* apName, const unsigned aValue) 176 | { 177 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 178 | const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue); 179 | check(ret); 180 | } 181 | 182 | // Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 183 | void Statement::bind(const char* apName, const long long aValue) 184 | { 185 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 186 | const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue); 187 | check(ret); 188 | } 189 | 190 | // Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 191 | void Statement::bind(const char* apName, const double aValue) 192 | { 193 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 194 | const int ret = sqlite3_bind_double(mStmtPtr, index, aValue); 195 | check(ret); 196 | } 197 | 198 | // Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 199 | void Statement::bind(const char* apName, const std::string& aValue) 200 | { 201 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 202 | const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(), 203 | static_cast(aValue.size()), SQLITE_TRANSIENT); 204 | check(ret); 205 | } 206 | 207 | // Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 208 | void Statement::bind(const char* apName, const char* apValue) 209 | { 210 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 211 | const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_TRANSIENT); 212 | check(ret); 213 | } 214 | 215 | // Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 216 | void Statement::bind(const char* apName, const void* apValue, const int aSize) 217 | { 218 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 219 | const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_TRANSIENT); 220 | check(ret); 221 | } 222 | 223 | // Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 224 | void Statement::bindNoCopy(const char* apName, const std::string& aValue) 225 | { 226 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 227 | const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(), 228 | static_cast(aValue.size()), SQLITE_STATIC); 229 | check(ret); 230 | } 231 | 232 | // Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 233 | void Statement::bindNoCopy(const char* apName, const char* apValue) 234 | { 235 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 236 | const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_STATIC); 237 | check(ret); 238 | } 239 | 240 | // Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 241 | void Statement::bindNoCopy(const char* apName, const void* apValue, const int aSize) 242 | { 243 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 244 | const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_STATIC); 245 | check(ret); 246 | } 247 | 248 | // Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement 249 | void Statement::bind(const char* apName) 250 | { 251 | const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); 252 | const int ret = sqlite3_bind_null(mStmtPtr, index); 253 | check(ret); 254 | } 255 | 256 | 257 | // Execute a step of the query to fetch one row of results 258 | bool Statement::executeStep() 259 | { 260 | const int ret = tryExecuteStep(); 261 | if ((SQLITE_ROW != ret) && (SQLITE_DONE != ret)) // on row or no (more) row ready, else it's a problem 262 | { 263 | if (ret == sqlite3_errcode(mStmtPtr)) 264 | { 265 | throw SQLite::Exception(mStmtPtr, ret); 266 | } 267 | else 268 | { 269 | throw SQLite::Exception("Statement needs to be reseted", ret); 270 | } 271 | } 272 | 273 | return mbHasRow; // true only if one row is accessible by getColumn(N) 274 | } 275 | 276 | // Execute a one-step query with no expected result 277 | int Statement::exec() 278 | { 279 | const int ret = tryExecuteStep(); 280 | if (SQLITE_DONE != ret) // the statement has finished executing successfully 281 | { 282 | if (SQLITE_ROW == ret) 283 | { 284 | throw SQLite::Exception("exec() does not expect results. Use executeStep."); 285 | } 286 | else if (ret == sqlite3_errcode(mStmtPtr)) 287 | { 288 | throw SQLite::Exception(mStmtPtr, ret); 289 | } 290 | else 291 | { 292 | throw SQLite::Exception("Statement needs to be reseted", ret); 293 | } 294 | } 295 | 296 | // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE) 297 | return sqlite3_changes(mStmtPtr); 298 | } 299 | 300 | int Statement::tryExecuteStep() noexcept 301 | { 302 | if (false == mbDone) 303 | { 304 | const int ret = sqlite3_step(mStmtPtr); 305 | if (SQLITE_ROW == ret) // one row is ready : call getColumn(N) to access it 306 | { 307 | mbHasRow = true; 308 | } 309 | else if (SQLITE_DONE == ret) // no (more) row ready : the query has finished executing 310 | { 311 | mbHasRow = false; 312 | mbDone = true; 313 | } 314 | else 315 | { 316 | mbHasRow = false; 317 | mbDone = false; 318 | } 319 | 320 | return ret; 321 | } 322 | else 323 | { 324 | // Statement needs to be reseted ! 325 | return SQLITE_MISUSE; 326 | } 327 | } 328 | 329 | 330 | // Return a copy of the column data specified by its index starting at 0 331 | // (use the Column copy-constructor) 332 | Column Statement::getColumn(const int aIndex) 333 | { 334 | checkRow(); 335 | checkIndex(aIndex); 336 | 337 | // Share the Statement Object handle with the new Column created 338 | return Column(mStmtPtr, aIndex); 339 | } 340 | 341 | // Return a copy of the column data specified by its column name starting at 0 342 | // (use the Column copy-constructor) 343 | Column Statement::getColumn(const char* apName) 344 | { 345 | checkRow(); 346 | const int index = getColumnIndex(apName); 347 | 348 | // Share the Statement Object handle with the new Column created 349 | return Column(mStmtPtr, index); 350 | } 351 | 352 | // Test if the column is NULL 353 | bool Statement::isColumnNull(const int aIndex) const 354 | { 355 | checkRow(); 356 | checkIndex(aIndex); 357 | return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex)); 358 | } 359 | 360 | bool Statement::isColumnNull(const char* apName) const 361 | { 362 | checkRow(); 363 | const int index = getColumnIndex(apName); 364 | return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, index)); 365 | } 366 | 367 | // Return the named assigned to the specified result column (potentially aliased) 368 | const char* Statement::getColumnName(const int aIndex) const 369 | { 370 | checkIndex(aIndex); 371 | return sqlite3_column_name(mStmtPtr, aIndex); 372 | } 373 | 374 | #ifdef SQLITE_ENABLE_COLUMN_METADATA 375 | // Return the named assigned to the specified result column (potentially aliased) 376 | const char* Statement::getColumnOriginName(const int aIndex) const 377 | { 378 | checkIndex(aIndex); 379 | return sqlite3_column_origin_name(mStmtPtr, aIndex); 380 | } 381 | #endif 382 | 383 | // Return the index of the specified (potentially aliased) column name 384 | int Statement::getColumnIndex(const char* apName) const 385 | { 386 | // Build the map of column index by name on first call 387 | if (mColumnNames.empty()) 388 | { 389 | for (int i = 0; i < mColumnCount; ++i) 390 | { 391 | const char* pName = sqlite3_column_name(mStmtPtr, i); 392 | mColumnNames[pName] = i; 393 | } 394 | } 395 | 396 | const TColumnNames::const_iterator iIndex = mColumnNames.find(apName); 397 | if (iIndex == mColumnNames.end()) 398 | { 399 | throw SQLite::Exception("Unknown column name."); 400 | } 401 | 402 | return (*iIndex).second; 403 | } 404 | 405 | int Statement::getBindParameterCount() const noexcept 406 | { 407 | return sqlite3_bind_parameter_count(mStmtPtr); 408 | } 409 | 410 | // Return the numeric result code for the most recent failed API call (if any). 411 | int Statement::getErrorCode() const noexcept // nothrow 412 | { 413 | return sqlite3_errcode(mStmtPtr); 414 | } 415 | 416 | // Return the extended numeric result code for the most recent failed API call (if any). 417 | int Statement::getExtendedErrorCode() const noexcept // nothrow 418 | { 419 | return sqlite3_extended_errcode(mStmtPtr); 420 | } 421 | 422 | // Return UTF-8 encoded English language explanation of the most recent failed API call (if any). 423 | const char* Statement::getErrorMsg() const noexcept // nothrow 424 | { 425 | return sqlite3_errmsg(mStmtPtr); 426 | } 427 | 428 | // Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded. 429 | std::string Statement::getExpandedSQL() { 430 | char* expanded = sqlite3_expanded_sql(mStmtPtr); 431 | std::string expandedString(expanded); 432 | sqlite3_free(expanded); 433 | return expandedString; 434 | } 435 | 436 | //////////////////////////////////////////////////////////////////////////////// 437 | // Internal class : shared pointer to the sqlite3_stmt SQLite Statement Object 438 | //////////////////////////////////////////////////////////////////////////////// 439 | 440 | /** 441 | * @brief Prepare the statement and initialize its reference counter 442 | * 443 | * @param[in] apSQLite The sqlite3 database connexion 444 | * @param[in] aQuery The SQL query string to prepare 445 | */ 446 | Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) : 447 | mpSQLite(apSQLite), 448 | mpStmt(NULL), 449 | mpRefCount(NULL) 450 | { 451 | const int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), static_cast(aQuery.size()), &mpStmt, NULL); 452 | if (SQLITE_OK != ret) 453 | { 454 | throw SQLite::Exception(apSQLite, ret); 455 | } 456 | // Initialize the reference counter of the sqlite3_stmt : 457 | // used to share the mStmtPtr between Statement and Column objects; 458 | // This is needed to enable Column objects to live longer than the Statement objet it refers to. 459 | mpRefCount = new unsigned int(1); // NOLINT(readability/casting) 460 | } 461 | 462 | /** 463 | * @brief Copy constructor increments the ref counter 464 | * 465 | * @param[in] aPtr Pointer to copy 466 | */ 467 | Statement::Ptr::Ptr(const Statement::Ptr& aPtr) : 468 | mpSQLite(aPtr.mpSQLite), 469 | mpStmt(aPtr.mpStmt), 470 | mpRefCount(aPtr.mpRefCount) 471 | { 472 | assert(NULL != mpRefCount); 473 | assert(0 != *mpRefCount); 474 | 475 | // Increment the reference counter of the sqlite3_stmt, 476 | // asking not to finalize the sqlite3_stmt during the lifetime of the new objet 477 | ++(*mpRefCount); 478 | } 479 | 480 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) 481 | Statement::Ptr::Ptr(Ptr&& aPtr) : 482 | mpSQLite(aPtr.mpSQLite), 483 | mpStmt(aPtr.mpStmt), 484 | mpRefCount(aPtr.mpRefCount) 485 | { 486 | aPtr.mpSQLite = NULL; 487 | aPtr.mpStmt = NULL; 488 | aPtr.mpRefCount = NULL; 489 | } 490 | #endif 491 | 492 | /** 493 | * @brief Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0 494 | */ 495 | Statement::Ptr::~Ptr() 496 | { 497 | if (NULL != mpRefCount) 498 | { 499 | assert(0 != *mpRefCount); 500 | 501 | // Decrement and check the reference counter of the sqlite3_stmt 502 | --(*mpRefCount); 503 | if (0 == *mpRefCount) 504 | { 505 | // If count reaches zero, finalize the sqlite3_stmt, as no Statement nor Column objet use it anymore. 506 | // No need to check the return code, as it is the same as the last statement evaluation. 507 | sqlite3_finalize(mpStmt); 508 | 509 | // and delete the reference counter 510 | delete mpRefCount; 511 | mpRefCount = NULL; 512 | mpStmt = NULL; 513 | } 514 | // else, the finalization will be done later, by the last object 515 | } 516 | } 517 | 518 | 519 | } // namespace SQLite 520 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/Database.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Database.h 3 | * @ingroup SQLiteCpp 4 | * @brief Management of a SQLite Database Connection. 5 | * 6 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #pragma once 12 | 13 | #include 14 | #include // definition of nullptr for C++98/C++03 compilers 15 | 16 | #include 17 | 18 | // Forward declarations to avoid inclusion of in a header 19 | struct sqlite3; 20 | struct sqlite3_context; 21 | 22 | #ifndef SQLITE_USE_LEGACY_STRUCT // Since SQLITE 3.19 (used by default since SQLiteCpp 2.1.0) 23 | typedef struct sqlite3_value sqlite3_value; 24 | #else // Before SQLite 3.19 (legacy struct forward declaration can be activated with CMake SQLITECPP_LEGACY_STRUCT var) 25 | struct Mem; 26 | typedef struct Mem sqlite3_value; 27 | #endif 28 | 29 | 30 | namespace SQLite 31 | { 32 | 33 | // Those public constants enable most usages of SQLiteCpp without including in the client application. 34 | 35 | /// The database is opened in read-only mode. If the database does not already exist, an error is returned. 36 | extern const int OPEN_READONLY; // SQLITE_OPEN_READONLY 37 | /// The database is opened for reading and writing if possible, or reading only if the file is write protected 38 | /// by the operating system. In either case the database must already exist, otherwise an error is returned. 39 | extern const int OPEN_READWRITE; // SQLITE_OPEN_READWRITE 40 | /// With OPEN_READWRITE: The database is opened for reading and writing, and is created if it does not already exist. 41 | extern const int OPEN_CREATE; // SQLITE_OPEN_CREATE 42 | 43 | /// Enable URI filename interpretation, parsed according to RFC 3986 (ex. "file:data.db?mode=ro&cache=private") 44 | extern const int OPEN_URI; // SQLITE_OPEN_URI 45 | 46 | extern const int OK; ///< SQLITE_OK (used by inline check() bellow) 47 | 48 | extern const char* VERSION; ///< SQLITE_VERSION string from the sqlite3.h used at compile time 49 | extern const int VERSION_NUMBER; ///< SQLITE_VERSION_NUMBER from the sqlite3.h used at compile time 50 | 51 | /// Return SQLite version string using runtime call to the compiled library 52 | const char* getLibVersion() noexcept; // nothrow 53 | /// Return SQLite version number using runtime call to the compiled library 54 | int getLibVersionNumber() noexcept; // nothrow 55 | 56 | 57 | /** 58 | * @brief RAII management of a SQLite Database Connection. 59 | * 60 | * A Database object manage a list of all SQLite Statements associated with the 61 | * underlying SQLite 3 database connection. 62 | * 63 | * Resource Acquisition Is Initialization (RAII) means that the Database Connection 64 | * is opened in the constructor and closed in the destructor, so that there is 65 | * no need to worry about memory management or the validity of the underlying SQLite Connection. 66 | * 67 | * Thread-safety: a Database object shall not be shared by multiple threads, because : 68 | * 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads 69 | * provided that no single database connection is used simultaneously in two or more threads." 70 | * 2) the SQLite "Serialized" mode is not supported by SQLiteC++, 71 | * because of the way it shares the underling SQLite precompiled statement 72 | * in a custom shared pointer (See the inner class "Statement::Ptr"). 73 | */ 74 | class Database 75 | { 76 | friend class Statement; // Give Statement constructor access to the mpSQLite Connection Handle 77 | 78 | public: 79 | /** 80 | * @brief Open the provided database UTF-8 filename. 81 | * 82 | * Uses sqlite3_open_v2() with readonly default flag, which is the opposite behavior 83 | * of the old sqlite3_open() function (READWRITE+CREATE). 84 | * This makes sense if you want to use it on a readonly filesystem 85 | * or to prevent creation of a void file when a required file is missing. 86 | * 87 | * Exception is thrown in case of error, then the Database object is NOT constructed. 88 | * 89 | * @param[in] apFilename UTF-8 path/uri to the database file ("filename" sqlite3 parameter) 90 | * @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE... 91 | * @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout()) 92 | * @param[in] apVfs UTF-8 name of custom VFS to use, or nullptr for sqlite3 default 93 | * 94 | * @throw SQLite::Exception in case of error 95 | */ 96 | Database(const char* apFilename, 97 | const int aFlags = SQLite::OPEN_READONLY, 98 | const int aBusyTimeoutMs = 0, 99 | const char* apVfs = nullptr); 100 | 101 | /** 102 | * @brief Open the provided database UTF-8 filename. 103 | * 104 | * Uses sqlite3_open_v2() with readonly default flag, which is the opposite behavior 105 | * of the old sqlite3_open() function (READWRITE+CREATE). 106 | * This makes sense if you want to use it on a readonly filesystem 107 | * or to prevent creation of a void file when a required file is missing. 108 | * 109 | * Exception is thrown in case of error, then the Database object is NOT constructed. 110 | * 111 | * @param[in] aFilename UTF-8 path/uri to the database file ("filename" sqlite3 parameter) 112 | * @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE... 113 | * @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout()) 114 | * @param[in] aVfs UTF-8 name of custom VFS to use, or empty string for sqlite3 default 115 | * 116 | * @throw SQLite::Exception in case of error 117 | */ 118 | Database(const std::string& aFilename, 119 | const int aFlags = SQLite::OPEN_READONLY, 120 | const int aBusyTimeoutMs = 0, 121 | const std::string& aVfs = ""); 122 | 123 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) 124 | /** 125 | * @brief Move an SQLite database connection. 126 | * 127 | * @param[in] aDatabase Database to move 128 | */ 129 | inline Database(Database&& aDatabase) noexcept : 130 | mpSQLite(aDatabase.mpSQLite), 131 | mFilename(std::move(aDatabase.mFilename)) 132 | { 133 | aDatabase.mpSQLite = nullptr; 134 | } 135 | #endif 136 | 137 | /** 138 | * @brief Close the SQLite database connection. 139 | * 140 | * All SQLite statements must have been finalized before, 141 | * so all Statement objects must have been unregistered. 142 | * 143 | * @warning assert in case of error 144 | */ 145 | ~Database(); 146 | 147 | /** 148 | * @brief Set a busy handler that sleeps for a specified amount of time when a table is locked. 149 | * 150 | * This is useful in multithreaded program to handle case where a table is locked for writing by a thread. 151 | * Any other thread cannot access the table and will receive a SQLITE_BUSY error: 152 | * setting a timeout will wait and retry up to the time specified before returning this SQLITE_BUSY error. 153 | * Reading the value of timeout for current connection can be done with SQL query "PRAGMA busy_timeout;". 154 | * Default busy timeout is 0ms. 155 | * 156 | * @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY 157 | * 158 | * @throw SQLite::Exception in case of error 159 | */ 160 | void setBusyTimeout(const int aBusyTimeoutMs); 161 | 162 | /** 163 | * @brief Shortcut to execute one or multiple statements without results. 164 | * 165 | * This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" : 166 | * - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE" 167 | * - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP" 168 | * - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK" 169 | * 170 | * @see Statement::exec() to handle precompiled statements (for better performances) without results 171 | * @see Statement::executeStep() to handle "SELECT" queries with results 172 | * 173 | * @param[in] apQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements 174 | * 175 | * @return number of rows modified by the *last* INSERT, UPDATE or DELETE statement (beware of multiple statements) 176 | * @warning undefined for CREATE or DROP table: returns the value of a previous INSERT, UPDATE or DELETE statement. 177 | * 178 | * @throw SQLite::Exception in case of error 179 | */ 180 | int exec(const char* apQueries); 181 | 182 | /** 183 | * @brief Shortcut to execute one or multiple statements without results. 184 | * 185 | * This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" : 186 | * - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE" 187 | * - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP" 188 | * - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK" 189 | * 190 | * @see Statement::exec() to handle precompiled statements (for better performances) without results 191 | * @see Statement::executeStep() to handle "SELECT" queries with results 192 | * 193 | * @param[in] aQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements 194 | * 195 | * @return number of rows modified by the *last* INSERT, UPDATE or DELETE statement (beware of multiple statements) 196 | * @warning undefined for CREATE or DROP table: returns the value of a previous INSERT, UPDATE or DELETE statement. 197 | * 198 | * @throw SQLite::Exception in case of error 199 | */ 200 | inline int exec(const std::string& aQueries) 201 | { 202 | return exec(aQueries.c_str()); 203 | } 204 | 205 | /** 206 | * @brief Shortcut to execute a one step query and fetch the first column of the result. 207 | * 208 | * This is a shortcut to execute a simple statement with a single result. 209 | * This should be used only for non reusable queries (else you should use a Statement with bind()). 210 | * This should be used only for queries with expected results (else an exception is fired). 211 | * 212 | * @warning WARNING: Be very careful with this dangerous method: you have to 213 | * make a COPY OF THE result, else it will be destroy before the next line 214 | * (when the underlying temporary Statement and Column objects are destroyed) 215 | * 216 | * @see also Statement class for handling queries with multiple results 217 | * 218 | * @param[in] apQuery an UTF-8 encoded SQL query 219 | * 220 | * @return a temporary Column object with the first column of result. 221 | * 222 | * @throw SQLite::Exception in case of error 223 | */ 224 | Column execAndGet(const char* apQuery); 225 | 226 | /** 227 | * @brief Shortcut to execute a one step query and fetch the first column of the result. 228 | * 229 | * This is a shortcut to execute a simple statement with a single result. 230 | * This should be used only for non reusable queries (else you should use a Statement with bind()). 231 | * This should be used only for queries with expected results (else an exception is fired). 232 | * 233 | * @warning WARNING: Be very careful with this dangerous method: you have to 234 | * make a COPY OF THE result, else it will be destroy before the next line 235 | * (when the underlying temporary Statement and Column objects are destroyed) 236 | * 237 | * @see also Statement class for handling queries with multiple results 238 | * 239 | * @param[in] aQuery an UTF-8 encoded SQL query 240 | * 241 | * @return a temporary Column object with the first column of result. 242 | * 243 | * @throw SQLite::Exception in case of error 244 | */ 245 | inline Column execAndGet(const std::string& aQuery) 246 | { 247 | return execAndGet(aQuery.c_str()); 248 | } 249 | 250 | /** 251 | * @brief Shortcut to test if a table exists. 252 | * 253 | * Table names are case sensitive. 254 | * 255 | * @param[in] apTableName an UTF-8 encoded case sensitive Table name 256 | * 257 | * @return true if the table exists. 258 | * 259 | * @throw SQLite::Exception in case of error 260 | */ 261 | bool tableExists(const char* apTableName); 262 | 263 | /** 264 | * @brief Shortcut to test if a table exists. 265 | * 266 | * Table names are case sensitive. 267 | * 268 | * @param[in] aTableName an UTF-8 encoded case sensitive Table name 269 | * 270 | * @return true if the table exists. 271 | * 272 | * @throw SQLite::Exception in case of error 273 | */ 274 | inline bool tableExists(const std::string& aTableName) 275 | { 276 | return tableExists(aTableName.c_str()); 277 | } 278 | 279 | /** 280 | * @brief Get the rowid of the most recent successful INSERT into the database from the current connection. 281 | * 282 | * Each entry in an SQLite table always has a unique 64-bit signed integer key called the rowid. 283 | * If the table has a column of type INTEGER PRIMARY KEY, then it is an alias for the rowid. 284 | * 285 | * @return Rowid of the most recent successful INSERT into the database, or 0 if there was none. 286 | */ 287 | long long getLastInsertRowid() const noexcept; // nothrow 288 | 289 | /// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection (not DROP table). 290 | int getTotalChanges() const noexcept; // nothrow 291 | 292 | /// Return the numeric result code for the most recent failed API call (if any). 293 | int getErrorCode() const noexcept; // nothrow 294 | /// Return the extended numeric result code for the most recent failed API call (if any). 295 | int getExtendedErrorCode() const noexcept; // nothrow 296 | /// Return UTF-8 encoded English language explanation of the most recent failed API call (if any). 297 | const char* getErrorMsg() const noexcept; // nothrow 298 | 299 | /// Return the filename used to open the database. 300 | const std::string& getFilename() const noexcept // nothrow 301 | { 302 | return mFilename; 303 | } 304 | 305 | /** 306 | * @brief Return raw pointer to SQLite Database Connection Handle. 307 | * 308 | * This is often needed to mix this wrapper with other libraries or for advance usage not supported by SQLiteCpp. 309 | */ 310 | inline sqlite3* getHandle() const noexcept // nothrow 311 | { 312 | return mpSQLite; 313 | } 314 | 315 | /** 316 | * @brief Create or redefine a SQL function or aggregate in the sqlite database. 317 | * 318 | * This is the equivalent of the sqlite3_create_function_v2 command. 319 | * @see http://www.sqlite.org/c3ref/create_function.html 320 | * 321 | * @note UTF-8 text encoding assumed. 322 | * 323 | * @param[in] apFuncName Name of the SQL function to be created or redefined 324 | * @param[in] aNbArg Number of arguments in the function 325 | * @param[in] abDeterministic Optimize for deterministic functions (most are). A random number generator is not. 326 | * @param[in] apApp Arbitrary pointer of user data, accessible with sqlite3_user_data(). 327 | * @param[in] apFunc Pointer to a C-function to implement a scalar SQL function (apStep & apFinal nullptr) 328 | * @param[in] apStep Pointer to a C-function to implement an aggregate SQL function (apFunc nullptr) 329 | * @param[in] apFinal Pointer to a C-function to implement an aggregate SQL function (apFunc nullptr) 330 | * @param[in] apDestroy If not nullptr, then it is the destructor for the application data pointer. 331 | * 332 | * @throw SQLite::Exception in case of error 333 | */ 334 | void createFunction(const char* apFuncName, 335 | int aNbArg, 336 | bool abDeterministic, 337 | void* apApp, 338 | void (*apFunc)(sqlite3_context *, int, sqlite3_value **), 339 | void (*apStep)(sqlite3_context *, int, sqlite3_value **), 340 | void (*apFinal)(sqlite3_context *), // NOLINT(readability/casting) 341 | void (*apDestroy)(void *)); 342 | 343 | /** 344 | * @brief Create or redefine a SQL function or aggregate in the sqlite database. 345 | * 346 | * This is the equivalent of the sqlite3_create_function_v2 command. 347 | * @see http://www.sqlite.org/c3ref/create_function.html 348 | * 349 | * @note UTF-8 text encoding assumed. 350 | * 351 | * @param[in] aFuncName Name of the SQL function to be created or redefined 352 | * @param[in] aNbArg Number of arguments in the function 353 | * @param[in] abDeterministic Optimize for deterministic functions (most are). A random number generator is not. 354 | * @param[in] apApp Arbitrary pointer of user data, accessible with sqlite3_user_data(). 355 | * @param[in] apFunc Pointer to a C-function to implement a scalar SQL function (apStep & apFinal nullptr) 356 | * @param[in] apStep Pointer to a C-function to implement an aggregate SQL function (apFunc nullptr) 357 | * @param[in] apFinal Pointer to a C-function to implement an aggregate SQL function (apFunc nullptr) 358 | * @param[in] apDestroy If not nullptr, then it is the destructor for the application data pointer. 359 | * 360 | * @throw SQLite::Exception in case of error 361 | */ 362 | inline void createFunction(const std::string& aFuncName, 363 | int aNbArg, 364 | bool abDeterministic, 365 | void* apApp, 366 | void (*apFunc)(sqlite3_context *, int, sqlite3_value **), 367 | void (*apStep)(sqlite3_context *, int, sqlite3_value **), 368 | void (*apFinal)(sqlite3_context *), // NOLINT(readability/casting) 369 | void (*apDestroy)(void *)) 370 | { 371 | return createFunction(aFuncName.c_str(), aNbArg, abDeterministic, 372 | apApp, apFunc, apStep, apFinal, apDestroy); 373 | } 374 | 375 | /** 376 | * @brief Load a module into the current sqlite database instance. 377 | * 378 | * This is the equivalent of the sqlite3_load_extension call, but additionally enables 379 | * module loading support prior to loading the requested module. 380 | * 381 | * @see http://www.sqlite.org/c3ref/load_extension.html 382 | * 383 | * @note UTF-8 text encoding assumed. 384 | * 385 | * @param[in] apExtensionName Name of the shared library containing extension 386 | * @param[in] apEntryPointName Name of the entry point (nullptr to let sqlite work it out) 387 | * 388 | * @throw SQLite::Exception in case of error 389 | */ 390 | void loadExtension(const char* apExtensionName, const char* apEntryPointName); 391 | 392 | /** 393 | * @brief Set the key for the current sqlite database instance. 394 | * 395 | * This is the equivalent of the sqlite3_key call and should thus be called 396 | * directly after opening the database. 397 | * Open encrypted database -> call db.key("secret") -> database ready 398 | * 399 | * @param[in] aKey Key to decode/encode the database 400 | * 401 | * @throw SQLite::Exception in case of error 402 | */ 403 | void key(const std::string& aKey) const; 404 | 405 | /** 406 | * @brief Reset the key for the current sqlite database instance. 407 | * 408 | * This is the equivalent of the sqlite3_rekey call and should thus be called 409 | * after the database has been opened with a valid key. To decrypt a 410 | * database, call this method with an empty string. 411 | * Open normal database -> call db.rekey("secret") -> encrypted database, database ready 412 | * Open encrypted database -> call db.key("secret") -> call db.rekey("newsecret") -> change key, database ready 413 | * Open encrypted database -> call db.key("secret") -> call db.rekey("") -> decrypted database, database ready 414 | * 415 | * @param[in] aNewKey New key to encode the database 416 | * 417 | * @throw SQLite::Exception in case of error 418 | */ 419 | void rekey(const std::string& aNewKey) const; 420 | 421 | /** 422 | * @brief Test if a file contains an unencrypted database. 423 | * 424 | * This is a simple test that reads the first bytes of a database file and 425 | * compares them to the standard header for unencrypted databases. If the 426 | * header does not match the standard string, we assume that we have an 427 | * encrypted file. 428 | * 429 | * @param[in] aFilename path/uri to a file 430 | * 431 | * @return true if the database has the standard header. 432 | * 433 | * @throw SQLite::Exception in case of error 434 | */ 435 | static bool isUnencrypted(const std::string& aFilename); 436 | 437 | /** 438 | * @brief BackupType for the backup() method 439 | */ 440 | enum BackupType { Save, Load }; 441 | 442 | /** 443 | * @brief Load or save the database content. 444 | * 445 | * This function is used to load the contents of a database file on disk 446 | * into the "main" database of open database connection, or to save the current 447 | * contents of the database into a database file on disk. 448 | * 449 | * @return SQLITE_OK on success or an error code from SQLite. 450 | */ 451 | int backup(const char* zFilename, BackupType type); 452 | 453 | private: 454 | /// @{ Database must be non-copyable 455 | Database(const Database&); 456 | Database& operator=(const Database&); 457 | /// @} 458 | 459 | /** 460 | * @brief Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message 461 | */ 462 | inline void check(const int aRet) const 463 | { 464 | if (SQLite::OK != aRet) 465 | { 466 | throw SQLite::Exception(mpSQLite, aRet); 467 | } 468 | } 469 | 470 | private: 471 | sqlite3* mpSQLite; ///< Pointer to SQLite Database Connection Handle 472 | std::string mFilename; ///< UTF-8 filename used to open the database 473 | }; 474 | 475 | 476 | } // namespace SQLite 477 | -------------------------------------------------------------------------------- /libs/SQLiteCpp/include/SQLiteCpp/Statement.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Statement.h 3 | * @ingroup SQLiteCpp 4 | * @brief A prepared SQLite Statement is a compiled SQL query ready to be executed, pointing to a row of result. 5 | * 6 | * Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include // For INT_MAX 18 | 19 | // Forward declarations to avoid inclusion of in a header 20 | struct sqlite3; 21 | struct sqlite3_stmt; 22 | 23 | 24 | namespace SQLite 25 | { 26 | 27 | 28 | // Forward declaration 29 | class Database; 30 | class Column; 31 | 32 | extern const int OK; ///< SQLITE_OK 33 | 34 | /** 35 | * @brief RAII encapsulation of a prepared SQLite Statement. 36 | * 37 | * A Statement is a compiled SQL query ready to be executed step by step 38 | * to provide results one row at a time. 39 | * 40 | * Resource Acquisition Is Initialization (RAII) means that the Statement 41 | * is compiled in the constructor and finalized in the destructor, so that there is 42 | * no need to worry about memory management or the validity of the underlying SQLite Statement. 43 | * 44 | * Thread-safety: a Statement object shall not be shared by multiple threads, because : 45 | * 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads 46 | * provided that no single database connection is used simultaneously in two or more threads." 47 | * 2) the SQLite "Serialized" mode is not supported by SQLiteC++, 48 | * because of the way it shares the underling SQLite precompiled statement 49 | * in a custom shared pointer (See the inner class "Statement::Ptr"). 50 | */ 51 | class Statement 52 | { 53 | friend class Column; // For access to Statement::Ptr inner class 54 | 55 | public: 56 | /** 57 | * @brief Compile and register the SQL query for the provided SQLite Database Connection 58 | * 59 | * @param[in] aDatabase the SQLite Database Connection 60 | * @param[in] apQuery an UTF-8 encoded query string 61 | * 62 | * Exception is thrown in case of error, then the Statement object is NOT constructed. 63 | */ 64 | Statement(Database& aDatabase, const char* apQuery); 65 | 66 | /** 67 | * @brief Compile and register the SQL query for the provided SQLite Database Connection 68 | * 69 | * @param[in] aDatabase the SQLite Database Connection 70 | * @param[in] aQuery an UTF-8 encoded query string 71 | * 72 | * Exception is thrown in case of error, then the Statement object is NOT constructed. 73 | */ 74 | Statement(Database& aDatabase, const std::string& aQuery); 75 | 76 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) 77 | /** 78 | * @brief Move an SQLite statement. 79 | * 80 | * @param[in] aStatement Statement to move 81 | */ 82 | Statement(Statement&& aStatement) noexcept; 83 | #endif 84 | 85 | /// Finalize and unregister the SQL query from the SQLite Database Connection. 86 | ~Statement(); 87 | 88 | /// Reset the statement to make it ready for a new execution. Throws an exception on error. 89 | void reset(); 90 | 91 | /// Reset the statement. Returns the sqlite result code instead of throwing an exception on error. 92 | int tryReset() noexcept; 93 | 94 | /** 95 | * @brief Clears away all the bindings of a prepared statement. 96 | * 97 | * Contrary to the intuition of many, reset() does not reset the bindings on a prepared statement. 98 | * Use this routine to reset all parameters to NULL. 99 | */ 100 | void clearBindings(); // throw(SQLite::Exception) 101 | 102 | //////////////////////////////////////////////////////////////////////////// 103 | // Bind a value to a parameter of the SQL statement, 104 | // in the form "?" (unnamed), "?NNN", ":VVV", "@VVV" or "$VVV". 105 | // 106 | // Can use the parameter index, starting from "1", to the higher NNN value, 107 | // or the complete parameter name "?NNN", ":VVV", "@VVV" or "$VVV" 108 | // (prefixed with the corresponding sign "?", ":", "@" or "$") 109 | // 110 | // Note that for text and blob values, the SQLITE_TRANSIENT flag is used, 111 | // which tell the sqlite library to make its own copy of the data before the bind() call returns. 112 | // This choice is done to prevent any common misuses, like passing a pointer to a 113 | // dynamic allocated and temporary variable (a std::string for instance). 114 | // This is under-optimized for static data (a static text define in code) 115 | // as well as for dynamic allocated buffer which could be transfer to sqlite 116 | // instead of being copied. 117 | // => if you know what you are doing, use bindNoCopy() instead of bind() 118 | 119 | /** 120 | * @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 121 | */ 122 | void bind(const int aIndex, const int aValue); 123 | /** 124 | * @brief Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 125 | */ 126 | void bind(const int aIndex, const unsigned aValue); 127 | 128 | #if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW) 129 | /** 130 | * @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 131 | */ 132 | void bind(const int aIndex, const long aValue) 133 | { 134 | bind(aIndex, static_cast(aValue)); 135 | } 136 | #else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS) 137 | /** 138 | * @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 139 | */ 140 | void bind(const int aIndex, const long aValue) 141 | { 142 | bind(aIndex, static_cast(aValue)); 143 | } 144 | #endif 145 | 146 | /** 147 | * @brief Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 148 | */ 149 | void bind(const int aIndex, const long long aValue); 150 | /** 151 | * @brief Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 152 | */ 153 | void bind(const int aIndex, const double aValue); 154 | /** 155 | * @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 156 | * 157 | * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use 158 | */ 159 | void bind(const int aIndex, const std::string& aValue); 160 | /** 161 | * @brief Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 162 | * 163 | * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use 164 | */ 165 | void bind(const int aIndex, const char* apValue); 166 | /** 167 | * @brief Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 168 | * 169 | * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use 170 | */ 171 | void bind(const int aIndex, const void* apValue, const int aSize); 172 | /** 173 | * @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1). 174 | * 175 | * The string can contain null characters as it is binded using its size. 176 | * 177 | * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. 178 | */ 179 | void bindNoCopy(const int aIndex, const std::string& aValue); 180 | /** 181 | * @brief Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 182 | * 183 | * Main usage is with null-terminated literal text (aka in code static strings) 184 | * 185 | * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. 186 | */ 187 | void bindNoCopy(const int aIndex, const char* apValue); 188 | /** 189 | * @brief Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 190 | * 191 | * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. 192 | */ 193 | void bindNoCopy(const int aIndex, const void* apValue, const int aSize); 194 | /** 195 | * @brief Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 196 | * 197 | * @see clearBindings() to set all bound parameters to NULL. 198 | */ 199 | void bind(const int aIndex); 200 | 201 | /** 202 | * @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 203 | */ 204 | void bind(const char* apName, const int aValue); 205 | /** 206 | * @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 207 | */ 208 | void bind(const char* apName, const unsigned aValue); 209 | 210 | #if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW) 211 | /** 212 | * @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 213 | */ 214 | void bind(const char* apName, const long aValue) 215 | { 216 | bind(apName, static_cast(aValue)); 217 | } 218 | #else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS) 219 | /** 220 | * @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 221 | */ 222 | void bind(const char* apName, const long aValue) 223 | { 224 | bind(apName, static_cast(aValue)); 225 | } 226 | #endif 227 | /** 228 | * @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 229 | */ 230 | void bind(const char* apName, const long long aValue); 231 | /** 232 | * @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 233 | */ 234 | void bind(const char* apName, const double aValue); 235 | /** 236 | * @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 237 | * 238 | * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use 239 | */ 240 | void bind(const char* apName, const std::string& aValue); 241 | /** 242 | * @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 243 | * 244 | * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use 245 | */ 246 | void bind(const char* apName, const char* apValue); 247 | /** 248 | * @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 249 | * 250 | * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use 251 | */ 252 | void bind(const char* apName, const void* apValue, const int aSize); 253 | /** 254 | * @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 255 | * 256 | * The string can contain null characters as it is binded using its size. 257 | * 258 | * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. 259 | */ 260 | void bindNoCopy(const char* apName, const std::string& aValue); 261 | /** 262 | * @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 263 | * 264 | * Main usage is with null-terminated literal text (aka in code static strings) 265 | * 266 | * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. 267 | */ 268 | void bindNoCopy(const char* apName, const char* apValue); 269 | /** 270 | * @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 271 | * 272 | * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. 273 | */ 274 | void bindNoCopy(const char* apName, const void* apValue, const int aSize); 275 | /** 276 | * @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 277 | * 278 | * @see clearBindings() to set all bound parameters to NULL. 279 | */ 280 | void bind(const char* apName); // bind NULL value 281 | 282 | 283 | /** 284 | * @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 285 | */ 286 | inline void bind(const std::string& aName, const int aValue) 287 | { 288 | bind(aName.c_str(), aValue); 289 | } 290 | /** 291 | * @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 292 | */ 293 | inline void bind(const std::string& aName, const unsigned aValue) 294 | { 295 | bind(aName.c_str(), aValue); 296 | } 297 | 298 | #if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW) 299 | /** 300 | * @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 301 | */ 302 | void bind(const std::string& aName, const long aValue) 303 | { 304 | bind(aName.c_str(), static_cast(aValue)); 305 | } 306 | #else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS) 307 | /** 308 | * @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 309 | */ 310 | void bind(const std::string& aName, const long aValue) 311 | { 312 | bind(aName.c_str(), static_cast(aValue)); 313 | } 314 | #endif 315 | /** 316 | * @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 317 | */ 318 | inline void bind(const std::string& aName, const long long aValue) 319 | { 320 | bind(aName.c_str(), aValue); 321 | } 322 | /** 323 | * @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 324 | */ 325 | inline void bind(const std::string& aName, const double aValue) 326 | { 327 | bind(aName.c_str(), aValue); 328 | } 329 | /** 330 | * @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 331 | * 332 | * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use 333 | */ 334 | inline void bind(const std::string& aName, const std::string& aValue) 335 | { 336 | bind(aName.c_str(), aValue); 337 | } 338 | /** 339 | * @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 340 | * 341 | * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use 342 | */ 343 | inline void bind(const std::string& aName, const char* apValue) 344 | { 345 | bind(aName.c_str(), apValue); 346 | } 347 | /** 348 | * @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 349 | * 350 | * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use 351 | */ 352 | inline void bind(const std::string& aName, const void* apValue, const int aSize) 353 | { 354 | bind(aName.c_str(), apValue, aSize); 355 | } 356 | /** 357 | * @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 358 | * 359 | * The string can contain null characters as it is binded using its size. 360 | * 361 | * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. 362 | */ 363 | inline void bindNoCopy(const std::string& aName, const std::string& aValue) 364 | { 365 | bindNoCopy(aName.c_str(), aValue); 366 | } 367 | /** 368 | * @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 369 | * 370 | * Main usage is with null-terminated literal text (aka in code static strings) 371 | * 372 | * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. 373 | */ 374 | inline void bindNoCopy(const std::string& aName, const char* apValue) 375 | { 376 | bindNoCopy(aName.c_str(), apValue); 377 | } 378 | /** 379 | * @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 380 | * 381 | * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement. 382 | */ 383 | inline void bindNoCopy(const std::string& aName, const void* apValue, const int aSize) 384 | { 385 | bindNoCopy(aName.c_str(), apValue, aSize); 386 | } 387 | /** 388 | * @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1) 389 | * 390 | * @see clearBindings() to set all bound parameters to NULL. 391 | */ 392 | inline void bind(const std::string& aName) // bind NULL value 393 | { 394 | bind(aName.c_str()); 395 | } 396 | 397 | //////////////////////////////////////////////////////////////////////////// 398 | 399 | /** 400 | * @brief Execute a step of the prepared query to fetch one row of results. 401 | * 402 | * While true is returned, a row of results is available, and can be accessed 403 | * thru the getColumn() method 404 | * 405 | * @see exec() execute a one-step prepared statement with no expected result 406 | * @see tryExecuteStep() try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code. 407 | * @see Database::exec() is a shortcut to execute one or multiple statements without results 408 | * 409 | * @return - true (SQLITE_ROW) if there is another row ready : you can call getColumn(N) to get it 410 | * then you have to call executeStep() again to fetch more rows until the query is finished 411 | * - false (SQLITE_DONE) if the query has finished executing : there is no (more) row of result 412 | * (case of a query with no result, or after N rows fetched successfully) 413 | * 414 | * @throw SQLite::Exception in case of error 415 | */ 416 | bool executeStep(); 417 | 418 | /** 419 | * @brief Try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code. 420 | * 421 | * 422 | * 423 | * @see exec() execute a one-step prepared statement with no expected result 424 | * @see executeStep() execute a step of the prepared query to fetch one row of results 425 | * @see Database::exec() is a shortcut to execute one or multiple statements without results 426 | * 427 | * @return the sqlite result code. 428 | */ 429 | int tryExecuteStep() noexcept; 430 | 431 | /** 432 | * @brief Execute a one-step query with no expected result. 433 | * 434 | * This method is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" : 435 | * - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP" 436 | * - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE" 437 | * - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK" 438 | * 439 | * It is similar to Database::exec(), but using a precompiled statement, it adds : 440 | * - the ability to bind() arguments to it (best way to insert data), 441 | * - reusing it allows for better performances (efficient for multiple insertion). 442 | * 443 | * @see executeStep() execute a step of the prepared query to fetch one row of results 444 | * @see tryExecuteStep() try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code. 445 | * @see Database::exec() is a shortcut to execute one or multiple statements without results 446 | * 447 | * @return number of row modified by this SQL statement (INSERT, UPDATE or DELETE) 448 | * 449 | * @throw SQLite::Exception in case of error, or if row of results are returned ! 450 | */ 451 | int exec(); 452 | 453 | //////////////////////////////////////////////////////////////////////////// 454 | 455 | /** 456 | * @brief Return a copy of the column data specified by its index 457 | * 458 | * Can be used to access the data of the current row of result when applicable, 459 | * while the executeStep() method returns true. 460 | * 461 | * Throw an exception if there is no row to return a Column from: 462 | * - if provided index is out of bound 463 | * - before any executeStep() call 464 | * - after the last executeStep() returned false 465 | * - after a reset() call 466 | * 467 | * Throw an exception if the specified index is out of the [0, getColumnCount()) range. 468 | * 469 | * @param[in] aIndex Index of the column, starting at 0 470 | * 471 | * @note This method is not const, reflecting the fact that the returned Column object will 472 | * share the ownership of the underlying sqlite3_stmt. 473 | * 474 | * @warning The resulting Column object must not be memorized "as-is". 475 | * Is is only a wrapper around the current result row, so it is only valid 476 | * while the row from the Statement remains valid, that is only until next executeStep() call. 477 | * Thus, you should instead extract immediately its data (getInt(), getText()...) 478 | * and use or copy this data for any later usage. 479 | */ 480 | Column getColumn(const int aIndex); 481 | 482 | /** 483 | * @brief Return a copy of the column data specified by its column name (less efficient than using an index) 484 | * 485 | * Can be used to access the data of the current row of result when applicable, 486 | * while the executeStep() method returns true. 487 | * 488 | * Throw an exception if there is no row to return a Column from : 489 | * - if provided name is not one of the aliased column names 490 | * - before any executeStep() call 491 | * - after the last executeStep() returned false 492 | * - after a reset() call 493 | * 494 | * Throw an exception if the specified name is not an on of the aliased name of the columns in the result. 495 | * 496 | * @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name) 497 | * 498 | * @note Uses a map of column names to indexes, build on first call. 499 | * 500 | * @note This method is not const, reflecting the fact that the returned Column object will 501 | * share the ownership of the underlying sqlite3_stmt. 502 | * 503 | * @warning The resulting Column object must not be memorized "as-is". 504 | * Is is only a wrapper around the current result row, so it is only valid 505 | * while the row from the Statement remains valid, that is only until next executeStep() call. 506 | * Thus, you should instead extract immediately its data (getInt(), getText()...) 507 | * and use or copy this data for any later usage. 508 | * 509 | * Throw an exception if the specified name is not one of the aliased name of the columns in the result. 510 | */ 511 | Column getColumn(const char* apName); 512 | 513 | #if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) 514 | /** 515 | * @brief Return an instance of T constructed from copies of the first N columns 516 | * 517 | * Can be used to access the data of the current row of result when applicable, 518 | * while the executeStep() method returns true. 519 | * 520 | * Throw an exception if there is no row to return a Column from: 521 | * - if provided column count is out of bound 522 | * - before any executeStep() call 523 | * - after the last executeStep() returned false 524 | * - after a reset() call 525 | * 526 | * Throw an exception if the specified column count is out of the [0, getColumnCount()) range. 527 | * 528 | * @tparam T Object type to construct 529 | * @tparam N Number of columns 530 | * 531 | * @note Requires std=C++14 532 | */ 533 | template 534 | T getColumns(); 535 | 536 | private: 537 | /** 538 | * @brief Helper function used by getColumns to expand an integer_sequence used to generate 539 | * the required Column objects 540 | */ 541 | template 542 | T getColumns(const std::integer_sequence); 543 | 544 | public: 545 | #endif 546 | 547 | /** 548 | * @brief Test if the column value is NULL 549 | * 550 | * @param[in] aIndex Index of the column, starting at 0 551 | * 552 | * @return true if the column value is NULL 553 | * 554 | * Throw an exception if the specified index is out of the [0, getColumnCount()) range. 555 | */ 556 | bool isColumnNull(const int aIndex) const; 557 | 558 | /** 559 | * @brief Test if the column value is NULL 560 | * 561 | * @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name) 562 | * 563 | * @return true if the column value is NULL 564 | * 565 | * Throw an exception if the specified name is not one of the aliased name of the columns in the result. 566 | */ 567 | bool isColumnNull(const char* apName) const; 568 | 569 | /** 570 | * @brief Return a pointer to the named assigned to the specified result column (potentially aliased) 571 | * 572 | * @param[in] aIndex Index of the column in the range [0, getColumnCount()). 573 | * 574 | * @see getColumnOriginName() to get original column name (not aliased) 575 | * 576 | * Throw an exception if the specified index is out of the [0, getColumnCount()) range. 577 | */ 578 | const char* getColumnName(const int aIndex) const; 579 | 580 | #ifdef SQLITE_ENABLE_COLUMN_METADATA 581 | /** 582 | * @brief Return a pointer to the table column name that is the origin of the specified result column 583 | * 584 | * Require definition of the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro : 585 | * - when building the SQLite library itself (which is the case for the Debian libsqlite3 binary for instance), 586 | * - and also when compiling this wrapper. 587 | * 588 | * Throw an exception if the specified index is out of the [0, getColumnCount()) range. 589 | */ 590 | const char* getColumnOriginName(const int aIndex) const; 591 | #endif 592 | 593 | /** 594 | * @brief Return the index of the specified (potentially aliased) column name 595 | * 596 | * @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name) 597 | * 598 | * @note Uses a map of column names to indexes, build on first call. 599 | * 600 | * Throw an exception if the specified name is not known. 601 | */ 602 | int getColumnIndex(const char* apName) const; 603 | 604 | //////////////////////////////////////////////////////////////////////////// 605 | 606 | /// Return the UTF-8 SQL Query. 607 | inline const std::string& getQuery() const 608 | { 609 | return mQuery; 610 | } 611 | 612 | // Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded. 613 | std::string getExpandedSQL(); 614 | 615 | /// Return the number of columns in the result set returned by the prepared statement 616 | inline int getColumnCount() const 617 | { 618 | return mColumnCount; 619 | } 620 | /// true when a row has been fetched with executeStep() 621 | inline bool hasRow() const 622 | { 623 | return mbHasRow; 624 | } 625 | /// @deprecated, use #hasRow() 626 | inline bool isOk() const 627 | { 628 | return hasRow(); 629 | } 630 | /// true when the last executeStep() had no more row to fetch 631 | inline bool isDone() const 632 | { 633 | return mbDone; 634 | } 635 | 636 | /// Return the number of bind parameters in the statement 637 | int getBindParameterCount() const noexcept; 638 | 639 | /// Return the numeric result code for the most recent failed API call (if any). 640 | int getErrorCode() const noexcept; // nothrow 641 | /// Return the extended numeric result code for the most recent failed API call (if any). 642 | int getExtendedErrorCode() const noexcept; // nothrow 643 | /// Return UTF-8 encoded English language explanation of the most recent failed API call (if any). 644 | const char* getErrorMsg() const noexcept; // nothrow 645 | 646 | private: 647 | /** 648 | * @brief Shared pointer to the sqlite3_stmt SQLite Statement Object. 649 | * 650 | * Manage the finalization of the sqlite3_stmt with a reference counter. 651 | * 652 | * This is a internal class, not part of the API (hence full documentation is in the cpp). 653 | */ 654 | class Ptr 655 | { 656 | public: 657 | // Prepare the statement and initialize its reference counter 658 | Ptr(sqlite3* apSQLite, std::string& aQuery); 659 | // Copy constructor increments the ref counter 660 | Ptr(const Ptr& aPtr); 661 | 662 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) 663 | // Move constructor 664 | Ptr(Ptr&& aPtr); 665 | #endif 666 | 667 | // Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0 668 | ~Ptr(); 669 | 670 | /// Inline cast operator returning the pointer to SQLite Database Connection Handle 671 | inline operator sqlite3*() const 672 | { 673 | return mpSQLite; 674 | } 675 | 676 | /// Inline cast operator returning the pointer to SQLite Statement Object 677 | inline operator sqlite3_stmt*() const 678 | { 679 | return mpStmt; 680 | } 681 | 682 | private: 683 | /// @{ Unused/forbidden copy/assignment operator 684 | Ptr& operator=(const Ptr& aPtr); 685 | /// @} 686 | 687 | private: 688 | sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle 689 | sqlite3_stmt* mpStmt; //!< Pointer to SQLite Statement Object 690 | unsigned int* mpRefCount; //!< Pointer to the heap allocated reference counter of the sqlite3_stmt 691 | //!< (to share it with Column objects) 692 | }; 693 | 694 | private: 695 | /// @{ Statement must be non-copyable 696 | Statement(const Statement&); 697 | Statement& operator=(const Statement&); 698 | /// @} 699 | 700 | /** 701 | * @brief Check if a return code equals SQLITE_OK, else throw a SQLite::Exception with the SQLite error message 702 | * 703 | * @param[in] aRet SQLite return code to test against the SQLITE_OK expected value 704 | */ 705 | inline void check(const int aRet) const 706 | { 707 | if (SQLite::OK != aRet) 708 | { 709 | throw SQLite::Exception(mStmtPtr, aRet); 710 | } 711 | } 712 | 713 | /** 714 | * @brief Check if there is a row of result returned by executeStep(), else throw a SQLite::Exception. 715 | */ 716 | inline void checkRow() const 717 | { 718 | if (false == mbHasRow) 719 | { 720 | throw SQLite::Exception("No row to get a column from. executeStep() was not called, or returned false."); 721 | } 722 | } 723 | 724 | /** 725 | * @brief Check if there is a Column index is in the range of columns in the result. 726 | */ 727 | inline void checkIndex(const int aIndex) const 728 | { 729 | if ((aIndex < 0) || (aIndex >= mColumnCount)) 730 | { 731 | throw SQLite::Exception("Column index out of range."); 732 | } 733 | } 734 | 735 | private: 736 | /// Map of columns index by name (mutable so getColumnIndex can be const) 737 | typedef std::map TColumnNames; 738 | 739 | private: 740 | std::string mQuery; //!< UTF-8 SQL Query 741 | Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object 742 | int mColumnCount; //!< Number of columns in the result of the prepared statement 743 | mutable TColumnNames mColumnNames; //!< Map of columns index by name (mutable so getColumnIndex can be const) 744 | bool mbHasRow; //!< true when a row has been fetched with executeStep() 745 | bool mbDone; //!< true when the last executeStep() had no more row to fetch 746 | }; 747 | 748 | 749 | } // namespace SQLite 750 | --------------------------------------------------------------------------------