Compare commits

..

No commits in common. "4294d4e68c92b1cd4bfea6c372993d7f1569527a" and "77919e4ce035ad9f46e46a5fb8093cdb59c0b298" have entirely different histories.

10 changed files with 678 additions and 582 deletions

View File

@ -1,32 +1,19 @@
cmake_minimum_required(VERSION 3.14)
project(park)
set(CMAKE_CXX_STANDARD 11)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp/include
)
add_executable(park main.cpp data.cpp headers/data.h Customer.cpp headers/Customer.h Park_spot.cpp headers/Park_spot.h Park_time.cpp headers/Park_time.h)
if (UNIX)
target_link_libraries(park
SQLiteCpp
sqlite3
pthread
dl
)
elseif (MSYS OR MINGW)
target_link_libraries(park
SQLiteCpp
sqlite3
pthread
ssp
)
endif()
cmake_minimum_required(VERSION 3.14)
project(park)
set(CMAKE_CXX_STANDARD 11)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp/include
)
add_executable(park main.cpp data.cpp headers/data.h Customer.cpp headers/Customer.h Park_spot.cpp headers/Park_spot.h Park_time.cpp headers/Park_time.h)
target_link_libraries(park
SQLiteCpp
sqlite3
pthread
dl
)

View File

@ -1,40 +1,39 @@
#include "headers/Park_spot.h"
#include "headers/data.h"
#include <iostream>
#include <thread> // to make pausing work, not sure if i need chrono, or this, or both
#include <vector>
/*
Code strucure like this:
class declarations zijn in /headers/class_naam.h, en definitions van de member
functs in /class_naam.cpp elke klas in zn eigen file omdat ik incomplete class
declarations wilt tegengaan, omdat ik ze niet goed begrijp. En header/source
split om multiple definition errors tegen te gaan.
Park_spot representeert een parkeermeter bij elke parkeer spot.
Een customer is een customer.
Park time is een object die reffereert naar parkspot en customer, basically een
record die zegt dat een customer voor x tijd geparkeert heeft bij spot x, enz.
De client clockt in en uit bij een spot.
*/
void Wait(int sec)
/*
a wait function where 1 sec represents 1 hour irl.
*/
{
std::this_thread::sleep_for(seconds{sec});
}
using std::cout;
int main() {
SQLite::Database db = data::start_db();
// see implementation of update_db, save_db and delete_db of customer to see how queries and statements work
Customer sagar{"Sagar Winston Ramsaransing", Verhicle_type::medium, db};
sagar.update_db(db);
cout << "THIS WRKS";
// sagar.delete_db(db);
}
#include "headers/Park_spot.h"
#include "headers/data.h"
#include <iostream>
#include <thread> // to make pausing work, not sure if i need chrono, or this, or both
#include <vector>
/*
Code strucure like this:
class declarations zijn in /headers/class_naam.h, en definitions van de member
functs in /class_naam.cpp elke klas in zn eigen file omdat ik incomplete class
declarations wilt tegengaan, omdat ik ze niet goed begrijp. En header/source
split om multiple definition errors tegen te gaan.
Park_spot representeert een parkeermeter bij elke parkeer spot.
Een customer is een customer.
Park time is een object die reffereert naar parkspot en customer, basically een
record die zegt dat een customer voor x tijd geparkeert heeft bij spot x, enz.
De client clockt in en uit bij een spot.
*/
void Wait(int sec)
/*
a wait function where 1 sec represents 1 hour irl.
*/
{
std::this_thread::sleep_for(seconds{sec});
}
using std::cout;
int main() {
SQLite::Database db = data::start_db();
// see implementation of update_db, save_db and delete_db of customer to see how queries and statements work
Customer sagar{"Ramsaransing", Verhicle_type::medium, db};
sagar.update_db(db);
sagar.delete_db(db);
}

BIN
test.db3

Binary file not shown.

View File

@ -1,338 +1,338 @@
# Main CMake file for compiling the library itself, examples and tests.
#
# Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
#
# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
# or copy at http://opensource.org/licenses/MIT)
cmake_minimum_required(VERSION 2.8.12) # first version with add_compile_options()
project(SQLiteCpp)
message (STATUS "CMake version: ${CMAKE_VERSION}")
# Define useful variables to handle OS differences:
if (WIN32)
set(DEV_NULL "NUL")
else (WIN32) # UNIX
set(DEV_NULL "/dev/null")
endif (WIN32)
# then Compiler/IDE differences:
if (MSVC)
set(CPPLINT_ARG_OUTPUT "--output=vs7")
set(CPPCHECK_ARG_TEMPLATE "--template=vs")
# disable Visual Studio warnings for fopen() used in the example
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
# Flags for linking with multithread static C++ runtime, required by googletest
if (SQLITECPP_BUILD_TESTS)
message(STATUS "Linking against multithread static C++ runtime for unit tests with googletest")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
endif (SQLITECPP_BUILD_TESTS)
# Handle the (partly supported) MSVC versions prior to 2015
if (MSVC_VERSION LESS 1900) # OR MSVC_TOOLSET_VERSION LESS 140)
message(WARNING "MSVC < 2015 detected: Visual Studio prior to 2015 is not fully supported. BLOB storage seems to be corrupted.")
endif (MSVC_VERSION LESS 1900)
else (MSVC)
set(CPPLINT_ARG_OUTPUT "--output=eclipse")
set(CPPCHECK_ARG_TEMPLATE "--template=gcc")
# Useful compile flags and extra warnings
add_compile_options(-fstack-protector -Wall -Wextra -Wpedantic -Wno-long-long -Wswitch-enum -Wshadow -Winline)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++0x-compat") # C++ only
if (CMAKE_COMPILER_IS_GNUCXX)
# GCC flags
option(SQLITECPP_USE_GCOV "USE GCov instrumentation." OFF)
if (SQLITECPP_USE_GCOV)
message (STATUS "Using GCov instrumentation")
add_compile_options (-coverage) # NOTE -fkeep-inline-functions would be usefull but not working with current google test and gcc 4.8
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage")
endif ()
endif (CMAKE_COMPILER_IS_GNUCXX)
endif (MSVC)
# and then common variables
set(CPPLINT_ARG_VERBOSE "--verbose=3")
set(CPPLINT_ARG_LINELENGTH "--linelength=120")
# Print CXX compiler information
message (STATUS "CMAKE_CXX_COMPILER '${CMAKE_CXX_COMPILER}' '${CMAKE_CXX_COMPILER_ID}' '${CMAKE_CXX_COMPILER_VERSION}'")
# Print CXX FLAGS
message (STATUS "CMAKE_CXX_FLAGS '${CMAKE_CXX_FLAGS}'")
if (MSVC)
message (STATUS "CMAKE_CXX_FLAGS_DEBUG '${CMAKE_CXX_FLAGS_DEBUG}'")
message (STATUS "CMAKE_CXX_FLAGS_RELEASE '${CMAKE_CXX_FLAGS_RELEASE}'")
message (STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO '${CMAKE_CXX_FLAGS_RELWITHDEBINFO}'")
message (STATUS "CMAKE_CXX_FLAGS_MINSIZEREL '${CMAKE_CXX_FLAGS_MINSIZEREL}'")
else (NOT MSVC)
if (CMAKE_BUILD_TYPE STREQUAL Debug)
message (STATUS "CMAKE_CXX_FLAGS_DEBUG '${CMAKE_CXX_FLAGS_DEBUG}'")
elseif (CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
message (STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO '${CMAKE_CXX_FLAGS_RELWITHDEBINFO}'")
elseif (CMAKE_BUILD_TYPE STREQUAL MinSizeRel)
message (STATUS "CMAKE_CXX_FLAGS_MINSIZEREL '${CMAKE_CXX_FLAGS_MINSIZEREL}'")
else ()
message (STATUS "CMAKE_CXX_FLAGS_RELEASE '${CMAKE_CXX_FLAGS_RELEASE}'")
endif ()
endif ()
# Options relative to SQLite and SQLiteC++ functions
option(SQLITE_ENABLE_COLUMN_METADATA "Enable Column::getColumnOriginName(). Require support from sqlite3 library." ON)
if (SQLITE_ENABLE_COLUMN_METADATA)
# Enable the use of SQLite column metadata and Column::getColumnOriginName() method,
# Require that the sqlite3 library is also compiled with this flag (default under Debian/Ubuntu, but not on Mac OS X).
add_definitions(-DSQLITE_ENABLE_COLUMN_METADATA)
endif (SQLITE_ENABLE_COLUMN_METADATA)
option(SQLITE_ENABLE_ASSERT_HANDLER "Enable the user defintion of a assertion_failed() handler." OFF)
if (SQLITE_ENABLE_ASSERT_HANDLER)
# Enable the user defintion of a assertion_failed() handler (default to false, easier to handler for begginers).
add_definitions(-DSQLITECPP_ENABLE_ASSERT_HANDLER)
endif (SQLITE_ENABLE_ASSERT_HANDLER)
option(SQLITE_USE_LEGACY_STRUCT "Fallback to forward declaration of legacy struct sqlite3_value (pre SQLite 3.19)" OFF)
if (SQLITE_USE_LEGACY_STRUCT)
# Force forward declaration of legacy struct sqlite3_value (pre SQLite 3.19)
add_definitions(-DSQLITE_USE_LEGACY_STRUCT)
endif (SQLITE_USE_LEGACY_STRUCT)
## Build the C++ Wrapper ##
# adding a new file require explicittly modifing the CMakeLists.txt
# so that CMake knows that it should rebuild the project (it is best practice)
# list of sources files of the library
set(SQLITECPP_SRC
${PROJECT_SOURCE_DIR}/src/Backup.cpp
${PROJECT_SOURCE_DIR}/src/Column.cpp
${PROJECT_SOURCE_DIR}/src/Database.cpp
${PROJECT_SOURCE_DIR}/src/Exception.cpp
${PROJECT_SOURCE_DIR}/src/Statement.cpp
${PROJECT_SOURCE_DIR}/src/Transaction.cpp
)
source_group(src FILES ${SQLITECPP_SRC})
# list of header files of the library
set(SQLITECPP_INC
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/SQLiteCpp.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Assertion.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Backup.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Column.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Database.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Exception.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Statement.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Transaction.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Utils.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/VariadicBind.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/ExecuteMany.h
)
source_group(include FILES ${SQLITECPP_INC})
# list of test files of the library
set(SQLITECPP_TESTS
tests/Column_test.cpp
tests/Database_test.cpp
tests/Statement_test.cpp
tests/Backup_test.cpp
tests/Transaction_test.cpp
tests/VariadicBind_test.cpp
tests/Exception_test.cpp
tests/ExecuteMany_test.cpp
)
source_group(tests FILES ${SQLITECPP_TESTS})
# list of example files of the library
set(SQLITECPP_EXAMPLES
examples/example1/main.cpp
)
source_group(example1 FILES ${SQLITECPP_EXAMPLES})
# list of doc files of the library
set(SQLITECPP_DOC
README.md
LICENSE.txt
CHANGELOG.md
TODO.txt
)
source_group(doc FILES ${SQLITECPP_DOC})
# list of script files of the library
set(SQLITECPP_SCRIPT
.travis.yml
appveyor.yml
build.bat
build.sh
cpplint.py
Doxyfile
FindSQLiteCpp.cmake
)
source_group(scripts FILES ${SQLITECPP_SCRIPT})
# All includes are relative to the "include" directory
include_directories("${PROJECT_SOURCE_DIR}/include")
# add sources of the wrapper as a "SQLiteCpp" static library
add_library(SQLiteCpp ${SQLITECPP_SRC} ${SQLITECPP_INC} ${SQLITECPP_DOC} ${SQLITECPP_SCRIPT})
# make the sqlite3 library part of the interface of the SQLiteCpp wrapper itself (the client app does not need to link to sqlite3)
# PR https://github.com/SRombauts/SQLiteCpp/pull/111 "linked SQLiteCpp to sqlite3" commented out since it breaks install step from PR #118
#target_link_libraries(SQLiteCpp PUBLIC sqlite3)
if (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-fPIC")
endif (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
# Allow the library to be installed via "make install" and found with "find_package"
install(TARGETS SQLiteCpp
EXPORT ${PROJECT_NAME}Config
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
COMPONENT libraries)
target_include_directories(SQLiteCpp PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/>)
install(DIRECTORY include/ DESTINATION include COMPONENT headers FILES_MATCHING REGEX ".*\\.(hpp|h)$")
install(EXPORT ${PROJECT_NAME}Config DESTINATION lib/cmake/${PROJECT_NAME})
## Build provided copy of SQLite3 C library ##
# TODO
#find_package(sqlite3)
#if(sqlite3_VERSION VERSION_LESS "3.19")
# set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-DSQLITECPP_HAS_MEM_STRUCT")
#endif()
option(SQLITECPP_USE_ASAN "Use Address Sanitizer." OFF)
if (SQLITECPP_USE_ASAN)
if ((CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 6) OR ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang"))
message (STATUS "Using Address Sanitizer")
set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
endif ()
endif ()
endif (SQLITECPP_USE_ASAN)
option(SQLITECPP_INTERNAL_SQLITE "Add the internal SQLite3 source to the project." ON)
if (SQLITECPP_INTERNAL_SQLITE)
# build the SQLite3 C library (for ease of use/compatibility) versus Linux sqlite3-dev package
add_subdirectory(sqlite3)
target_include_directories(sqlite3 PUBLIC "${PROJECT_SOURCE_DIR}/sqlite3")
target_include_directories(SQLiteCpp PRIVATE "${PROJECT_SOURCE_DIR}/sqlite3")
endif (SQLITECPP_INTERNAL_SQLITE)
# Optional additional targets:
option(SQLITECPP_RUN_CPPLINT "Run cpplint.py tool for Google C++ StyleGuide." ON)
if (SQLITECPP_RUN_CPPLINT)
find_package(PythonInterp)
if (PYTHONINTERP_FOUND)
# add a cpplint target to the "all" target
add_custom_target(SQLiteCpp_cpplint
ALL
COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/cpplint.py ${CPPLINT_ARG_OUTPUT} ${CPPLINT_ARG_VERBOSE} ${CPPLINT_ARG_LINELENGTH} ${SQLITECPP_SRC} ${SQLITECPP_INC}
)
endif (PYTHONINTERP_FOUND)
else (SQLITECPP_RUN_CPPLINT)
message(STATUS "SQLITECPP_RUN_CPPLINT OFF")
endif (SQLITECPP_RUN_CPPLINT)
option(SQLITECPP_RUN_CPPCHECK "Run cppcheck C++ static analysis tool." ON)
if (SQLITECPP_RUN_CPPCHECK)
find_program(CPPCHECK_EXECUTABLE NAMES cppcheck)
if (CPPCHECK_EXECUTABLE)
# add a cppcheck target to the "all" target
add_custom_target(SQLiteCpp_cppcheck
ALL
COMMAND ${CPPCHECK_EXECUTABLE} -j 8 cppcheck --enable=style --quiet ${CPPCHECK_ARG_TEMPLATE} ${PROJECT_SOURCE_DIR}/src
)
execute_process(COMMAND "${CPPCHECK_EXECUTABLE}" --version OUTPUT_VARIABLE CPPCHECK_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "Found Cppcheck: ${CPPCHECK_EXECUTABLE} ${CPPCHECK_VERSION}")
else (CPPCHECK_EXECUTABLE)
message(STATUS "Could NOT find cppcheck")
endif (CPPCHECK_EXECUTABLE)
else (SQLITECPP_RUN_CPPCHECK)
message(STATUS "SQLITECPP_RUN_CPPCHECK OFF")
endif (SQLITECPP_RUN_CPPCHECK)
option(SQLITECPP_RUN_DOXYGEN "Run Doxygen C++ documentation tool." OFF)
if (SQLITECPP_RUN_DOXYGEN)
find_package(Doxygen)
if (DOXYGEN_FOUND)
# add a Doxygen target to the "all" target
add_custom_target(SQLiteCpp_doxygen
ALL
COMMAND doxygen Doxyfile > ${DEV_NULL}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
endif (DOXYGEN_FOUND)
else (SQLITECPP_RUN_DOXYGEN)
message(STATUS "SQLITECPP_RUN_DOXYGEN OFF")
endif (SQLITECPP_RUN_DOXYGEN)
option(SQLITECPP_BUILD_EXAMPLES "Build examples." OFF)
if (SQLITECPP_BUILD_EXAMPLES)
# add the basic example executable
add_executable(SQLiteCpp_example1 ${SQLITECPP_EXAMPLES})
target_link_libraries(SQLiteCpp_example1 SQLiteCpp sqlite3)
# Link target with pthread and dl for linux
if (UNIX)
target_link_libraries(SQLiteCpp_example1 pthread)
if (NOT APPLE)
target_link_libraries(SQLiteCpp_example1 dl)
endif ()
elseif (MSYS OR MINGW)
target_link_libraries(SQLiteCpp_example1 ssp)
endif ()
else (SQLITECPP_BUILD_EXAMPLES)
message(STATUS "SQLITECPP_BUILD_EXAMPLES OFF")
endif (SQLITECPP_BUILD_EXAMPLES)
option(SQLITECPP_BUILD_TESTS "Build and run tests." OFF)
if (SQLITECPP_BUILD_TESTS)
# deactivate some warnings for compiling the gtest library
if (NOT MSVC)
add_compile_options(-Wno-variadic-macros -Wno-long-long -Wno-switch-enum -Wno-float-equal -Wno-conversion-null -Wno-switch-default -Wno-pedantic)
endif (NOT MSVC)
# add the subdirectory containing the CMakeLists.txt for the gtest library
# TODO: under Linux, uses libgtest-dev if found
if (NOT EXISTS "${PROJECT_SOURCE_DIR}/googletest/CMakeLists.txt")
message(FATAL_ERROR "Missing 'googletest' submodule! Either use 'git submodule init' and 'git submodule update' to get googletest according to the README, or deactivate unit tests with -DSQLITECPP_BUILD_TESTS=OFF")
endif ()
add_subdirectory(googletest)
include_directories("${PROJECT_SOURCE_DIR}/googletest/googletest/include")
# Add definitions to keep googletest from making the compilation fail
if (MSVC)
if (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS_EQUAL 1919) # OR MSVC_TOOLSET_VERSION EQUAL 141)
target_compile_definitions(gtest PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gtest_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gmock PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gmock_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
endif (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS_EQUAL 1919)
endif (MSVC)
# add the unit test executable
add_executable(SQLiteCpp_tests ${SQLITECPP_TESTS})
target_link_libraries(SQLiteCpp_tests gtest_main SQLiteCpp sqlite3)
# Link target with dl for linux
if (UNIX AND NOT APPLE)
target_link_libraries(SQLiteCpp_tests dl)
endif ()
# add a "test" target:
enable_testing()
# does the tests pass?
add_test(UnitTests SQLiteCpp_tests)
if (SQLITECPP_BUILD_EXAMPLES)
# does the example1 runs successfully?
add_test(Example1Run SQLiteCpp_example1)
endif (SQLITECPP_BUILD_EXAMPLES)
else (SQLITECPP_BUILD_TESTS)
message(STATUS "SQLITECPP_BUILD_TESTS OFF")
endif (SQLITECPP_BUILD_TESTS)
# Main CMake file for compiling the library itself, examples and tests.
#
# Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
#
# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
# or copy at http://opensource.org/licenses/MIT)
cmake_minimum_required(VERSION 2.8.12) # first version with add_compile_options()
project(SQLiteCpp)
message (STATUS "CMake version: ${CMAKE_VERSION}")
# Define useful variables to handle OS differences:
if (WIN32)
set(DEV_NULL "NUL")
else (WIN32) # UNIX
set(DEV_NULL "/dev/null")
endif (WIN32)
# then Compiler/IDE differences:
if (MSVC)
set(CPPLINT_ARG_OUTPUT "--output=vs7")
set(CPPCHECK_ARG_TEMPLATE "--template=vs")
# disable Visual Studio warnings for fopen() used in the example
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
# Flags for linking with multithread static C++ runtime, required by googletest
if (SQLITECPP_BUILD_TESTS)
message(STATUS "Linking against multithread static C++ runtime for unit tests with googletest")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
endif (SQLITECPP_BUILD_TESTS)
# Handle the (partly supported) MSVC versions prior to 2015
if (MSVC_VERSION LESS 1900) # OR MSVC_TOOLSET_VERSION LESS 140)
message(WARNING "MSVC < 2015 detected: Visual Studio prior to 2015 is not fully supported. BLOB storage seems to be corrupted.")
endif (MSVC_VERSION LESS 1900)
else (MSVC)
set(CPPLINT_ARG_OUTPUT "--output=eclipse")
set(CPPCHECK_ARG_TEMPLATE "--template=gcc")
# Useful compile flags and extra warnings
add_compile_options(-fstack-protector -Wall -Wextra -Wpedantic -Wno-long-long -Wswitch-enum -Wshadow -Winline)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++0x-compat") # C++ only
if (CMAKE_COMPILER_IS_GNUCXX)
# GCC flags
option(SQLITECPP_USE_GCOV "USE GCov instrumentation." OFF)
if (SQLITECPP_USE_GCOV)
message (STATUS "Using GCov instrumentation")
add_compile_options (-coverage) # NOTE -fkeep-inline-functions would be usefull but not working with current google test and gcc 4.8
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage")
endif ()
endif (CMAKE_COMPILER_IS_GNUCXX)
endif (MSVC)
# and then common variables
set(CPPLINT_ARG_VERBOSE "--verbose=3")
set(CPPLINT_ARG_LINELENGTH "--linelength=120")
# Print CXX compiler information
message (STATUS "CMAKE_CXX_COMPILER '${CMAKE_CXX_COMPILER}' '${CMAKE_CXX_COMPILER_ID}' '${CMAKE_CXX_COMPILER_VERSION}'")
# Print CXX FLAGS
message (STATUS "CMAKE_CXX_FLAGS '${CMAKE_CXX_FLAGS}'")
if (MSVC)
message (STATUS "CMAKE_CXX_FLAGS_DEBUG '${CMAKE_CXX_FLAGS_DEBUG}'")
message (STATUS "CMAKE_CXX_FLAGS_RELEASE '${CMAKE_CXX_FLAGS_RELEASE}'")
message (STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO '${CMAKE_CXX_FLAGS_RELWITHDEBINFO}'")
message (STATUS "CMAKE_CXX_FLAGS_MINSIZEREL '${CMAKE_CXX_FLAGS_MINSIZEREL}'")
else (NOT MSVC)
if (CMAKE_BUILD_TYPE STREQUAL Debug)
message (STATUS "CMAKE_CXX_FLAGS_DEBUG '${CMAKE_CXX_FLAGS_DEBUG}'")
elseif (CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
message (STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO '${CMAKE_CXX_FLAGS_RELWITHDEBINFO}'")
elseif (CMAKE_BUILD_TYPE STREQUAL MinSizeRel)
message (STATUS "CMAKE_CXX_FLAGS_MINSIZEREL '${CMAKE_CXX_FLAGS_MINSIZEREL}'")
else ()
message (STATUS "CMAKE_CXX_FLAGS_RELEASE '${CMAKE_CXX_FLAGS_RELEASE}'")
endif ()
endif ()
# Options relative to SQLite and SQLiteC++ functions
option(SQLITE_ENABLE_COLUMN_METADATA "Enable Column::getColumnOriginName(). Require support from sqlite3 library." ON)
if (SQLITE_ENABLE_COLUMN_METADATA)
# Enable the use of SQLite column metadata and Column::getColumnOriginName() method,
# Require that the sqlite3 library is also compiled with this flag (default under Debian/Ubuntu, but not on Mac OS X).
add_definitions(-DSQLITE_ENABLE_COLUMN_METADATA)
endif (SQLITE_ENABLE_COLUMN_METADATA)
option(SQLITE_ENABLE_ASSERT_HANDLER "Enable the user defintion of a assertion_failed() handler." OFF)
if (SQLITE_ENABLE_ASSERT_HANDLER)
# Enable the user defintion of a assertion_failed() handler (default to false, easier to handler for begginers).
add_definitions(-DSQLITECPP_ENABLE_ASSERT_HANDLER)
endif (SQLITE_ENABLE_ASSERT_HANDLER)
option(SQLITE_USE_LEGACY_STRUCT "Fallback to forward declaration of legacy struct sqlite3_value (pre SQLite 3.19)" OFF)
if (SQLITE_USE_LEGACY_STRUCT)
# Force forward declaration of legacy struct sqlite3_value (pre SQLite 3.19)
add_definitions(-DSQLITE_USE_LEGACY_STRUCT)
endif (SQLITE_USE_LEGACY_STRUCT)
## Build the C++ Wrapper ##
# adding a new file require explicittly modifing the CMakeLists.txt
# so that CMake knows that it should rebuild the project (it is best practice)
# list of sources files of the library
set(SQLITECPP_SRC
${PROJECT_SOURCE_DIR}/src/Backup.cpp
${PROJECT_SOURCE_DIR}/src/Column.cpp
${PROJECT_SOURCE_DIR}/src/Database.cpp
${PROJECT_SOURCE_DIR}/src/Exception.cpp
${PROJECT_SOURCE_DIR}/src/Statement.cpp
${PROJECT_SOURCE_DIR}/src/Transaction.cpp
)
source_group(src FILES ${SQLITECPP_SRC})
# list of header files of the library
set(SQLITECPP_INC
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/SQLiteCpp.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Assertion.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Backup.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Column.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Database.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Exception.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Statement.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Transaction.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Utils.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/VariadicBind.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/ExecuteMany.h
)
source_group(include FILES ${SQLITECPP_INC})
# list of test files of the library
set(SQLITECPP_TESTS
tests/Column_test.cpp
tests/Database_test.cpp
tests/Statement_test.cpp
tests/Backup_test.cpp
tests/Transaction_test.cpp
tests/VariadicBind_test.cpp
tests/Exception_test.cpp
tests/ExecuteMany_test.cpp
)
source_group(tests FILES ${SQLITECPP_TESTS})
# list of example files of the library
set(SQLITECPP_EXAMPLES
examples/example1/main.cpp
)
source_group(example1 FILES ${SQLITECPP_EXAMPLES})
# list of doc files of the library
set(SQLITECPP_DOC
README.md
LICENSE.txt
CHANGELOG.md
TODO.txt
)
source_group(doc FILES ${SQLITECPP_DOC})
# list of script files of the library
set(SQLITECPP_SCRIPT
.travis.yml
appveyor.yml
build.bat
build.sh
cpplint.py
Doxyfile
FindSQLiteCpp.cmake
)
source_group(scripts FILES ${SQLITECPP_SCRIPT})
# All includes are relative to the "include" directory
include_directories("${PROJECT_SOURCE_DIR}/include")
# add sources of the wrapper as a "SQLiteCpp" static library
add_library(SQLiteCpp ${SQLITECPP_SRC} ${SQLITECPP_INC} ${SQLITECPP_DOC} ${SQLITECPP_SCRIPT})
# make the sqlite3 library part of the interface of the SQLiteCpp wrapper itself (the client app does not need to link to sqlite3)
# PR https://github.com/SRombauts/SQLiteCpp/pull/111 "linked SQLiteCpp to sqlite3" commented out since it breaks install step from PR #118
#target_link_libraries(SQLiteCpp PUBLIC sqlite3)
if (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-fPIC")
endif (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
# Allow the library to be installed via "make install" and found with "find_package"
install(TARGETS SQLiteCpp
EXPORT ${PROJECT_NAME}Config
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
COMPONENT libraries)
target_include_directories(SQLiteCpp PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/>)
install(DIRECTORY include/ DESTINATION include COMPONENT headers FILES_MATCHING REGEX ".*\\.(hpp|h)$")
install(EXPORT ${PROJECT_NAME}Config DESTINATION lib/cmake/${PROJECT_NAME})
## Build provided copy of SQLite3 C library ##
# TODO
#find_package(sqlite3)
#if(sqlite3_VERSION VERSION_LESS "3.19")
# set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-DSQLITECPP_HAS_MEM_STRUCT")
#endif()
option(SQLITECPP_USE_ASAN "Use Address Sanitizer." OFF)
if (SQLITECPP_USE_ASAN)
if ((CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 6) OR ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang"))
message (STATUS "Using Address Sanitizer")
set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
endif ()
endif ()
endif (SQLITECPP_USE_ASAN)
option(SQLITECPP_INTERNAL_SQLITE "Add the internal SQLite3 source to the project." ON)
if (SQLITECPP_INTERNAL_SQLITE)
# build the SQLite3 C library (for ease of use/compatibility) versus Linux sqlite3-dev package
add_subdirectory(sqlite3)
target_include_directories(sqlite3 PUBLIC "${PROJECT_SOURCE_DIR}/sqlite3")
target_include_directories(SQLiteCpp PRIVATE "${PROJECT_SOURCE_DIR}/sqlite3")
endif (SQLITECPP_INTERNAL_SQLITE)
# Optional additional targets:
option(SQLITECPP_RUN_CPPLINT "Run cpplint.py tool for Google C++ StyleGuide." ON)
if (SQLITECPP_RUN_CPPLINT)
find_package(PythonInterp)
if (PYTHONINTERP_FOUND)
# add a cpplint target to the "all" target
add_custom_target(SQLiteCpp_cpplint
ALL
COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/cpplint.py ${CPPLINT_ARG_OUTPUT} ${CPPLINT_ARG_VERBOSE} ${CPPLINT_ARG_LINELENGTH} ${SQLITECPP_SRC} ${SQLITECPP_INC}
)
endif (PYTHONINTERP_FOUND)
else (SQLITECPP_RUN_CPPLINT)
message(STATUS "SQLITECPP_RUN_CPPLINT OFF")
endif (SQLITECPP_RUN_CPPLINT)
option(SQLITECPP_RUN_CPPCHECK "Run cppcheck C++ static analysis tool." ON)
if (SQLITECPP_RUN_CPPCHECK)
find_program(CPPCHECK_EXECUTABLE NAMES cppcheck)
if (CPPCHECK_EXECUTABLE)
# add a cppcheck target to the "all" target
add_custom_target(SQLiteCpp_cppcheck
ALL
COMMAND ${CPPCHECK_EXECUTABLE} -j 8 cppcheck --enable=style --quiet ${CPPCHECK_ARG_TEMPLATE} ${PROJECT_SOURCE_DIR}/src
)
execute_process(COMMAND "${CPPCHECK_EXECUTABLE}" --version OUTPUT_VARIABLE CPPCHECK_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "Found Cppcheck: ${CPPCHECK_EXECUTABLE} ${CPPCHECK_VERSION}")
else (CPPCHECK_EXECUTABLE)
message(STATUS "Could NOT find cppcheck")
endif (CPPCHECK_EXECUTABLE)
else (SQLITECPP_RUN_CPPCHECK)
message(STATUS "SQLITECPP_RUN_CPPCHECK OFF")
endif (SQLITECPP_RUN_CPPCHECK)
option(SQLITECPP_RUN_DOXYGEN "Run Doxygen C++ documentation tool." OFF)
if (SQLITECPP_RUN_DOXYGEN)
find_package(Doxygen)
if (DOXYGEN_FOUND)
# add a Doxygen target to the "all" target
add_custom_target(SQLiteCpp_doxygen
ALL
COMMAND doxygen Doxyfile > ${DEV_NULL}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
endif (DOXYGEN_FOUND)
else (SQLITECPP_RUN_DOXYGEN)
message(STATUS "SQLITECPP_RUN_DOXYGEN OFF")
endif (SQLITECPP_RUN_DOXYGEN)
option(SQLITECPP_BUILD_EXAMPLES "Build examples." OFF)
if (SQLITECPP_BUILD_EXAMPLES)
# add the basic example executable
add_executable(SQLiteCpp_example1 ${SQLITECPP_EXAMPLES})
target_link_libraries(SQLiteCpp_example1 SQLiteCpp sqlite3)
# Link target with pthread and dl for linux
if (UNIX)
target_link_libraries(SQLiteCpp_example1 pthread)
if (NOT APPLE)
target_link_libraries(SQLiteCpp_example1 dl)
endif ()
elseif (MSYS OR MINGW)
target_link_libraries(SQLiteCpp_example1 ssp)
endif ()
else (SQLITECPP_BUILD_EXAMPLES)
message(STATUS "SQLITECPP_BUILD_EXAMPLES OFF")
endif (SQLITECPP_BUILD_EXAMPLES)
option(SQLITECPP_BUILD_TESTS "Build and run tests." OFF)
if (SQLITECPP_BUILD_TESTS)
# deactivate some warnings for compiling the gtest library
if (NOT MSVC)
add_compile_options(-Wno-variadic-macros -Wno-long-long -Wno-switch-enum -Wno-float-equal -Wno-conversion-null -Wno-switch-default -Wno-pedantic)
endif (NOT MSVC)
# add the subdirectory containing the CMakeLists.txt for the gtest library
# TODO: under Linux, uses libgtest-dev if found
if (NOT EXISTS "${PROJECT_SOURCE_DIR}/googletest/CMakeLists.txt")
message(FATAL_ERROR "Missing 'googletest' submodule! Either use 'git submodule init' and 'git submodule update' to get googletest according to the README, or deactivate unit tests with -DSQLITECPP_BUILD_TESTS=OFF")
endif ()
add_subdirectory(googletest)
include_directories("${PROJECT_SOURCE_DIR}/googletest/googletest/include")
# Add definitions to keep googletest from making the compilation fail
if (MSVC)
if (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS_EQUAL 1919) # OR MSVC_TOOLSET_VERSION EQUAL 141)
target_compile_definitions(gtest PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gtest_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gmock PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gmock_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
endif (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS_EQUAL 1919)
endif (MSVC)
# add the unit test executable
add_executable(SQLiteCpp_tests ${SQLITECPP_TESTS})
target_link_libraries(SQLiteCpp_tests gtest_main SQLiteCpp sqlite3)
# Link target with dl for linux
if (UNIX AND NOT APPLE)
target_link_libraries(SQLiteCpp_tests dl)
endif ()
# add a "test" target:
enable_testing()
# does the tests pass?
add_test(UnitTests SQLiteCpp_tests)
if (SQLITECPP_BUILD_EXAMPLES)
# does the example1 runs successfully?
add_test(Example1Run SQLiteCpp_example1)
endif (SQLITECPP_BUILD_EXAMPLES)
else (SQLITECPP_BUILD_TESTS)
message(STATUS "SQLITECPP_BUILD_TESTS OFF")
endif (SQLITECPP_BUILD_TESTS)

View File

@ -10,78 +10,95 @@
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Backup.h>
#include <SQLiteCpp/Exception.h>
#include <sqlite3.h>
namespace SQLite {
namespace SQLite
{
// Initialize resource for SQLite database backup
Backup::Backup(Database& aDestDatabase,
const char* apDestDatabaseName,
Database& aSrcDatabase,
const char* apSrcDatabaseName)
: mpSQLiteBackup(NULL)
Backup::Backup(Database& aDestDatabase,
const char* apDestDatabaseName,
Database& aSrcDatabase,
const char* apSrcDatabaseName) :
mpSQLiteBackup(NULL)
{
mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(),
apDestDatabaseName,
aSrcDatabase.getHandle(),
apSrcDatabaseName);
if (NULL == mpSQLiteBackup) {
apDestDatabaseName,
aSrcDatabase.getHandle(),
apSrcDatabaseName);
if (NULL == mpSQLiteBackup)
{
// If an error occurs, the error code and message are attached to the destination database connection.
throw SQLite::Exception(aDestDatabase.getHandle());
}
}
// Initialize resource for SQLite database backup
Backup::Backup(Database& aDestDatabase,
const std::string& aDestDatabaseName,
Database& aSrcDatabase,
const std::string& aSrcDatabaseName)
: mpSQLiteBackup(NULL)
Backup::Backup(Database& aDestDatabase,
const std::string& aDestDatabaseName,
Database& aSrcDatabase,
const std::string& aSrcDatabaseName) :
mpSQLiteBackup(NULL)
{
mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(),
aDestDatabaseName.c_str(),
aSrcDatabase.getHandle(),
aSrcDatabaseName.c_str());
if (NULL == mpSQLiteBackup) {
aDestDatabaseName.c_str(),
aSrcDatabase.getHandle(),
aSrcDatabaseName.c_str());
if (NULL == mpSQLiteBackup)
{
// If an error occurs, the error code and message are attached to the destination database connection.
throw SQLite::Exception(aDestDatabase.getHandle());
}
}
// Initialize resource for SQLite database backup
Backup::Backup(Database& aDestDatabase, Database& aSrcDatabase)
: mpSQLiteBackup(NULL)
Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) :
mpSQLiteBackup(NULL)
{
mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(),
"main",
aSrcDatabase.getHandle(),
"main");
if (NULL == mpSQLiteBackup) {
"main",
aSrcDatabase.getHandle(),
"main");
if (NULL == mpSQLiteBackup)
{
// If an error occurs, the error code and message are attached to the destination database connection.
throw SQLite::Exception(aDestDatabase.getHandle());
}
}
// Release resource for SQLite database backup
Backup::~Backup()
{
if (NULL != mpSQLiteBackup) {
if (NULL != mpSQLiteBackup)
{
sqlite3_backup_finish(mpSQLiteBackup);
}
}
// Execute backup step with a given number of source pages to be copied
int Backup::executeStep(const int aNumPage /* = -1 */)
{
const int res = sqlite3_backup_step(mpSQLiteBackup, aNumPage);
if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res) {
if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res)
{
throw SQLite::Exception(sqlite3_errstr(res), res);
}
return res;
}
// Get the number of remaining source pages to be copied in this backup process
int Backup::getRemainingPageCount()
{
return sqlite3_backup_remaining(mpSQLiteBackup);
}
// Get the number of total source pages to be copied in this backup process
int Backup::getTotalPageCount()
{
return sqlite3_backup_pagecount(mpSQLiteBackup);
}
} // namespace SQLite
} // namespace SQLite

View File

@ -9,33 +9,41 @@
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Column.h>
#include <sqlite3.h>
#include <iostream>
namespace SQLite
{
const int INTEGER = SQLITE_INTEGER;
const int FLOAT = SQLITE_FLOAT;
const int TEXT = SQLITE_TEXT;
const int BLOB = SQLITE_BLOB;
const int Null = SQLITE_NULL;
const int INTEGER = SQLITE_INTEGER;
const int FLOAT = SQLITE_FLOAT;
const int TEXT = SQLITE_TEXT;
const int BLOB = SQLITE_BLOB;
const int Null = SQLITE_NULL;
// Encapsulation of a Column in a row of the result pointed by the prepared Statement.
Column::Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept
: // nothrow
mStmtPtr(aStmtPtr)
,
Column::Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept : // nothrow
mStmtPtr(aStmtPtr),
mIndex(aIndex)
{
}
// Finalize and unregister the SQL query from the SQLite Database Connection.
Column::~Column()
{
// the finalization will be done by the destructor of the last shared pointer
}
// Return the named assigned to this result column (potentially aliased)
const char* Column::getName() const noexcept // nothrow
{
return sqlite3_column_name(mStmtPtr, mIndex);
}
#ifdef SQLITE_ENABLE_COLUMN_METADATA
// Return the name of the table column that is the origin of this result column
const char* Column::getOriginName() const noexcept // nothrow
@ -43,61 +51,74 @@ const char* Column::getOriginName() const noexcept // nothrow
return sqlite3_column_origin_name(mStmtPtr, mIndex);
}
#endif
// Return the integer value of the column specified by its index starting at 0
int Column::getInt() const noexcept // nothrow
{
return sqlite3_column_int(mStmtPtr, mIndex);
}
// Return the unsigned integer value of the column specified by its index starting at 0
unsigned Column::getUInt() const noexcept // nothrow
{
return static_cast<unsigned>(getInt64());
}
// Return the 64bits integer value of the column specified by its index starting at 0
long long Column::getInt64() const noexcept // nothrow
{
return sqlite3_column_int64(mStmtPtr, mIndex);
}
// Return the double value of the column specified by its index starting at 0
double Column::getDouble() const noexcept // nothrow
{
return sqlite3_column_double(mStmtPtr, mIndex);
}
// Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0
const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept // nothrow
{
const char* pText = reinterpret_cast<const char*>(sqlite3_column_text(mStmtPtr, mIndex));
return (pText ? pText : apDefaultValue);
return (pText?pText:apDefaultValue);
}
// Return a pointer to the blob value (*not* NULL terminated) of the column specified by its index starting at 0
const void* Column::getBlob() const noexcept // nothrow
{
return sqlite3_column_blob(mStmtPtr, mIndex);
}
// Return a std::string to a TEXT or BLOB column
std::string Column::getString() const
{
// Note: using sqlite3_column_blob and not sqlite3_column_text
// - no need for sqlite3_column_text to add a \0 on the end, as we're getting the bytes length directly
const char* data = static_cast<const char*>(sqlite3_column_blob(mStmtPtr, mIndex));
const char *data = static_cast<const char *>(sqlite3_column_blob(mStmtPtr, mIndex));
// SQLite docs: "The safest policy is to invoke… sqlite3_column_blob() followed by sqlite3_column_bytes()"
// Note: std::string is ok to pass nullptr as first arg, if length is 0
return std::string(data, sqlite3_column_bytes(mStmtPtr, mIndex));
}
// Return the type of the value of the column
int Column::getType() const noexcept // nothrow
{
return sqlite3_column_type(mStmtPtr, mIndex);
}
// Return the number of bytes used by the text value of the column
int Column::getBytes() const noexcept // nothrow
{
return sqlite3_column_bytes(mStmtPtr, mIndex);
}
// Standard std::ostream inserter
std::ostream& operator<<(std::ostream& aStream, const Column& aColumn)
{
aStream.write(aColumn.getText(), aColumn.getBytes());
return aStream;
}
} // namespace SQLite
} // namespace SQLite

View File

@ -9,42 +9,52 @@
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Assertion.h>
#include <SQLiteCpp/Exception.h>
#include <sqlite3.h>
#include <fstream>
#include <string.h>
#ifndef SQLITE_DETERMINISTIC
#define SQLITE_DETERMINISTIC 0x800
#endif // SQLITE_DETERMINISTIC
namespace SQLite
{
const int OPEN_READONLY = SQLITE_OPEN_READONLY;
const int OPEN_READWRITE = SQLITE_OPEN_READWRITE;
const int OPEN_CREATE = SQLITE_OPEN_CREATE;
const int OPEN_URI = SQLITE_OPEN_URI;
const int OK = SQLITE_OK;
const char* VERSION = SQLITE_VERSION;
const int VERSION_NUMBER = SQLITE_VERSION_NUMBER;
const int OPEN_READONLY = SQLITE_OPEN_READONLY;
const int OPEN_READWRITE = SQLITE_OPEN_READWRITE;
const int OPEN_CREATE = SQLITE_OPEN_CREATE;
const int OPEN_URI = SQLITE_OPEN_URI;
const int OK = SQLITE_OK;
const char* VERSION = SQLITE_VERSION;
const int VERSION_NUMBER = SQLITE_VERSION_NUMBER;
// Return SQLite version string using runtime call to the compiled library
const char* getLibVersion() noexcept // nothrow
{
return sqlite3_libversion();
}
// Return SQLite version number using runtime call to the compiled library
int getLibVersionNumber() noexcept // nothrow
{
return sqlite3_libversion_number();
}
// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
Database::Database(const char* apFilename,
const int aFlags /* = SQLite::OPEN_READONLY*/,
const int aBusyTimeoutMs /* = 0 */,
const char* apVfs /* = nullptr*/)
:
mpSQLite(nullptr)
,
const int aFlags /* = SQLite::OPEN_READONLY*/,
const int aBusyTimeoutMs /* = 0 */,
const char* apVfs /* = nullptr*/) :
mpSQLite(nullptr),
mFilename(apFilename)
{
const int ret = sqlite3_open_v2(apFilename, &mpSQLite, aFlags, apVfs);
@ -59,14 +69,13 @@ Database::Database(const char* apFilename,
setBusyTimeout(aBusyTimeoutMs);
}
}
// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
Database::Database(const std::string& aFilename,
const int aFlags /* = SQLite::OPEN_READONLY*/,
const int aBusyTimeoutMs /* = 0 */,
const std::string& aVfs /* = "" */)
:
mpSQLite(nullptr)
,
const int aFlags /* = SQLite::OPEN_READONLY*/,
const int aBusyTimeoutMs /* = 0 */,
const std::string& aVfs /* = "" */) :
mpSQLite(nullptr),
mFilename(aFilename)
{
const int ret = sqlite3_open_v2(aFilename.c_str(), &mpSQLite, aFlags, aVfs.empty() ? nullptr : aVfs.c_str());
@ -81,16 +90,20 @@ Database::Database(const std::string& aFilename,
setBusyTimeout(aBusyTimeoutMs);
}
}
// Close the SQLite database connection.
Database::~Database()
{
const int ret = sqlite3_close(mpSQLite);
// Avoid unreferenced variable warning when build in release mode
(void)ret;
(void) ret;
// Only case of error is SQLITE_BUSY: "database is locked" (some statements are not finalized)
// Never throw an exception in a destructor :
SQLITECPP_ASSERT(SQLITE_OK == ret, "database is locked"); // See SQLITECPP_ENABLE_ASSERT_HANDLER
SQLITECPP_ASSERT(SQLITE_OK == ret, "database is locked"); // See SQLITECPP_ENABLE_ASSERT_HANDLER
}
/**
* @brief Set a busy handler that sleeps for a specified amount of time when a table is locked.
*
@ -109,14 +122,17 @@ void Database::setBusyTimeout(const int aBusyTimeoutMs)
const int ret = sqlite3_busy_timeout(mpSQLite, aBusyTimeoutMs);
check(ret);
}
// Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...).
int Database::exec(const char* apQueries)
{
const int ret = sqlite3_exec(mpSQLite, apQueries, nullptr, nullptr, nullptr);
check(ret);
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only)
return sqlite3_changes(mpSQLite);
}
// Shortcut to execute a one step query and fetch the first column of the result.
// WARNING: Be very careful with this dangerous method: you have to
// make a COPY OF THE result, else it will be destroy before the next line
@ -129,6 +145,7 @@ Column Database::execAndGet(const char* apQuery)
(void)query.executeStep(); // Can return false if no result, which will throw next line in getColumn()
return query.getColumn(0);
}
// Shortcut to test if a table exists.
bool Database::tableExists(const char* apTableName)
{
@ -137,60 +154,68 @@ bool Database::tableExists(const char* apTableName)
(void)query.executeStep(); // Cannot return false, as the above query always return a result
return (1 == query.getColumn(0).getInt());
}
// Get the rowid of the most recent successful INSERT into the database from the current connection.
long long Database::getLastInsertRowid() const noexcept // nothrow
{
return sqlite3_last_insert_rowid(mpSQLite);
}
// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection.
int Database::getTotalChanges() const noexcept // nothrow
{
return sqlite3_total_changes(mpSQLite);
}
// Return the numeric result code for the most recent failed API call (if any).
int Database::getErrorCode() const noexcept // nothrow
{
return sqlite3_errcode(mpSQLite);
}
// Return the extended numeric result code for the most recent failed API call (if any).
int Database::getExtendedErrorCode() const noexcept // nothrow
{
return sqlite3_extended_errcode(mpSQLite);
}
// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Database::getErrorMsg() const noexcept // nothrow
{
return sqlite3_errmsg(mpSQLite);
}
// Attach a custom function to your sqlite database. Assumes UTF8 text representation.
// Parameter details can be found here: http://www.sqlite.org/c3ref/create_function.html
void Database::createFunction(const char* apFuncName,
int aNbArg,
bool abDeterministic,
void* apApp,
void (*apFunc)(sqlite3_context*, int, sqlite3_value**),
void (*apStep)(sqlite3_context*, int, sqlite3_value**),
void (*apFinal)(sqlite3_context*), // NOLINT(readability/casting)
void (*apDestroy)(void*))
void Database::createFunction(const char* apFuncName,
int aNbArg,
bool abDeterministic,
void* apApp,
void (*apFunc)(sqlite3_context *, int, sqlite3_value **),
void (*apStep)(sqlite3_context *, int, sqlite3_value **),
void (*apFinal)(sqlite3_context *), // NOLINT(readability/casting)
void (*apDestroy)(void *))
{
int TextRep = SQLITE_UTF8;
// optimization if deterministic function (e.g. of nondeterministic function random())
if (abDeterministic)
{
TextRep = TextRep | SQLITE_DETERMINISTIC;
TextRep = TextRep|SQLITE_DETERMINISTIC;
}
const int ret = sqlite3_create_function_v2(mpSQLite, apFuncName, aNbArg, TextRep,
apApp, apFunc, apStep, apFinal, apDestroy);
apApp, apFunc, apStep, apFinal, apDestroy);
check(ret);
}
// Load an extension into the sqlite database. Only affects the current connection.
// Parameter details can be found here: http://www.sqlite.org/c3ref/load_extension.html
void Database::loadExtension(const char* apExtensionName, const char* apEntryPointName)
void Database::loadExtension(const char* apExtensionName, const char *apEntryPointName)
{
#ifdef SQLITE_OMIT_LOAD_EXTENSION
// Unused
(void)apExtensionName;
(void)apEntryPointName;
throw std::runtime_error("sqlite extensions are disabled");
#else
#ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION // Since SQLite 3.13 (2016-05-18):
@ -204,10 +229,12 @@ void Database::loadExtension(const char* apExtensionName, const char* apEntryPoi
int ret = sqlite3_enable_load_extension(mpSQLite, 1);
#endif
check(ret);
ret = sqlite3_load_extension(mpSQLite, apExtensionName, apEntryPointName, 0);
check(ret);
#endif
}
// Set the key for the current sqlite database instance.
void Database::key(const std::string& aKey) const
{
@ -226,6 +253,7 @@ void Database::key(const std::string& aKey) const
}
#endif // SQLITE_HAS_CODEC
}
// Reset the key for the current sqlite database instance.
void Database::rekey(const std::string& aNewKey) const
{
@ -247,6 +275,7 @@ void Database::rekey(const std::string& aNewKey) const
throw exception;
#endif // SQLITE_HAS_CODEC
}
// Test if a file contains an unencrypted database.
bool Database::isUnencrypted(const std::string& aFilename)
{
@ -270,4 +299,5 @@ bool Database::isUnencrypted(const std::string& aFilename)
const SQLite::Exception exception("Could not open database, the aFilename parameter was empty.");
throw exception;
}
} // namespace SQLite
} // namespace SQLite

View File

@ -9,66 +9,59 @@
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Exception.h>
#include <sqlite3.h>
namespace SQLite
{
Exception::Exception(const char* aErrorMessage)
:
std::runtime_error(aErrorMessage)
,
mErrcode(-1)
, // 0 would be SQLITE_OK, which doesn't make sense
Exception::Exception(const char* aErrorMessage) :
std::runtime_error(aErrorMessage),
mErrcode(-1), // 0 would be SQLITE_OK, which doesn't make sense
mExtendedErrcode(-1)
{
}
Exception::Exception(const std::string& aErrorMessage)
:
std::runtime_error(aErrorMessage)
,
mErrcode(-1)
, // 0 would be SQLITE_OK, which doesn't make sense
Exception::Exception(const std::string& aErrorMessage) :
std::runtime_error(aErrorMessage),
mErrcode(-1), // 0 would be SQLITE_OK, which doesn't make sense
mExtendedErrcode(-1)
{
}
Exception::Exception(const char* aErrorMessage, int ret)
:
std::runtime_error(aErrorMessage)
,
mErrcode(ret)
,
Exception::Exception(const char* aErrorMessage, int ret) :
std::runtime_error(aErrorMessage),
mErrcode(ret),
mExtendedErrcode(-1)
{
}
Exception::Exception(const std::string& aErrorMessage, int ret)
:
std::runtime_error(aErrorMessage)
,
mErrcode(ret)
,
Exception::Exception(const std::string& aErrorMessage, int ret) :
std::runtime_error(aErrorMessage),
mErrcode(ret),
mExtendedErrcode(-1)
{
}
Exception::Exception(sqlite3* apSQLite)
:
std::runtime_error(sqlite3_errmsg(apSQLite))
,
mErrcode(sqlite3_errcode(apSQLite))
,
Exception::Exception(sqlite3* apSQLite) :
std::runtime_error(sqlite3_errmsg(apSQLite)),
mErrcode(sqlite3_errcode(apSQLite)),
mExtendedErrcode(sqlite3_extended_errcode(apSQLite))
{
}
Exception::Exception(sqlite3* apSQLite, int ret)
:
std::runtime_error(sqlite3_errmsg(apSQLite))
,
mErrcode(ret)
,
Exception::Exception(sqlite3* apSQLite, int ret) :
std::runtime_error(sqlite3_errmsg(apSQLite)),
mErrcode(ret),
mExtendedErrcode(sqlite3_extended_errcode(apSQLite))
{
}
// Return a string, solely based on the error code
const char* Exception::getErrorStr() const noexcept // nothrow
{
return sqlite3_errstr(mErrcode);
}
} // namespace SQLite
} // namespace SQLite

View File

@ -9,54 +9,45 @@
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Column.h>
#include <SQLiteCpp/Assertion.h>
#include <SQLiteCpp/Exception.h>
#include <sqlite3.h>
namespace SQLite
{
// Compile and register the SQL query for the provided SQLite Database Connection
Statement::Statement(Database& aDatabase, const char* apQuery)
:
mQuery(apQuery)
,
mStmtPtr(aDatabase.mpSQLite, mQuery)
, // prepare the SQL query, and ref count (needs Database friendship)
mColumnCount(0)
,
mbHasRow(false)
,
Statement::Statement(Database &aDatabase, const char* apQuery) :
mQuery(apQuery),
mStmtPtr(aDatabase.mpSQLite, mQuery), // prepare the SQL query, and ref count (needs Database friendship)
mColumnCount(0),
mbHasRow(false),
mbDone(false)
{
mColumnCount = sqlite3_column_count(mStmtPtr);
}
// Compile and register the SQL query for the provided SQLite Database Connection
Statement::Statement(Database& aDatabase, const std::string& aQuery)
:
mQuery(aQuery)
,
mStmtPtr(aDatabase.mpSQLite, mQuery)
, // prepare the SQL query, and ref count (needs Database friendship)
mColumnCount(0)
,
mbHasRow(false)
,
Statement::Statement(Database &aDatabase, const std::string& aQuery) :
mQuery(aQuery),
mStmtPtr(aDatabase.mpSQLite, mQuery), // prepare the SQL query, and ref count (needs Database friendship)
mColumnCount(0),
mbHasRow(false),
mbDone(false)
{
mColumnCount = sqlite3_column_count(mStmtPtr);
}
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
Statement::Statement(Statement&& aStatement) noexcept
:
mQuery(std::move(aStatement.mQuery))
,
mStmtPtr(std::move(aStatement.mStmtPtr))
,
mColumnCount(aStatement.mColumnCount)
,
mbHasRow(aStatement.mbHasRow)
,
Statement::Statement(Statement&& aStatement) noexcept :
mQuery(std::move(aStatement.mQuery)),
mStmtPtr(std::move(aStatement.mStmtPtr)),
mColumnCount(aStatement.mColumnCount),
mbHasRow(aStatement.mbHasRow),
mbDone(aStatement.mbDone)
{
aStatement.mColumnCount = 0;
@ -64,97 +55,114 @@ Statement::Statement(Statement&& aStatement) noexcept
aStatement.mbDone = false;
}
#endif
// Finalize and unregister the SQL query from the SQLite Database Connection.
Statement::~Statement()
{
// the finalization will be done by the destructor of the last shared pointer
}
// Reset the statement to make it ready for a new execution (see also #clearBindings() bellow)
void Statement::reset()
{
const int ret = tryReset();
check(ret);
}
int Statement::tryReset() noexcept
{
mbHasRow = false;
mbDone = false;
return sqlite3_reset(mStmtPtr);
}
// Clears away all the bindings of a prepared statement (can be associated with #reset() above).
void Statement::clearBindings()
{
const int ret = sqlite3_clear_bindings(mStmtPtr);
check(ret);
}
// Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const int aValue)
{
const int ret = sqlite3_bind_int(mStmtPtr, aIndex, aValue);
check(ret);
}
// Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const unsigned aValue)
{
const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue);
check(ret);
}
// Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const long long aValue)
{
const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue);
check(ret);
}
// Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const double aValue)
{
const int ret = sqlite3_bind_double(mStmtPtr, aIndex, aValue);
check(ret);
}
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const std::string& aValue)
{
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(),
static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
check(ret);
}
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const char* apValue)
{
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_TRANSIENT);
check(ret);
}
// Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const void* apValue, const int aSize)
{
const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_TRANSIENT);
check(ret);
}
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const int aIndex, const std::string& aValue)
{
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(),
static_cast<int>(aValue.size()), SQLITE_STATIC);
static_cast<int>(aValue.size()), SQLITE_STATIC);
check(ret);
}
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const int aIndex, const char* apValue)
{
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_STATIC);
check(ret);
}
// Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const int aIndex, const void* apValue, const int aSize)
{
const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_STATIC);
check(ret);
}
// Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex)
{
const int ret = sqlite3_bind_null(mStmtPtr, aIndex);
check(ret);
}
// Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const int aValue)
{
@ -162,6 +170,7 @@ void Statement::bind(const char* apName, const int aValue)
const int ret = sqlite3_bind_int(mStmtPtr, index, aValue);
check(ret);
}
// Bind a 32bits unsigned int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const unsigned aValue)
{
@ -169,6 +178,7 @@ void Statement::bind(const char* apName, const unsigned aValue)
const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
check(ret);
}
// Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const long long aValue)
{
@ -176,6 +186,7 @@ void Statement::bind(const char* apName, const long long aValue)
const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
check(ret);
}
// Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const double aValue)
{
@ -183,14 +194,16 @@ void Statement::bind(const char* apName, const double aValue)
const int ret = sqlite3_bind_double(mStmtPtr, index, aValue);
check(ret);
}
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const std::string& aValue)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(),
static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
check(ret);
}
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const char* apValue)
{
@ -198,6 +211,7 @@ void Statement::bind(const char* apName, const char* apValue)
const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_TRANSIENT);
check(ret);
}
// Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const void* apValue, const int aSize)
{
@ -205,14 +219,16 @@ void Statement::bind(const char* apName, const void* apValue, const int aSize)
const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_TRANSIENT);
check(ret);
}
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const char* apName, const std::string& aValue)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(),
static_cast<int>(aValue.size()), SQLITE_STATIC);
static_cast<int>(aValue.size()), SQLITE_STATIC);
check(ret);
}
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const char* apName, const char* apValue)
{
@ -220,6 +236,7 @@ void Statement::bindNoCopy(const char* apName, const char* apValue)
const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_STATIC);
check(ret);
}
// Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const char* apName, const void* apValue, const int aSize)
{
@ -227,6 +244,7 @@ void Statement::bindNoCopy(const char* apName, const void* apValue, const int aS
const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_STATIC);
check(ret);
}
// Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName)
{
@ -234,6 +252,8 @@ void Statement::bind(const char* apName)
const int ret = sqlite3_bind_null(mStmtPtr, index);
check(ret);
}
// Execute a step of the query to fetch one row of results
bool Statement::executeStep()
{
@ -249,8 +269,10 @@ bool Statement::executeStep()
throw SQLite::Exception("Statement needs to be reseted", ret);
}
}
return mbHasRow; // true only if one row is accessible by getColumn(N)
}
// Execute a one-step query with no expected result
int Statement::exec()
{
@ -270,9 +292,11 @@ int Statement::exec()
throw SQLite::Exception("Statement needs to be reseted", ret);
}
}
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE)
return sqlite3_changes(mStmtPtr);
}
int Statement::tryExecuteStep() noexcept
{
if (false == mbDone)
@ -292,6 +316,7 @@ int Statement::tryExecuteStep() noexcept
mbHasRow = false;
mbDone = false;
}
return ret;
}
else
@ -300,24 +325,30 @@ int Statement::tryExecuteStep() noexcept
return SQLITE_MISUSE;
}
}
// Return a copy of the column data specified by its index starting at 0
// (use the Column copy-constructor)
Column Statement::getColumn(const int aIndex)
{
checkRow();
checkIndex(aIndex);
// Share the Statement Object handle with the new Column created
return Column(mStmtPtr, aIndex);
}
// Return a copy of the column data specified by its column name starting at 0
// (use the Column copy-constructor)
Column Statement::getColumn(const char* apName)
Column Statement::getColumn(const char* apName)
{
checkRow();
const int index = getColumnIndex(apName);
// Share the Statement Object handle with the new Column created
return Column(mStmtPtr, index);
}
// Test if the column is NULL
bool Statement::isColumnNull(const int aIndex) const
{
@ -325,18 +356,21 @@ bool Statement::isColumnNull(const int aIndex) const
checkIndex(aIndex);
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex));
}
bool Statement::isColumnNull(const char* apName) const
{
checkRow();
const int index = getColumnIndex(apName);
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, index));
}
// Return the named assigned to the specified result column (potentially aliased)
const char* Statement::getColumnName(const int aIndex) const
{
checkIndex(aIndex);
return sqlite3_column_name(mStmtPtr, aIndex);
}
#ifdef SQLITE_ENABLE_COLUMN_METADATA
// Return the named assigned to the specified result column (potentially aliased)
const char* Statement::getColumnOriginName(const int aIndex) const
@ -345,6 +379,7 @@ const char* Statement::getColumnOriginName(const int aIndex) const
return sqlite3_column_origin_name(mStmtPtr, aIndex);
}
#endif
// Return the index of the specified (potentially aliased) column name
int Statement::getColumnIndex(const char* apName) const
{
@ -357,55 +392,60 @@ int Statement::getColumnIndex(const char* apName) const
mColumnNames[pName] = i;
}
}
const TColumnNames::const_iterator iIndex = mColumnNames.find(apName);
if (iIndex == mColumnNames.end())
{
throw SQLite::Exception("Unknown column name.");
}
return (*iIndex).second;
}
int Statement::getBindParameterCount() const noexcept
{
return sqlite3_bind_parameter_count(mStmtPtr);
}
// Return the numeric result code for the most recent failed API call (if any).
int Statement::getErrorCode() const noexcept // nothrow
{
return sqlite3_errcode(mStmtPtr);
}
// Return the extended numeric result code for the most recent failed API call (if any).
int Statement::getExtendedErrorCode() const noexcept // nothrow
{
return sqlite3_extended_errcode(mStmtPtr);
}
// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Statement::getErrorMsg() const noexcept // nothrow
{
return sqlite3_errmsg(mStmtPtr);
}
// Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded.
std::string Statement::getExpandedSQL()
{
std::string Statement::getExpandedSQL() {
char* expanded = sqlite3_expanded_sql(mStmtPtr);
std::string expandedString(expanded);
sqlite3_free(expanded);
return expandedString;
}
////////////////////////////////////////////////////////////////////////////////
// Internal class : shared pointer to the sqlite3_stmt SQLite Statement Object
////////////////////////////////////////////////////////////////////////////////
/**
* @brief Prepare the statement and initialize its reference counter
*
* @param[in] apSQLite The sqlite3 database connexion
* @param[in] aQuery The SQL query string to prepare
*/
Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery)
:
mpSQLite(apSQLite)
,
mpStmt(NULL)
,
Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) :
mpSQLite(apSQLite),
mpStmt(NULL),
mpRefCount(NULL)
{
const int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), static_cast<int>(aQuery.size()), &mpStmt, NULL);
@ -416,34 +456,31 @@ Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery)
// Initialize the reference counter of the sqlite3_stmt :
// used to share the mStmtPtr between Statement and Column objects;
// This is needed to enable Column objects to live longer than the Statement objet it refers to.
mpRefCount = new unsigned int(1); // NOLINT(readability/casting)
mpRefCount = new unsigned int(1); // NOLINT(readability/casting)
}
/**
* @brief Copy constructor increments the ref counter
*
* @param[in] aPtr Pointer to copy
*/
Statement::Ptr::Ptr(const Statement::Ptr& aPtr)
:
mpSQLite(aPtr.mpSQLite)
,
mpStmt(aPtr.mpStmt)
,
Statement::Ptr::Ptr(const Statement::Ptr& aPtr) :
mpSQLite(aPtr.mpSQLite),
mpStmt(aPtr.mpStmt),
mpRefCount(aPtr.mpRefCount)
{
assert(NULL != mpRefCount);
assert(0 != *mpRefCount);
// Increment the reference counter of the sqlite3_stmt,
// asking not to finalize the sqlite3_stmt during the lifetime of the new objet
++(*mpRefCount);
}
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
Statement::Ptr::Ptr(Ptr&& aPtr)
:
mpSQLite(aPtr.mpSQLite)
,
mpStmt(aPtr.mpStmt)
,
Statement::Ptr::Ptr(Ptr&& aPtr) :
mpSQLite(aPtr.mpSQLite),
mpStmt(aPtr.mpStmt),
mpRefCount(aPtr.mpRefCount)
{
aPtr.mpSQLite = NULL;
@ -451,6 +488,7 @@ Statement::Ptr::Ptr(Ptr&& aPtr)
aPtr.mpRefCount = NULL;
}
#endif
/**
* @brief Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
*/
@ -459,6 +497,7 @@ Statement::Ptr::~Ptr()
if (NULL != mpRefCount)
{
assert(0 != *mpRefCount);
// Decrement and check the reference counter of the sqlite3_stmt
--(*mpRefCount);
if (0 == *mpRefCount)
@ -466,6 +505,7 @@ Statement::Ptr::~Ptr()
// If count reaches zero, finalize the sqlite3_stmt, as no Statement nor Column objet use it anymore.
// No need to check the return code, as it is the same as the last statement evaluation.
sqlite3_finalize(mpStmt);
// and delete the reference counter
delete mpRefCount;
mpRefCount = NULL;
@ -474,4 +514,6 @@ Statement::Ptr::~Ptr()
// else, the finalization will be done later, by the last object
}
}
} // namespace SQLite
} // namespace SQLite

View File

@ -9,19 +9,23 @@
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Transaction.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Assertion.h>
namespace SQLite
{
// Begins the SQLite transaction
Transaction::Transaction(Database& aDatabase)
:
mDatabase(aDatabase)
,
Transaction::Transaction(Database& aDatabase) :
mDatabase(aDatabase),
mbCommited(false)
{
mDatabase.exec("BEGIN");
}
// Safely rollback the transaction if it has not been committed.
Transaction::~Transaction()
{
@ -37,6 +41,7 @@ Transaction::~Transaction()
}
}
}
// Commit the transaction.
void Transaction::commit()
{
@ -50,4 +55,6 @@ void Transaction::commit()
throw SQLite::Exception("Transaction already commited.");
}
}
} // namespace SQLite
} // namespace SQLite