mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Moved sqlite3 over here.
This commit is contained in:
parent
d0a8ea21af
commit
2e683a4b69
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2013-2016, Roland Bock
|
# Copyright (c) 2013-2021, Roland Bock
|
||||||
# Copyright (c) 2016 Christian Dávid
|
# Copyright (c) 2016 Christian Dávid
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
@ -27,6 +27,35 @@
|
|||||||
cmake_minimum_required(VERSION 3.14)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
project(sqlpp11 VERSION 0.1 LANGUAGES CXX)
|
project(sqlpp11 VERSION 0.1 LANGUAGES CXX)
|
||||||
|
|
||||||
|
option(MYSQL_CONNECTOR "Build MySQL Connector" OFF)
|
||||||
|
option(POSTGRESQL_CONNECTOR "Build PostgreSQL Connector" OFF)
|
||||||
|
option(SQLITE3_CONNECTOR "Build SQLite3 Connector" OFF)
|
||||||
|
option(SQLCIPHER_CONNECTOR "Build SQLite3 Connector with SQLCipher" OFF)
|
||||||
|
|
||||||
|
if(MYSQL_CONNECTOR)
|
||||||
|
find_package(MySQL REQUIRED)
|
||||||
|
else()
|
||||||
|
message(STATUS "Not building MYSQL_CONNECTOR")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(POSTGRESQL_CONNECTOR)
|
||||||
|
find_package(PostgreSQL REQUIRED)
|
||||||
|
else()
|
||||||
|
message(STATUS "Not building POSTGRESQL_CONNECTOR")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SQLITE3_CONNECTOR)
|
||||||
|
find_package(SQLite3 REQUIRED)
|
||||||
|
else()
|
||||||
|
message(STATUS "Not building SQLITE3_CONNECTOR")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SQLCIPHER_CONNECTOR)
|
||||||
|
find_package(SQLCipher REQUIRED)
|
||||||
|
else()
|
||||||
|
message(STATUS "Not building SQLCIPHER_CONNECTOR")
|
||||||
|
endif()
|
||||||
|
|
||||||
### Project Wide Setup
|
### Project Wide Setup
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||||
|
|
||||||
@ -44,10 +73,13 @@ endif()
|
|||||||
### Dependencies
|
### Dependencies
|
||||||
add_subdirectory(dependencies)
|
add_subdirectory(dependencies)
|
||||||
|
|
||||||
### Main targets
|
### Core targets
|
||||||
add_library(sqlpp11 INTERFACE)
|
add_library(sqlpp11 INTERFACE)
|
||||||
add_library(sqlpp11::sqlpp11 ALIAS sqlpp11)
|
add_library(sqlpp11::sqlpp11 ALIAS sqlpp11)
|
||||||
|
|
||||||
|
# Connector targets
|
||||||
|
add_subdirectory(src)
|
||||||
|
|
||||||
target_link_libraries(sqlpp11 INTERFACE date::date)
|
target_link_libraries(sqlpp11 INTERFACE date::date)
|
||||||
|
|
||||||
target_include_directories(sqlpp11 INTERFACE
|
target_include_directories(sqlpp11 INTERFACE
|
||||||
@ -127,8 +159,5 @@ install(
|
|||||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
|
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
add_subdirectory(test_types)
|
add_subdirectory(test_types)
|
||||||
add_subdirectory(test_serializer)
|
|
||||||
add_subdirectory(test_static_asserts)
|
|
||||||
add_subdirectory(test_constraints)
|
|
||||||
add_subdirectory(test_scripts)
|
add_subdirectory(test_scripts)
|
||||||
endif()
|
endif()
|
||||||
|
109
include/sqlpp11/sqlite3/bind_result.h
Normal file
109
include/sqlpp11/sqlite3/bind_result.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2015, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_SQLITE3_BIND_RESULT_H
|
||||||
|
#define SQLPP_SQLITE3_BIND_RESULT_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <sqlpp11/chrono.h>
|
||||||
|
#include <sqlpp11/sqlite3/export.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct prepared_statement_handle_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SQLPP11_SQLITE3_EXPORT bind_result_t
|
||||||
|
{
|
||||||
|
std::shared_ptr<detail::prepared_statement_handle_t> _handle;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bind_result_t() = default;
|
||||||
|
bind_result_t(const std::shared_ptr<detail::prepared_statement_handle_t>& handle);
|
||||||
|
bind_result_t(const bind_result_t&) = delete;
|
||||||
|
bind_result_t(bind_result_t&& rhs) = default;
|
||||||
|
bind_result_t& operator=(const bind_result_t&) = delete;
|
||||||
|
bind_result_t& operator=(bind_result_t&&) = default;
|
||||||
|
~bind_result_t() = default;
|
||||||
|
|
||||||
|
bool operator==(const bind_result_t& rhs) const
|
||||||
|
{
|
||||||
|
return _handle == rhs._handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ResultRow>
|
||||||
|
void next(ResultRow& result_row)
|
||||||
|
{
|
||||||
|
if (!_handle)
|
||||||
|
{
|
||||||
|
result_row._invalidate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_impl())
|
||||||
|
{
|
||||||
|
if (not result_row)
|
||||||
|
{
|
||||||
|
result_row._validate();
|
||||||
|
}
|
||||||
|
result_row._bind(*this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (result_row)
|
||||||
|
result_row._invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _bind_boolean_result(size_t index, signed char* value, bool* is_null);
|
||||||
|
void _bind_floating_point_result(size_t index, double* value, bool* is_null);
|
||||||
|
void _bind_integral_result(size_t index, int64_t* value, bool* is_null);
|
||||||
|
void _bind_unsigned_integral_result(size_t index, uint64_t* value, bool* is_null);
|
||||||
|
void _bind_text_result(size_t index, const char** text, size_t* len);
|
||||||
|
void _bind_blob_result(size_t index, const uint8_t** text, size_t* len);
|
||||||
|
void _bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null);
|
||||||
|
void _bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool next_impl();
|
||||||
|
};
|
||||||
|
} // namespace sqlite3
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
359
include/sqlpp11/sqlite3/connection.h
Normal file
359
include/sqlpp11/sqlite3/connection.h
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_SQLITE3_CONNECTION_H
|
||||||
|
#define SQLPP_SQLITE3_CONNECTION_H
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <sqlpp11/connection.h>
|
||||||
|
#include <sqlpp11/schema.h>
|
||||||
|
#include <sqlpp11/serialize.h>
|
||||||
|
#include <sqlpp11/sqlite3/bind_result.h>
|
||||||
|
#include <sqlpp11/sqlite3/connection_config.h>
|
||||||
|
#include <sqlpp11/sqlite3/prepared_statement.h>
|
||||||
|
#include <sqlpp11/transaction.h>
|
||||||
|
#include <sqlpp11/type_traits.h>
|
||||||
|
#include <sqlpp11/sqlite3/export.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4251)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct connection_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
class connection;
|
||||||
|
|
||||||
|
struct serializer_t
|
||||||
|
{
|
||||||
|
serializer_t(const connection& db) : _db(db), _count(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream& operator<<(T t)
|
||||||
|
{
|
||||||
|
return _os << t;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string escape(std::string arg);
|
||||||
|
|
||||||
|
std::string str() const
|
||||||
|
{
|
||||||
|
return _os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count() const
|
||||||
|
{
|
||||||
|
return _count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_count()
|
||||||
|
{
|
||||||
|
++_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection& _db;
|
||||||
|
std::stringstream _os;
|
||||||
|
size_t _count;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SQLPP11_SQLITE3_EXPORT connection : public sqlpp::connection
|
||||||
|
{
|
||||||
|
std::unique_ptr<detail::connection_handle> _handle;
|
||||||
|
enum class transaction_status_type
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
maybe,
|
||||||
|
active
|
||||||
|
};
|
||||||
|
|
||||||
|
transaction_status_type _transaction_status = transaction_status_type::none;
|
||||||
|
|
||||||
|
// direct execution
|
||||||
|
bind_result_t select_impl(const std::string& statement);
|
||||||
|
size_t insert_impl(const std::string& statement);
|
||||||
|
size_t update_impl(const std::string& statement);
|
||||||
|
size_t remove_impl(const std::string& statement);
|
||||||
|
|
||||||
|
// prepared execution
|
||||||
|
prepared_statement_t prepare_impl(const std::string& statement);
|
||||||
|
bind_result_t run_prepared_select_impl(prepared_statement_t& prepared_statement);
|
||||||
|
size_t run_prepared_execute_impl(prepared_statement_t& prepared_statement);
|
||||||
|
size_t run_prepared_insert_impl(prepared_statement_t& prepared_statement);
|
||||||
|
size_t run_prepared_update_impl(prepared_statement_t& prepared_statement);
|
||||||
|
size_t run_prepared_remove_impl(prepared_statement_t& prepared_statement);
|
||||||
|
|
||||||
|
public:
|
||||||
|
using _prepared_statement_t = prepared_statement_t;
|
||||||
|
using _context_t = serializer_t;
|
||||||
|
using _serializer_context_t = _context_t;
|
||||||
|
using _interpreter_context_t = _context_t;
|
||||||
|
|
||||||
|
struct _tags
|
||||||
|
{
|
||||||
|
using _null_result_is_trivial_value = std::true_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static _context_t& _serialize_interpretable(const T& t, _context_t& context)
|
||||||
|
{
|
||||||
|
return ::sqlpp::serialize(t, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static _context_t& _interpret_interpretable(const T& t, _context_t& context)
|
||||||
|
{
|
||||||
|
return ::sqlpp::serialize(t, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
connection(connection_config config);
|
||||||
|
connection(connection&&) noexcept;
|
||||||
|
connection& operator=(connection&&) noexcept;
|
||||||
|
~connection();
|
||||||
|
connection(const connection&) = delete;
|
||||||
|
connection& operator=(const connection&) = delete;
|
||||||
|
|
||||||
|
//! select returns a result (which can be iterated row by row)
|
||||||
|
template <typename Select>
|
||||||
|
bind_result_t select(const Select& s)
|
||||||
|
{
|
||||||
|
_context_t context(*this);
|
||||||
|
serialize(s, context);
|
||||||
|
return select_impl(context.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Select>
|
||||||
|
_prepared_statement_t prepare_select(Select& s)
|
||||||
|
{
|
||||||
|
_context_t context(*this);
|
||||||
|
serialize(s, context);
|
||||||
|
return prepare_impl(context.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PreparedSelect>
|
||||||
|
bind_result_t run_prepared_select(const PreparedSelect& s)
|
||||||
|
{
|
||||||
|
s._prepared_statement._reset();
|
||||||
|
s._bind_params();
|
||||||
|
return run_prepared_select_impl(s._prepared_statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! insert returns the last auto_incremented id (or zero, if there is none)
|
||||||
|
template <typename Insert>
|
||||||
|
size_t insert(const Insert& i)
|
||||||
|
{
|
||||||
|
_context_t context(*this);
|
||||||
|
serialize(i, context);
|
||||||
|
return insert_impl(context.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Insert>
|
||||||
|
_prepared_statement_t prepare_insert(Insert& i)
|
||||||
|
{
|
||||||
|
_context_t context(*this);
|
||||||
|
serialize(i, context);
|
||||||
|
return prepare_impl(context.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PreparedInsert>
|
||||||
|
size_t run_prepared_insert(const PreparedInsert& i)
|
||||||
|
{
|
||||||
|
i._prepared_statement._reset();
|
||||||
|
i._bind_params();
|
||||||
|
return run_prepared_insert_impl(i._prepared_statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! update returns the number of affected rows
|
||||||
|
template <typename Update>
|
||||||
|
size_t update(const Update& u)
|
||||||
|
{
|
||||||
|
_context_t context(*this);
|
||||||
|
serialize(u, context);
|
||||||
|
return update_impl(context.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Update>
|
||||||
|
_prepared_statement_t prepare_update(Update& u)
|
||||||
|
{
|
||||||
|
_context_t context(*this);
|
||||||
|
serialize(u, context);
|
||||||
|
return prepare_impl(context.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PreparedUpdate>
|
||||||
|
size_t run_prepared_update(const PreparedUpdate& u)
|
||||||
|
{
|
||||||
|
u._prepared_statement._reset();
|
||||||
|
u._bind_params();
|
||||||
|
return run_prepared_update_impl(u._prepared_statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! remove returns the number of removed rows
|
||||||
|
template <typename Remove>
|
||||||
|
size_t remove(const Remove& r)
|
||||||
|
{
|
||||||
|
_context_t context(*this);
|
||||||
|
serialize(r, context);
|
||||||
|
return remove_impl(context.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Remove>
|
||||||
|
_prepared_statement_t prepare_remove(Remove& r)
|
||||||
|
{
|
||||||
|
_context_t context(*this);
|
||||||
|
serialize(r, context);
|
||||||
|
return prepare_impl(context.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PreparedRemove>
|
||||||
|
size_t run_prepared_remove(const PreparedRemove& r)
|
||||||
|
{
|
||||||
|
r._prepared_statement._reset();
|
||||||
|
r._bind_params();
|
||||||
|
return run_prepared_remove_impl(r._prepared_statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! execute arbitrary command (e.g. create a table)
|
||||||
|
size_t execute(const std::string& command);
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename Execute,
|
||||||
|
typename Enable = typename std::enable_if<not std::is_convertible<Execute, std::string>::value, void>::type>
|
||||||
|
size_t execute(const Execute& x)
|
||||||
|
{
|
||||||
|
_context_t context(*this);
|
||||||
|
serialize(x, context);
|
||||||
|
return execute(context.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Execute>
|
||||||
|
_prepared_statement_t prepare_execute(Execute& x)
|
||||||
|
{
|
||||||
|
_context_t context(*this);
|
||||||
|
serialize(x, context);
|
||||||
|
return prepare_impl(context.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PreparedExecute>
|
||||||
|
size_t run_prepared_execute(const PreparedExecute& x)
|
||||||
|
{
|
||||||
|
x._prepared_statement._reset();
|
||||||
|
x._bind_params();
|
||||||
|
return run_prepared_execute_impl(x._prepared_statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! escape given string (does not quote, though)
|
||||||
|
std::string escape(const std::string& s) const;
|
||||||
|
|
||||||
|
//! call run on the argument
|
||||||
|
template <typename T>
|
||||||
|
auto _run(const T& t, ::sqlpp::consistent_t) -> decltype(t._run(*this))
|
||||||
|
{
|
||||||
|
return t._run(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Check, typename T>
|
||||||
|
auto _run(const T& t, Check) -> Check;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto operator()(const T& t) -> decltype(this->_run(t, sqlpp::run_check_t<_serializer_context_t, T>{}))
|
||||||
|
{
|
||||||
|
return _run(t, sqlpp::run_check_t<_serializer_context_t, T>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
//! call prepare on the argument
|
||||||
|
template <typename T>
|
||||||
|
auto _prepare(const T& t, const std::true_type&) -> decltype(t._prepare(*this))
|
||||||
|
{
|
||||||
|
return t._prepare(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto _prepare(const T& t, const std::false_type&) -> void;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto prepare(const T& t)
|
||||||
|
-> decltype(this->_prepare(t, typename sqlpp::prepare_check_t<_serializer_context_t, T>::type{}))
|
||||||
|
{
|
||||||
|
sqlpp::prepare_check_t<_serializer_context_t, T>{};
|
||||||
|
return _prepare(t, sqlpp::prepare_check_t<_serializer_context_t, T>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
//! set the transaction isolation level for this connection
|
||||||
|
void set_default_isolation_level(isolation_level level);
|
||||||
|
|
||||||
|
//! get the currently active transaction isolation level
|
||||||
|
isolation_level get_default_isolation_level();
|
||||||
|
|
||||||
|
//! start transaction
|
||||||
|
void start_transaction();
|
||||||
|
|
||||||
|
//! commit transaction (or throw if the transaction has been finished already)
|
||||||
|
void commit_transaction();
|
||||||
|
|
||||||
|
//! rollback transaction with or without reporting the rollback (or throw if the transaction has been finished
|
||||||
|
// already)
|
||||||
|
void rollback_transaction(bool report);
|
||||||
|
|
||||||
|
//! report a rollback failure (will be called by transactions in case of a rollback failure in the destructor)
|
||||||
|
void report_rollback_failure(const std::string message) noexcept;
|
||||||
|
|
||||||
|
//! get the last inserted id
|
||||||
|
uint64_t last_insert_id() noexcept;
|
||||||
|
|
||||||
|
::sqlite3* native_handle();
|
||||||
|
|
||||||
|
auto attach(const connection_config&, const std::string name) -> schema_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::string serializer_t::escape(std::string arg)
|
||||||
|
{
|
||||||
|
return _db.escape(arg);
|
||||||
|
}
|
||||||
|
} // namespace sqlite3
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sqlpp11/sqlite3/serializer.h>
|
||||||
|
|
||||||
|
#endif
|
71
include/sqlpp11/sqlite3/connection_config.h
Normal file
71
include/sqlpp11/sqlite3/connection_config.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_SQLITE3_CONNECTION_CONFIG_H
|
||||||
|
#define SQLPP_SQLITE3_CONNECTION_CONFIG_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
struct connection_config
|
||||||
|
{
|
||||||
|
connection_config() : path_to_database(), flags(0), vfs(), debug(false),password("")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
connection_config(const connection_config&) = default;
|
||||||
|
connection_config(connection_config&&) = default;
|
||||||
|
|
||||||
|
connection_config(std::string path, int fl = 0, std::string vf = "", bool dbg = false,std::string password="")
|
||||||
|
: path_to_database(std::move(path)), flags(fl), vfs(std::move(vf)), debug(dbg),password(password)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const connection_config& other) const
|
||||||
|
{
|
||||||
|
return (other.path_to_database == path_to_database && other.flags == flags && other.vfs == vfs &&
|
||||||
|
other.debug == debug && other.password==password);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const connection_config& other) const
|
||||||
|
{
|
||||||
|
return !operator==(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string path_to_database;
|
||||||
|
int flags;
|
||||||
|
std::string vfs;
|
||||||
|
bool debug;
|
||||||
|
std::string password;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
237
include/sqlpp11/sqlite3/dynamic_libsqlite3.h
Normal file
237
include/sqlpp11/sqlite3/dynamic_libsqlite3.h
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Volker Aßmann
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#ifndef DYNAMIC_LIBSQLITE3_H
|
||||||
|
#define DYNAMIC_LIBSQLITE3_H
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
// namespace for internal sqlite function wrappers - when using this instead of sqlite3 direct linking
|
||||||
|
// do this:
|
||||||
|
// using namespace sqlpp::sqlite3::dyn;
|
||||||
|
// to override the libsqlite3 functions with these function pointers
|
||||||
|
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
namespace dynamic
|
||||||
|
{
|
||||||
|
/// load the SQLite libraries, optionally providing the filename (leave empty for default)
|
||||||
|
void init_sqlite(std::string libname);
|
||||||
|
|
||||||
|
#define DYNDEFINE(NAME) extern decltype(::NAME)* NAME
|
||||||
|
|
||||||
|
DYNDEFINE(sqlite3_open_v2);
|
||||||
|
DYNDEFINE(sqlite3_open);
|
||||||
|
DYNDEFINE(sqlite3_prepare_v2);
|
||||||
|
DYNDEFINE(sqlite3_exec);
|
||||||
|
DYNDEFINE(sqlite3_step);
|
||||||
|
DYNDEFINE(sqlite3_bind_int);
|
||||||
|
DYNDEFINE(sqlite3_close);
|
||||||
|
DYNDEFINE(sqlite3_initialize);
|
||||||
|
DYNDEFINE(sqlite3_os_init);
|
||||||
|
DYNDEFINE(sqlite3_os_end);
|
||||||
|
DYNDEFINE(sqlite3_bind_blob);
|
||||||
|
DYNDEFINE(sqlite3_bind_double);
|
||||||
|
DYNDEFINE(sqlite3_bind_int64);
|
||||||
|
DYNDEFINE(sqlite3_bind_null);
|
||||||
|
DYNDEFINE(sqlite3_bind_text);
|
||||||
|
DYNDEFINE(sqlite3_bind_value);
|
||||||
|
DYNDEFINE(sqlite3_libversion_number);
|
||||||
|
// DYNDEFINE(sqlite3_compileoption_used);
|
||||||
|
DYNDEFINE(sqlite3_threadsafe);
|
||||||
|
// DYNDEFINE(sqlite3_close_v2);
|
||||||
|
DYNDEFINE(sqlite3_shutdown);
|
||||||
|
DYNDEFINE(sqlite3_config);
|
||||||
|
DYNDEFINE(sqlite3_db_config);
|
||||||
|
DYNDEFINE(sqlite3_extended_result_codes);
|
||||||
|
DYNDEFINE(sqlite3_last_insert_rowid);
|
||||||
|
DYNDEFINE(sqlite3_changes);
|
||||||
|
DYNDEFINE(sqlite3_total_changes);
|
||||||
|
DYNDEFINE(sqlite3_interrupt);
|
||||||
|
DYNDEFINE(sqlite3_complete);
|
||||||
|
DYNDEFINE(sqlite3_complete16);
|
||||||
|
DYNDEFINE(sqlite3_busy_handler);
|
||||||
|
DYNDEFINE(sqlite3_busy_timeout);
|
||||||
|
DYNDEFINE(sqlite3_get_table);
|
||||||
|
DYNDEFINE(sqlite3_free_table);
|
||||||
|
// DYNDEFINE(sqlite3_realloc64);
|
||||||
|
DYNDEFINE(sqlite3_free);
|
||||||
|
// DYNDEFINE(sqlite3_msize);
|
||||||
|
DYNDEFINE(sqlite3_memory_used);
|
||||||
|
DYNDEFINE(sqlite3_memory_highwater);
|
||||||
|
DYNDEFINE(sqlite3_randomness);
|
||||||
|
DYNDEFINE(sqlite3_set_authorizer);
|
||||||
|
DYNDEFINE(sqlite3_progress_handler);
|
||||||
|
DYNDEFINE(sqlite3_open16);
|
||||||
|
// DYNDEFINE(sqlite3_uri_boolean);
|
||||||
|
// DYNDEFINE(sqlite3_uri_int64);
|
||||||
|
DYNDEFINE(sqlite3_errcode);
|
||||||
|
DYNDEFINE(sqlite3_errmsg);
|
||||||
|
DYNDEFINE(sqlite3_extended_errcode);
|
||||||
|
DYNDEFINE(sqlite3_limit);
|
||||||
|
DYNDEFINE(sqlite3_prepare);
|
||||||
|
DYNDEFINE(sqlite3_prepare16);
|
||||||
|
DYNDEFINE(sqlite3_prepare16_v2);
|
||||||
|
// DYNDEFINE(sqlite3_stmt_readonly);
|
||||||
|
// DYNDEFINE(sqlite3_stmt_busy);
|
||||||
|
// DYNDEFINE(sqlite3_bind_blob64);
|
||||||
|
DYNDEFINE(sqlite3_bind_text16);
|
||||||
|
// DYNDEFINE(sqlite3_bind_text64);
|
||||||
|
DYNDEFINE(sqlite3_bind_zeroblob);
|
||||||
|
DYNDEFINE(sqlite3_bind_parameter_count);
|
||||||
|
DYNDEFINE(sqlite3_bind_parameter_index);
|
||||||
|
DYNDEFINE(sqlite3_clear_bindings);
|
||||||
|
DYNDEFINE(sqlite3_column_count);
|
||||||
|
DYNDEFINE(sqlite3_data_count);
|
||||||
|
DYNDEFINE(sqlite3_column_bytes);
|
||||||
|
DYNDEFINE(sqlite3_column_bytes16);
|
||||||
|
DYNDEFINE(sqlite3_column_double);
|
||||||
|
DYNDEFINE(sqlite3_column_int);
|
||||||
|
DYNDEFINE(sqlite3_column_int64);
|
||||||
|
DYNDEFINE(sqlite3_column_text);
|
||||||
|
DYNDEFINE(sqlite3_column_type);
|
||||||
|
DYNDEFINE(sqlite3_column_value);
|
||||||
|
DYNDEFINE(sqlite3_column_blob);
|
||||||
|
DYNDEFINE(sqlite3_finalize);
|
||||||
|
DYNDEFINE(sqlite3_reset);
|
||||||
|
DYNDEFINE(sqlite3_create_function);
|
||||||
|
DYNDEFINE(sqlite3_create_function16);
|
||||||
|
// DYNDEFINE(sqlite3_create_function_v2);
|
||||||
|
DYNDEFINE(sqlite3_value_bytes);
|
||||||
|
DYNDEFINE(sqlite3_value_bytes16);
|
||||||
|
DYNDEFINE(sqlite3_value_double);
|
||||||
|
DYNDEFINE(sqlite3_value_int);
|
||||||
|
DYNDEFINE(sqlite3_value_int64);
|
||||||
|
DYNDEFINE(sqlite3_value_type);
|
||||||
|
DYNDEFINE(sqlite3_value_numeric_type);
|
||||||
|
DYNDEFINE(sqlite3_set_auxdata);
|
||||||
|
DYNDEFINE(sqlite3_result_blob);
|
||||||
|
// DYNDEFINE(sqlite3_result_blob64);
|
||||||
|
DYNDEFINE(sqlite3_result_double);
|
||||||
|
DYNDEFINE(sqlite3_result_error);
|
||||||
|
DYNDEFINE(sqlite3_result_error16);
|
||||||
|
DYNDEFINE(sqlite3_result_error_toobig);
|
||||||
|
DYNDEFINE(sqlite3_result_error_nomem);
|
||||||
|
DYNDEFINE(sqlite3_result_error_code);
|
||||||
|
DYNDEFINE(sqlite3_result_int);
|
||||||
|
DYNDEFINE(sqlite3_result_int64);
|
||||||
|
DYNDEFINE(sqlite3_result_null);
|
||||||
|
DYNDEFINE(sqlite3_result_text);
|
||||||
|
// DYNDEFINE(sqlite3_result_text64);
|
||||||
|
DYNDEFINE(sqlite3_result_text16);
|
||||||
|
DYNDEFINE(sqlite3_result_text16le);
|
||||||
|
DYNDEFINE(sqlite3_result_text16be);
|
||||||
|
DYNDEFINE(sqlite3_result_value);
|
||||||
|
DYNDEFINE(sqlite3_result_zeroblob);
|
||||||
|
DYNDEFINE(sqlite3_create_collation);
|
||||||
|
DYNDEFINE(sqlite3_create_collation_v2);
|
||||||
|
DYNDEFINE(sqlite3_create_collation16);
|
||||||
|
DYNDEFINE(sqlite3_collation_needed);
|
||||||
|
DYNDEFINE(sqlite3_collation_needed16);
|
||||||
|
|
||||||
|
#ifdef SQLITE_HAS_CODEC
|
||||||
|
|
||||||
|
DYNDEFINE(sqlite3_key);
|
||||||
|
DYNDEFINE(sqlite3_key_v2);
|
||||||
|
DYNDEFINE(sqlite3_rekey);
|
||||||
|
DYNDEFINE(sqlite3_rekey_v2);
|
||||||
|
DYNDEFINE(sqlite3_activate_see);
|
||||||
|
#endif
|
||||||
|
#ifdef SQLITE_ENABLE_CEROD
|
||||||
|
DYNDEFINE(sqlite3_activate_cerod);
|
||||||
|
#endif
|
||||||
|
DYNDEFINE(sqlite3_sleep);
|
||||||
|
DYNDEFINE(sqlite3_get_autocommit);
|
||||||
|
// DYNDEFINE(sqlite3_db_readonly);
|
||||||
|
DYNDEFINE(sqlite3_next_stmt);
|
||||||
|
DYNDEFINE(sqlite3_enable_shared_cache);
|
||||||
|
DYNDEFINE(sqlite3_release_memory);
|
||||||
|
// DYNDEFINE(sqlite3_db_release_memory);
|
||||||
|
// DYNDEFINE(sqlite3_soft_heap_limit64);
|
||||||
|
DYNDEFINE(sqlite3_table_column_metadata);
|
||||||
|
DYNDEFINE(sqlite3_load_extension);
|
||||||
|
DYNDEFINE(sqlite3_enable_load_extension);
|
||||||
|
DYNDEFINE(sqlite3_auto_extension);
|
||||||
|
// DYNDEFINE(sqlite3_cancel_auto_extension);
|
||||||
|
DYNDEFINE(sqlite3_reset_auto_extension);
|
||||||
|
DYNDEFINE(sqlite3_create_module);
|
||||||
|
DYNDEFINE(sqlite3_create_module_v2);
|
||||||
|
DYNDEFINE(sqlite3_declare_vtab);
|
||||||
|
DYNDEFINE(sqlite3_overload_function);
|
||||||
|
DYNDEFINE(sqlite3_blob_open);
|
||||||
|
DYNDEFINE(sqlite3_blob_close);
|
||||||
|
DYNDEFINE(sqlite3_blob_bytes);
|
||||||
|
DYNDEFINE(sqlite3_blob_read);
|
||||||
|
DYNDEFINE(sqlite3_blob_write);
|
||||||
|
DYNDEFINE(sqlite3_vfs_find);
|
||||||
|
DYNDEFINE(sqlite3_vfs_register);
|
||||||
|
DYNDEFINE(sqlite3_vfs_unregister);
|
||||||
|
DYNDEFINE(sqlite3_mutex_alloc);
|
||||||
|
DYNDEFINE(sqlite3_mutex_free);
|
||||||
|
DYNDEFINE(sqlite3_mutex_enter);
|
||||||
|
DYNDEFINE(sqlite3_mutex_try);
|
||||||
|
DYNDEFINE(sqlite3_mutex_leave);
|
||||||
|
// DYNDEFINE(sqlite3_mutex_held);
|
||||||
|
// DYNDEFINE(sqlite3_mutex_notheld);
|
||||||
|
DYNDEFINE(sqlite3_db_mutex);
|
||||||
|
DYNDEFINE(sqlite3_file_control);
|
||||||
|
DYNDEFINE(sqlite3_test_control);
|
||||||
|
DYNDEFINE(sqlite3_status);
|
||||||
|
DYNDEFINE(sqlite3_db_status);
|
||||||
|
DYNDEFINE(sqlite3_stmt_status);
|
||||||
|
DYNDEFINE(sqlite3_backup_init);
|
||||||
|
DYNDEFINE(sqlite3_backup_step);
|
||||||
|
DYNDEFINE(sqlite3_backup_finish);
|
||||||
|
DYNDEFINE(sqlite3_backup_remaining);
|
||||||
|
DYNDEFINE(sqlite3_backup_pagecount);
|
||||||
|
DYNDEFINE(sqlite3_unlock_notify);
|
||||||
|
// DYNDEFINE(sqlite3_stricmp);
|
||||||
|
// DYNDEFINE(sqlite3_strnicmp);
|
||||||
|
// DYNDEFINE(sqlite3_strglob);
|
||||||
|
// DYNDEFINE(sqlite3_log);
|
||||||
|
// DYNDEFINE(sqlite3_wal_autocheckpoint);
|
||||||
|
// DYNDEFINE(sqlite3_wal_checkpoint);
|
||||||
|
// DYNDEFINE(sqlite3_wal_checkpoint_v2);
|
||||||
|
// DYNDEFINE(sqlite3_vtab_config);
|
||||||
|
// DYNDEFINE(sqlite3_vtab_on_conflict);
|
||||||
|
// DYNDEFINE(sqlite3_rtree_geometry_callback);
|
||||||
|
// DYNDEFINE(sqlite3_rtree_query_callback);
|
||||||
|
} // namespace dynamic
|
||||||
|
} // namespace sqlite3
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#undef DYNDEFINE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif // DYNAMIC_LIBSQLITE3_H
|
18
include/sqlpp11/sqlite3/export.h
Normal file
18
include/sqlpp11/sqlite3/export.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef SQLPP_SQLITE3_EXPORT_H
|
||||||
|
#define SQLPP_SQLITE3_EXPORT_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef SQLPP11_SHARED
|
||||||
|
#ifdef SQLPP11_COMPILING_DLL
|
||||||
|
#define SQLPP11_SQLITE3_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define SQLPP11_SQLITE3_EXPORT __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define SQLPP11_SQLITE3_EXPORT
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define SQLPP11_SQLITE3_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
154
include/sqlpp11/sqlite3/insert_or.h
Normal file
154
include/sqlpp11/sqlite3/insert_or.h
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2015, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_SQLITE3_INSERT_OR_H
|
||||||
|
#define SQLPP_SQLITE3_INSERT_OR_H
|
||||||
|
|
||||||
|
#include <sqlpp11/default_value.h>
|
||||||
|
#include <sqlpp11/insert_value_list.h>
|
||||||
|
#include <sqlpp11/into.h>
|
||||||
|
#include <sqlpp11/noop.h>
|
||||||
|
#include <sqlpp11/parameter_list.h>
|
||||||
|
#include <sqlpp11/prepared_insert.h>
|
||||||
|
#include <sqlpp11/statement.h>
|
||||||
|
#include <sqlpp11/type_traits.h>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
struct insert_or_replace_name_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
struct insert_or_ignore_name_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename InsertOrAlternative>
|
||||||
|
struct insert_or_t : public statement_name_t<InsertOrAlternative>
|
||||||
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_return_value>;
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Statement>
|
||||||
|
struct _result_methods_t
|
||||||
|
{
|
||||||
|
using _statement_t = Statement;
|
||||||
|
|
||||||
|
const _statement_t& _get_statement() const
|
||||||
|
{
|
||||||
|
return static_cast<const _statement_t&>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Db>
|
||||||
|
auto _run(Db& db) const -> decltype(db.insert(this->_get_statement()))
|
||||||
|
{
|
||||||
|
return db.insert(_get_statement());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Db>
|
||||||
|
auto _prepare(Db& db) const -> prepared_insert_t<Db, _statement_t>
|
||||||
|
{
|
||||||
|
return {{}, db.prepare_insert(_get_statement())};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Database, typename InsertOrAlternative>
|
||||||
|
using blank_insert_or_t =
|
||||||
|
statement_t<Database, insert_or_t<InsertOrAlternative>, no_into_t, no_insert_value_list_t>;
|
||||||
|
|
||||||
|
template <typename Database>
|
||||||
|
using blank_insert_or_replace_t = blank_insert_or_t<Database, insert_or_replace_name_t>;
|
||||||
|
|
||||||
|
template <typename Database>
|
||||||
|
using blank_insert_or_ignore_t = blank_insert_or_t<Database, insert_or_ignore_name_t>;
|
||||||
|
|
||||||
|
inline auto insert_or_replace() -> blank_insert_or_replace_t<void>
|
||||||
|
{
|
||||||
|
return {blank_insert_or_replace_t<void>()};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Table>
|
||||||
|
constexpr auto insert_or_replace_into(Table table) -> decltype(blank_insert_or_replace_t<void>().into(table))
|
||||||
|
{
|
||||||
|
return {blank_insert_or_replace_t<void>().into(table)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Database>
|
||||||
|
constexpr auto dynamic_insert_or_replace(const Database&) -> decltype(blank_insert_or_replace_t<Database>())
|
||||||
|
{
|
||||||
|
return {blank_insert_or_replace_t<Database>()};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Database, typename Table>
|
||||||
|
constexpr auto dynamic_insert_or_replace_into(const Database&, Table table)
|
||||||
|
-> decltype(blank_insert_or_replace_t<Database>().into(table))
|
||||||
|
{
|
||||||
|
return {blank_insert_or_replace_t<Database>().into(table)};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto insert_or_ignore() -> blank_insert_or_ignore_t<void>
|
||||||
|
{
|
||||||
|
return {blank_insert_or_ignore_t<void>()};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Table>
|
||||||
|
constexpr auto insert_or_ignore_into(Table table) -> decltype(blank_insert_or_ignore_t<void>().into(table))
|
||||||
|
{
|
||||||
|
return {blank_insert_or_ignore_t<void>().into(table)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Database>
|
||||||
|
constexpr auto dynamic_insert_or_ignore(const Database&) -> decltype(blank_insert_or_ignore_t<Database>())
|
||||||
|
{
|
||||||
|
return {blank_insert_or_ignore_t<Database>()};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Database, typename Table>
|
||||||
|
constexpr auto dynamic_insert_or_ignore_into(const Database&, Table table)
|
||||||
|
-> decltype(blank_insert_or_ignore_t<Database>().into(table))
|
||||||
|
{
|
||||||
|
return {blank_insert_or_ignore_t<Database>().into(table)};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sqlite3::serializer_t& serialize(const sqlite3::insert_or_replace_name_t&, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
context << "INSERT OR REPLACE ";
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sqlite3::serializer_t& serialize(const sqlite3::insert_or_ignore_name_t&, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
context << "INSERT OR IGNORE ";
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
88
include/sqlpp11/sqlite3/prepared_statement.h
Normal file
88
include/sqlpp11/sqlite3/prepared_statement.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2015, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_SQLITE3_PREPARED_STATEMENT_H
|
||||||
|
#define SQLPP_SQLITE3_PREPARED_STATEMENT_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <sqlpp11/chrono.h>
|
||||||
|
#include <sqlpp11/sqlite3/export.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
class connection;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct prepared_statement_handle_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SQLPP11_SQLITE3_EXPORT prepared_statement_t
|
||||||
|
{
|
||||||
|
friend ::sqlpp::sqlite3::connection;
|
||||||
|
std::shared_ptr<detail::prepared_statement_handle_t> _handle;
|
||||||
|
|
||||||
|
public:
|
||||||
|
prepared_statement_t() = default;
|
||||||
|
prepared_statement_t(std::shared_ptr<detail::prepared_statement_handle_t>&& handle);
|
||||||
|
prepared_statement_t(const prepared_statement_t&) = delete;
|
||||||
|
prepared_statement_t(prepared_statement_t&& rhs) = default;
|
||||||
|
prepared_statement_t& operator=(const prepared_statement_t&) = delete;
|
||||||
|
prepared_statement_t& operator=(prepared_statement_t&&) = default;
|
||||||
|
~prepared_statement_t() = default;
|
||||||
|
|
||||||
|
bool operator==(const prepared_statement_t& rhs) const
|
||||||
|
{
|
||||||
|
return _handle == rhs._handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _reset();
|
||||||
|
void _bind_boolean_parameter(size_t index, const signed char* value, bool is_null);
|
||||||
|
void _bind_floating_point_parameter(size_t index, const double* value, bool is_null);
|
||||||
|
void _bind_integral_parameter(size_t index, const int64_t* value, bool is_null);
|
||||||
|
void _bind_unsigned_integral_parameter(size_t index, const uint64_t* value, bool is_null);
|
||||||
|
void _bind_text_parameter(size_t index, const std::string* value, bool is_null);
|
||||||
|
void _bind_date_parameter(size_t index, const ::sqlpp::chrono::day_point* value, bool is_null);
|
||||||
|
void _bind_date_time_parameter(size_t index, const ::sqlpp::chrono::microsecond_point* value, bool is_null);
|
||||||
|
void _bind_blob_parameter(size_t index, const std::vector<uint8_t>* value, bool is_null);
|
||||||
|
};
|
||||||
|
} // namespace sqlite3
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
140
include/sqlpp11/sqlite3/serializer.h
Normal file
140
include/sqlpp11/sqlite3/serializer.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_SQLITE3_SERIALIZER_H
|
||||||
|
#define SQLPP_SQLITE3_SERIALIZER_H
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <sqlpp11/any.h>
|
||||||
|
#include <sqlpp11/data_types/day_point/operand.h>
|
||||||
|
#include <sqlpp11/data_types/floating_point/operand.h>
|
||||||
|
#include <sqlpp11/data_types/integral/operand.h>
|
||||||
|
#include <sqlpp11/data_types/time_point/operand.h>
|
||||||
|
#include <sqlpp11/data_types/unsigned_integral/operand.h>
|
||||||
|
#include <sqlpp11/parameter.h>
|
||||||
|
#include <sqlpp11/pre_join.h>
|
||||||
|
#include <sqlpp11/some.h>
|
||||||
|
#include <sqlpp11/with.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
// Serialize parameters
|
||||||
|
template <typename ValueType, typename NameType>
|
||||||
|
sqlite3::serializer_t& serialize(const parameter_t<ValueType, NameType>&, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
context << "?" << context.count();
|
||||||
|
context.pop_count();
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable some stuff that won't work with sqlite3
|
||||||
|
#if SQLITE_VERSION_NUMBER < 3008003
|
||||||
|
template <typename Database, typename... Expressions>
|
||||||
|
sqlite3::serializer_t& serialize(const with_data_t<Database, Expressions...>&, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<Expressions...>::value, "Sqlite3: No support for with before version 3.8.3");
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename Select>
|
||||||
|
sqlite3::serializer_t& serialize(const any_t<Select>&, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<Select>::value, "Sqlite3: No support for any()");
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Select>
|
||||||
|
sqlite3::serializer_t& serialize(const some_t<Select>&, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<Select>::value, "Sqlite3: No support for some()");
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Lhs, typename Rhs>
|
||||||
|
sqlite3::serializer_t& serialize(const pre_join_t<outer_join_t, Lhs, Rhs>&, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<Lhs, Rhs>::value, "Sqlite3: No support for outer join");
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Lhs, typename Rhs>
|
||||||
|
sqlite3::serializer_t& serialize(const pre_join_t<right_outer_join_t, Lhs, Rhs>&, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<Lhs, Rhs>::value, "Sqlite3: No support for right_outer join");
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Some special treatment of data types
|
||||||
|
template <typename Period>
|
||||||
|
sqlite3::serializer_t& serialize(const time_point_operand<Period>& t, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
const auto dp = ::sqlpp::chrono::floor<::date::days>(t._t);
|
||||||
|
const auto time = ::date::make_time(t._t - dp);
|
||||||
|
const auto ymd = ::date::year_month_day{dp};
|
||||||
|
context << "STRFTIME('%Y-%m-%d %H:%M:%f', '" << ymd << ' ' << time << "')";
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sqlite3::serializer_t& serialize(const day_point_operand& t, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
const auto ymd = ::date::year_month_day{t._t};
|
||||||
|
context << "DATE('" << ymd << "')";
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline sqlite3::serializer_t& serialize(const floating_point_operand& t, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
if (std::isnan(t._t))
|
||||||
|
context << "'NaN'";
|
||||||
|
else if (std::isinf(t._t))
|
||||||
|
{
|
||||||
|
if (t._t > std::numeric_limits<double>::max())
|
||||||
|
context << "'Inf'";
|
||||||
|
else
|
||||||
|
context << "'-Inf'";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
context << t._t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sqlite3 accepts only signed integers,
|
||||||
|
// so we MUST perform a conversion from unsigned to signed
|
||||||
|
inline sqlite3::serializer_t& serialize(const unsigned_integral_operand& t, sqlite3::serializer_t& context)
|
||||||
|
{
|
||||||
|
context << static_cast<typename integral_operand::_value_t>(t._t);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
33
include/sqlpp11/sqlite3/sqlite3.h
Normal file
33
include/sqlpp11/sqlite3/sqlite3.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2015, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_SQLITE3_H
|
||||||
|
#define SQLPP_SQLITE3_H
|
||||||
|
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
#include <sqlpp11/sqlite3/insert_or.h>
|
||||||
|
|
||||||
|
#endif
|
35
src/CMakeLists.txt
Normal file
35
src/CMakeLists.txt
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Copyright (c) 2021-2021, Roland Bock
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
# other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
if(MYSQL_CONNECTOR)
|
||||||
|
add_subdirectory(mysql)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(POSTGRESQL_CONNECTOR)
|
||||||
|
add_subdirectory(postgresql)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SQLITE3_CONNECTOR OR SQLCIPHER_CONNECTOR)
|
||||||
|
add_subdirectory(sqlite3)
|
||||||
|
endif()
|
||||||
|
|
96
src/sqlite3/CMakeLists.txt
Normal file
96
src/sqlite3/CMakeLists.txt
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
# Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
# other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||||
|
|
||||||
|
add_library(sqlpp11-connector-sqlite3)
|
||||||
|
add_library(sqlpp11::sqlite3 ALIAS sqlpp11-connector-sqlite3)
|
||||||
|
|
||||||
|
target_sources(sqlpp11-connector-sqlite3
|
||||||
|
PRIVATE
|
||||||
|
connection.cpp
|
||||||
|
bind_result.cpp
|
||||||
|
prepared_statement.cpp
|
||||||
|
detail/connection_handle.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(sqlpp11-connector-sqlite3 PUBLIC sqlpp11::sqlpp11)
|
||||||
|
|
||||||
|
if (SQLPP_DYNAMIC_LOADING)
|
||||||
|
add_library(sqlpp11-connector-sqlite3-dynamic
|
||||||
|
connection.cpp
|
||||||
|
bind_result.cpp
|
||||||
|
prepared_statement.cpp
|
||||||
|
detail/connection_handle.cpp
|
||||||
|
detail/dynamic_libsqlite3.cpp
|
||||||
|
)
|
||||||
|
add_library(sqlpp11::sqlite3-dynamic ALIAS sqlpp11-connector-sqlite3-dynamic)
|
||||||
|
|
||||||
|
get_filename_component(SQLite3_LIB_FILE ${SQLite3_LIBRARY} NAME)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
# the import library (.lib) needs to be replaced by .dll
|
||||||
|
get_filename_component(SQLite3_LIB_FILE ${SQLite3_LIB_FILE} NAME_WE)
|
||||||
|
string(APPEND SQLite3_LIB_FILE ".dll")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(sqlpp11-connector-sqlite3 PROPERTIES DEFINE_SYMBOL SQLPP11_COMPILING_DLL)
|
||||||
|
set_target_properties(sqlpp11-connector-sqlite3-dynamic PROPERTIES DEFINE_SYMBOL SQLPP11_COMPILING_DLL)
|
||||||
|
|
||||||
|
target_compile_definitions(sqlpp11-connector-sqlite3-dynamic
|
||||||
|
PUBLIC SQLPP_DYNAMIC_LOADING
|
||||||
|
PRIVATE SQLPP_DYNAMIC_LOADING_FILENAME=${SQLite3_LIB_FILE})
|
||||||
|
|
||||||
|
target_include_directories(sqlpp11-connector-sqlite3-dynamic PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||||
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
|
||||||
|
target_link_libraries(sqlpp11-connector-sqlite3-dynamic PUBLIC sqlpp11::sqlpp11)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(sqlpp11-connector-sqlite3 PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||||
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
|
||||||
|
if (SQLCIPHER)
|
||||||
|
target_compile_definitions(sqlpp11-connector-sqlite3 PUBLIC SQLPP_USE_SQLCIPHER)
|
||||||
|
target_link_libraries(sqlpp11-connector-sqlite3 PUBLIC SQLCipher::SQLCipher)
|
||||||
|
if (SQLPP_DYNAMIC_LOADING)
|
||||||
|
target_compile_definitions(sqlpp11-connector-sqlite3-dynamic PUBLIC SQLPP_USE_SQLCIPHER)
|
||||||
|
target_include_directories(sqlpp11-connector-sqlite3-dynamic PUBLIC ${SQLCIPHER_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
target_link_libraries(sqlpp11-connector-sqlite3 PUBLIC SQLite::SQLite3)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(TARGETS sqlpp11-connector-sqlite3
|
||||||
|
ARCHIVE DESTINATION lib
|
||||||
|
LIBRARY DESTINATION lib
|
||||||
|
RUNTIME DESTINATION bin)
|
||||||
|
|
||||||
|
if (SQLPP_DYNAMIC_LOADING)
|
||||||
|
install(TARGETS sqlpp11-connector-sqlite3-dynamic
|
||||||
|
ARCHIVE DESTINATION lib
|
||||||
|
LIBRARY DESTINATION lib
|
||||||
|
RUNTIME DESTINATION bin)
|
||||||
|
endif()
|
249
src/sqlite3/bind_result.cpp
Normal file
249
src/sqlite3/bind_result.cpp
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "detail/prepared_statement_handle.h"
|
||||||
|
#include <cctype>
|
||||||
|
#include <ciso646>
|
||||||
|
#include <date/date.h> // Howard Hinnant's date library
|
||||||
|
#include <iostream>
|
||||||
|
#include <sqlpp11/exception.h>
|
||||||
|
#include <sqlpp11/sqlite3/bind_result.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
#include <sqlpp11/sqlite3/dynamic_libsqlite3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
using namespace dynamic;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bind_result_t::bind_result_t(const std::shared_ptr<detail::prepared_statement_handle_t>& handle) : _handle(handle)
|
||||||
|
{
|
||||||
|
if (_handle and _handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: Constructing bind result, using handle at " << _handle.get() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_result_t::_bind_boolean_result(size_t index, signed char* value, bool* is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding boolean result " << *value << " at index: " << index << std::endl;
|
||||||
|
|
||||||
|
*value = static_cast<signed char>(sqlite3_column_int(_handle->sqlite_statement, static_cast<int>(index)));
|
||||||
|
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_result_t::_bind_floating_point_result(size_t index, double* value, bool* is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding floating_point result " << *value << " at index: " << index << std::endl;
|
||||||
|
|
||||||
|
switch (sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)))
|
||||||
|
{
|
||||||
|
case (SQLITE3_TEXT):
|
||||||
|
*value = atof(
|
||||||
|
reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index))));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*value = sqlite3_column_double(_handle->sqlite_statement, static_cast<int>(index));
|
||||||
|
}
|
||||||
|
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_result_t::_bind_integral_result(size_t index, int64_t* value, bool* is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding integral result " << *value << " at index: " << index << std::endl;
|
||||||
|
|
||||||
|
*value = sqlite3_column_int64(_handle->sqlite_statement, static_cast<int>(index));
|
||||||
|
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_result_t::_bind_unsigned_integral_result(size_t index, uint64_t* value, bool* is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding unsigned integral result " << *value << " at index: " << index
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
*value = static_cast<uint64_t>(sqlite3_column_int64(_handle->sqlite_statement, static_cast<int>(index)));
|
||||||
|
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_result_t::_bind_text_result(size_t index, const char** value, size_t* len)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding text result at index: " << index << std::endl;
|
||||||
|
|
||||||
|
*value = (reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index))));
|
||||||
|
*len = sqlite3_column_bytes(_handle->sqlite_statement, static_cast<int>(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_result_t::_bind_blob_result(size_t index, const uint8_t** value, size_t* len)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding text result at index: " << index << std::endl;
|
||||||
|
|
||||||
|
*value =
|
||||||
|
(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(_handle->sqlite_statement, static_cast<int>(index))));
|
||||||
|
*len = sqlite3_column_bytes(_handle->sqlite_statement, static_cast<int>(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const auto date_digits = std::vector<char>{1, 1, 1, 1, 0, 1, 1, 0, 1, 1}; // 2015-10-28
|
||||||
|
const auto time_digits = std::vector<char>{0, 1, 1, 0, 1, 1, 0, 1, 1}; // T23:00:12
|
||||||
|
const auto ms_digits = std::vector<char>{0, 1, 1, 1}; // .123
|
||||||
|
|
||||||
|
auto check_digits(const char* text, const std::vector<char>& digitFlags) -> bool
|
||||||
|
{
|
||||||
|
for (const auto digitFlag : digitFlags)
|
||||||
|
{
|
||||||
|
if (digitFlag)
|
||||||
|
{
|
||||||
|
if (not std::isdigit(*text))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (std::isdigit(*text) or *text == '\0')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++text;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void bind_result_t::_bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding date result at index: " << index << std::endl;
|
||||||
|
|
||||||
|
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
||||||
|
if (*is_null)
|
||||||
|
{
|
||||||
|
*value = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto date_string =
|
||||||
|
reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index)));
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: date string: " << date_string << std::endl;
|
||||||
|
|
||||||
|
if (check_digits(date_string, date_digits))
|
||||||
|
{
|
||||||
|
const auto ymd = ::date::year(std::atoi(date_string)) / atoi(date_string + 5) / atoi(date_string + 8);
|
||||||
|
*value = ::sqlpp::chrono::day_point(ymd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: invalid date result: " << date_string << std::endl;
|
||||||
|
*value = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_result_t::_bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding date result at index: " << index << std::endl;
|
||||||
|
|
||||||
|
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
||||||
|
if (*is_null)
|
||||||
|
{
|
||||||
|
*value = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto date_time_string =
|
||||||
|
reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index)));
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: date_time string: " << date_time_string << std::endl;
|
||||||
|
|
||||||
|
if (check_digits(date_time_string, date_digits))
|
||||||
|
{
|
||||||
|
const auto ymd =
|
||||||
|
::date::year(std::atoi(date_time_string)) / atoi(date_time_string + 5) / atoi(date_time_string + 8);
|
||||||
|
*value = ::sqlpp::chrono::day_point(ymd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: invalid date_time result: " << date_time_string << std::endl;
|
||||||
|
*value = {};
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto time_string = date_time_string + 10;
|
||||||
|
if (check_digits(time_string, time_digits))
|
||||||
|
{
|
||||||
|
*value += ::std::chrono::hours(std::atoi(time_string + 1)) + std::chrono::minutes(std::atoi(time_string + 4)) +
|
||||||
|
std::chrono::seconds(std::atoi(time_string + 7));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto ms_string = time_string + 9;
|
||||||
|
if (check_digits(ms_string, ms_digits) and ms_string[4] == '\0')
|
||||||
|
{
|
||||||
|
*value += ::std::chrono::milliseconds(std::atoi(ms_string + 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bind_result_t::next_impl()
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: Accessing next row of handle at " << _handle.get() << std::endl;
|
||||||
|
|
||||||
|
auto rc = sqlite3_step(_handle->sqlite_statement);
|
||||||
|
|
||||||
|
switch (rc)
|
||||||
|
{
|
||||||
|
case SQLITE_ROW:
|
||||||
|
return true;
|
||||||
|
case SQLITE_DONE:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
throw sqlpp::exception("Sqlite3 error: Unexpected return value for sqlite3_step()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace sqlite3
|
||||||
|
} // namespace sqlpp
|
280
src/sqlite3/connection.cpp
Normal file
280
src/sqlite3/connection.cpp
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "detail/connection_handle.h"
|
||||||
|
#include "detail/prepared_statement_handle.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <sqlpp11/exception.h>
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
#include <sqlpp11/sqlite3/dynamic_libsqlite3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
using namespace dynamic;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
detail::prepared_statement_handle_t prepare_statement(detail::connection_handle& handle,
|
||||||
|
const std::string& statement)
|
||||||
|
{
|
||||||
|
if (handle.config.debug)
|
||||||
|
std::cerr << "Sqlite3 debug: Preparing: '" << statement << "'" << std::endl;
|
||||||
|
|
||||||
|
detail::prepared_statement_handle_t result(nullptr, handle.config.debug);
|
||||||
|
|
||||||
|
auto rc = sqlite3_prepare_v2(handle.sqlite, statement.c_str(), static_cast<int>(statement.size()),
|
||||||
|
&result.sqlite_statement, nullptr);
|
||||||
|
|
||||||
|
if (rc != SQLITE_OK)
|
||||||
|
{
|
||||||
|
throw sqlpp::exception("Sqlite3 error: Could not prepare statement: " +
|
||||||
|
std::string(sqlite3_errmsg(handle.sqlite)) + " (statement was >>" +
|
||||||
|
(rc == SQLITE_TOOBIG ? statement.substr(0, 128) + "..." : statement) +
|
||||||
|
"<<\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_statement(detail::connection_handle& handle, detail::prepared_statement_handle_t& prepared)
|
||||||
|
{
|
||||||
|
auto rc = sqlite3_step(prepared.sqlite_statement);
|
||||||
|
switch (rc)
|
||||||
|
{
|
||||||
|
case SQLITE_OK:
|
||||||
|
case SQLITE_ROW: // might occur if execute is called with a select
|
||||||
|
case SQLITE_DONE:
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
if(handle.config.debug)
|
||||||
|
std::cerr << "Sqlite3 debug: sqlite3_step return code: " << rc << std::endl;
|
||||||
|
throw sqlpp::exception("Sqlite3 error: Could not execute statement: " +
|
||||||
|
std::string(sqlite3_errmsg(handle.sqlite)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connection::connection(connection_config config) : _handle(new detail::connection_handle(std::move(config)))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
connection::connection(connection&&) noexcept = default;
|
||||||
|
connection& connection::operator=(connection&&) noexcept = default;
|
||||||
|
|
||||||
|
connection::~connection()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
::sqlite3* connection::native_handle()
|
||||||
|
{
|
||||||
|
return _handle->sqlite;
|
||||||
|
}
|
||||||
|
|
||||||
|
bind_result_t connection::select_impl(const std::string& statement)
|
||||||
|
{
|
||||||
|
std::unique_ptr<detail::prepared_statement_handle_t> prepared(
|
||||||
|
new detail::prepared_statement_handle_t(prepare_statement(*_handle, statement)));
|
||||||
|
if (!prepared)
|
||||||
|
{
|
||||||
|
throw sqlpp::exception("Sqlite3 error: Could not store result set");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {std::move(prepared)};
|
||||||
|
}
|
||||||
|
|
||||||
|
bind_result_t connection::run_prepared_select_impl(prepared_statement_t& prepared_statement)
|
||||||
|
{
|
||||||
|
return {prepared_statement._handle};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t connection::insert_impl(const std::string& statement)
|
||||||
|
{
|
||||||
|
auto prepared = prepare_statement(*_handle, statement);
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
|
||||||
|
return sqlite3_last_insert_rowid(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepared_statement_t connection::prepare_impl(const std::string& statement)
|
||||||
|
{
|
||||||
|
return {std::unique_ptr<detail::prepared_statement_handle_t>(
|
||||||
|
new detail::prepared_statement_handle_t(prepare_statement(*_handle, statement)))};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t connection::run_prepared_insert_impl(prepared_statement_t& prepared_statement)
|
||||||
|
{
|
||||||
|
execute_statement(*_handle, *prepared_statement._handle.get());
|
||||||
|
|
||||||
|
return sqlite3_last_insert_rowid(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t connection::run_prepared_execute_impl(prepared_statement_t& prepared_statement)
|
||||||
|
{
|
||||||
|
execute_statement(*_handle, *prepared_statement._handle.get());
|
||||||
|
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t connection::execute(const std::string& statement)
|
||||||
|
{
|
||||||
|
auto prepared = prepare_statement(*_handle, statement);
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t connection::update_impl(const std::string& statement)
|
||||||
|
{
|
||||||
|
auto prepared = prepare_statement(*_handle, statement);
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t connection::run_prepared_update_impl(prepared_statement_t& prepared_statement)
|
||||||
|
{
|
||||||
|
execute_statement(*_handle, *prepared_statement._handle.get());
|
||||||
|
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t connection::remove_impl(const std::string& statement)
|
||||||
|
{
|
||||||
|
auto prepared = prepare_statement(*_handle, statement);
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t connection::run_prepared_remove_impl(prepared_statement_t& prepared_statement)
|
||||||
|
{
|
||||||
|
execute_statement(*_handle, *prepared_statement._handle.get());
|
||||||
|
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string connection::escape(const std::string& s) const
|
||||||
|
{
|
||||||
|
std::string t;
|
||||||
|
t.reserve(s.size());
|
||||||
|
|
||||||
|
for (const char c : s)
|
||||||
|
{
|
||||||
|
if (c == '\'')
|
||||||
|
t.push_back(c);
|
||||||
|
t.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connection::set_default_isolation_level(isolation_level level)
|
||||||
|
{
|
||||||
|
if (level == sqlpp::isolation_level::read_uncommitted)
|
||||||
|
{
|
||||||
|
execute("pragma read_uncommitted = true");
|
||||||
|
} else {
|
||||||
|
execute("pragma read_uncommitted = false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlpp::isolation_level connection::get_default_isolation_level()
|
||||||
|
{
|
||||||
|
auto stmt = prepare_statement(*_handle, "pragma read_uncommitted");
|
||||||
|
execute_statement(*_handle, stmt);
|
||||||
|
|
||||||
|
int level = sqlite3_column_int(stmt.sqlite_statement, 0);
|
||||||
|
|
||||||
|
return level == 0 ? sqlpp::isolation_level::serializable :
|
||||||
|
sqlpp::isolation_level::read_uncommitted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connection::start_transaction()
|
||||||
|
{
|
||||||
|
if (_transaction_status == transaction_status_type::active)
|
||||||
|
{
|
||||||
|
throw sqlpp::exception("Sqlite3 error: Cannot have more than one open transaction per connection");
|
||||||
|
}
|
||||||
|
|
||||||
|
_transaction_status = transaction_status_type::maybe;
|
||||||
|
auto prepared = prepare_statement(*_handle, "BEGIN");
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
_transaction_status = transaction_status_type::active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connection::commit_transaction()
|
||||||
|
{
|
||||||
|
if (_transaction_status == transaction_status_type::none)
|
||||||
|
{
|
||||||
|
throw sqlpp::exception("Sqlite3 error: Cannot commit a finished or failed transaction");
|
||||||
|
}
|
||||||
|
_transaction_status = transaction_status_type::maybe;
|
||||||
|
auto prepared = prepare_statement(*_handle, "COMMIT");
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
_transaction_status = transaction_status_type::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connection::rollback_transaction(bool report)
|
||||||
|
{
|
||||||
|
if (_transaction_status == transaction_status_type::none)
|
||||||
|
{
|
||||||
|
throw sqlpp::exception("Sqlite3 error: Cannot rollback a finished or failed transaction");
|
||||||
|
}
|
||||||
|
if (report)
|
||||||
|
{
|
||||||
|
std::cerr << "Sqlite3 warning: Rolling back unfinished transaction" << std::endl;
|
||||||
|
}
|
||||||
|
_transaction_status = transaction_status_type::maybe;
|
||||||
|
auto prepared = prepare_statement(*_handle, "ROLLBACK");
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
_transaction_status = transaction_status_type::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connection::report_rollback_failure(const std::string message) noexcept
|
||||||
|
{
|
||||||
|
std::cerr << "Sqlite3 message:" << message << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t connection::last_insert_id() noexcept
|
||||||
|
{
|
||||||
|
return sqlite3_last_insert_rowid(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto connection::attach(const connection_config& config, const std::string name) -> schema_t
|
||||||
|
{
|
||||||
|
auto prepared =
|
||||||
|
prepare_statement(*_handle, "ATTACH '" + escape(config.path_to_database) + "' AS " + escape(name));
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
|
||||||
|
return {name};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
85
src/sqlite3/detail/connection_handle.cpp
Normal file
85
src/sqlite3/detail/connection_handle.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2015, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <sqlpp11/exception.h>
|
||||||
|
#include <sqlpp11/sqlite3/connection_config.h>
|
||||||
|
#include "connection_handle.h"
|
||||||
|
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
#include <sqlpp11/sqlite3/dynamic_libsqlite3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
using namespace dynamic;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
connection_handle::connection_handle(connection_config conf) : config(conf), sqlite(nullptr)
|
||||||
|
{
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
init_sqlite("");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto rc = sqlite3_open_v2(conf.path_to_database.c_str(), &sqlite, conf.flags,
|
||||||
|
conf.vfs.empty() ? nullptr : conf.vfs.c_str());
|
||||||
|
if (rc != SQLITE_OK)
|
||||||
|
{
|
||||||
|
const std::string msg = sqlite3_errmsg(sqlite);
|
||||||
|
sqlite3_close(sqlite);
|
||||||
|
throw sqlpp::exception("Sqlite3 error: Can't open database: " + msg);
|
||||||
|
}
|
||||||
|
#ifdef SQLITE_HAS_CODEC
|
||||||
|
if (conf.password.size()>0)
|
||||||
|
{
|
||||||
|
int ret = sqlite3_key(sqlite, conf.password.data(),conf.password.size());
|
||||||
|
if (ret!=SQLITE_OK)
|
||||||
|
{
|
||||||
|
const std::string msg = sqlite3_errmsg(sqlite);
|
||||||
|
sqlite3_close(sqlite);
|
||||||
|
throw sqlpp::exception("Sqlite3 error: Can't set password to database: " + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
connection_handle::~connection_handle()
|
||||||
|
{
|
||||||
|
auto rc = sqlite3_close(sqlite);
|
||||||
|
if (rc != SQLITE_OK)
|
||||||
|
{
|
||||||
|
std::cerr << "Sqlite3 error: Can't close database: " << sqlite3_errmsg(sqlite) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
src/sqlite3/detail/connection_handle.h
Normal file
61
src/sqlite3/detail/connection_handle.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_SQLITE3_CONNECTION_HANDLE_H
|
||||||
|
#define SQLPP_SQLITE3_CONNECTION_HANDLE_H
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <sqlpp11/sqlite3/connection_config.h>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
struct connection_config;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct connection_handle
|
||||||
|
{
|
||||||
|
connection_config config;
|
||||||
|
::sqlite3* sqlite;
|
||||||
|
|
||||||
|
connection_handle(connection_config config);
|
||||||
|
~connection_handle();
|
||||||
|
connection_handle(const connection_handle&) = delete;
|
||||||
|
connection_handle(connection_handle&&) = delete;
|
||||||
|
connection_handle& operator=(const connection_handle&) = delete;
|
||||||
|
connection_handle& operator=(connection_handle&&) = delete;
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace sqlite3
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#endif
|
466
src/sqlite3/detail/dynamic_libsqlite3.cpp
Normal file
466
src/sqlite3/detail/dynamic_libsqlite3.cpp
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Volker Assmann
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sqlpp11/sqlite3/dynamic_libsqlite3.h"
|
||||||
|
#include "sqlpp11/exception.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#else
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
namespace dynamic
|
||||||
|
{
|
||||||
|
#define DYNDEFINE(NAME) decltype(::NAME)* NAME
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
#define DYNLOAD(HNDL, NAME) NAME = reinterpret_cast<decltype(NAME)>(dlsym(HNDL, #NAME))
|
||||||
|
#else
|
||||||
|
#define DYNLOAD(HNDL, NAME) NAME = reinterpret_cast<decltype(NAME)>(GetProcAddress(HNDL, #NAME))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DYNDEFINE(sqlite3_open_v2);
|
||||||
|
DYNDEFINE(sqlite3_open);
|
||||||
|
DYNDEFINE(sqlite3_prepare_v2);
|
||||||
|
DYNDEFINE(sqlite3_exec);
|
||||||
|
DYNDEFINE(sqlite3_step);
|
||||||
|
DYNDEFINE(sqlite3_bind_int);
|
||||||
|
DYNDEFINE(sqlite3_close);
|
||||||
|
DYNDEFINE(sqlite3_initialize);
|
||||||
|
DYNDEFINE(sqlite3_os_init);
|
||||||
|
DYNDEFINE(sqlite3_os_end);
|
||||||
|
DYNDEFINE(sqlite3_bind_blob);
|
||||||
|
DYNDEFINE(sqlite3_bind_double);
|
||||||
|
DYNDEFINE(sqlite3_bind_int64);
|
||||||
|
DYNDEFINE(sqlite3_bind_null);
|
||||||
|
DYNDEFINE(sqlite3_bind_text);
|
||||||
|
DYNDEFINE(sqlite3_bind_value);
|
||||||
|
DYNDEFINE(sqlite3_libversion_number);
|
||||||
|
// DYNDEFINE(sqlite3_compileoption_used);
|
||||||
|
DYNDEFINE(sqlite3_threadsafe);
|
||||||
|
// DYNDEFINE(sqlite3_close_v2);
|
||||||
|
DYNDEFINE(sqlite3_shutdown);
|
||||||
|
DYNDEFINE(sqlite3_config);
|
||||||
|
DYNDEFINE(sqlite3_db_config);
|
||||||
|
DYNDEFINE(sqlite3_extended_result_codes);
|
||||||
|
DYNDEFINE(sqlite3_last_insert_rowid);
|
||||||
|
DYNDEFINE(sqlite3_changes);
|
||||||
|
DYNDEFINE(sqlite3_total_changes);
|
||||||
|
DYNDEFINE(sqlite3_interrupt);
|
||||||
|
DYNDEFINE(sqlite3_complete);
|
||||||
|
DYNDEFINE(sqlite3_complete16);
|
||||||
|
DYNDEFINE(sqlite3_busy_handler);
|
||||||
|
DYNDEFINE(sqlite3_busy_timeout);
|
||||||
|
DYNDEFINE(sqlite3_get_table);
|
||||||
|
DYNDEFINE(sqlite3_free_table);
|
||||||
|
// DYNDEFINE(sqlite3_realloc64);
|
||||||
|
DYNDEFINE(sqlite3_free);
|
||||||
|
// DYNDEFINE(sqlite3_msize);
|
||||||
|
DYNDEFINE(sqlite3_memory_used);
|
||||||
|
DYNDEFINE(sqlite3_memory_highwater);
|
||||||
|
DYNDEFINE(sqlite3_randomness);
|
||||||
|
DYNDEFINE(sqlite3_set_authorizer);
|
||||||
|
DYNDEFINE(sqlite3_progress_handler);
|
||||||
|
DYNDEFINE(sqlite3_open16);
|
||||||
|
// DYNDEFINE(sqlite3_uri_boolean);
|
||||||
|
// DYNDEFINE(sqlite3_uri_int64);
|
||||||
|
DYNDEFINE(sqlite3_errcode);
|
||||||
|
DYNDEFINE(sqlite3_errmsg);
|
||||||
|
DYNDEFINE(sqlite3_extended_errcode);
|
||||||
|
DYNDEFINE(sqlite3_limit);
|
||||||
|
DYNDEFINE(sqlite3_prepare);
|
||||||
|
DYNDEFINE(sqlite3_prepare16);
|
||||||
|
DYNDEFINE(sqlite3_prepare16_v2);
|
||||||
|
// DYNDEFINE(sqlite3_stmt_readonly);
|
||||||
|
// DYNDEFINE(sqlite3_stmt_busy);
|
||||||
|
// DYNDEFINE(sqlite3_bind_blob64);
|
||||||
|
DYNDEFINE(sqlite3_bind_text16);
|
||||||
|
// DYNDEFINE(sqlite3_bind_text64);
|
||||||
|
DYNDEFINE(sqlite3_bind_zeroblob);
|
||||||
|
DYNDEFINE(sqlite3_bind_parameter_count);
|
||||||
|
DYNDEFINE(sqlite3_bind_parameter_index);
|
||||||
|
DYNDEFINE(sqlite3_clear_bindings);
|
||||||
|
DYNDEFINE(sqlite3_column_count);
|
||||||
|
DYNDEFINE(sqlite3_data_count);
|
||||||
|
DYNDEFINE(sqlite3_column_bytes);
|
||||||
|
DYNDEFINE(sqlite3_column_bytes16);
|
||||||
|
DYNDEFINE(sqlite3_column_double);
|
||||||
|
DYNDEFINE(sqlite3_column_int);
|
||||||
|
DYNDEFINE(sqlite3_column_int64);
|
||||||
|
DYNDEFINE(sqlite3_column_text);
|
||||||
|
DYNDEFINE(sqlite3_column_type);
|
||||||
|
DYNDEFINE(sqlite3_column_value);
|
||||||
|
DYNDEFINE(sqlite3_column_blob);
|
||||||
|
DYNDEFINE(sqlite3_finalize);
|
||||||
|
DYNDEFINE(sqlite3_reset);
|
||||||
|
DYNDEFINE(sqlite3_create_function);
|
||||||
|
DYNDEFINE(sqlite3_create_function16);
|
||||||
|
// DYNDEFINE(sqlite3_create_function_v2);
|
||||||
|
DYNDEFINE(sqlite3_value_bytes);
|
||||||
|
DYNDEFINE(sqlite3_value_bytes16);
|
||||||
|
DYNDEFINE(sqlite3_value_double);
|
||||||
|
DYNDEFINE(sqlite3_value_int);
|
||||||
|
DYNDEFINE(sqlite3_value_int64);
|
||||||
|
DYNDEFINE(sqlite3_value_type);
|
||||||
|
DYNDEFINE(sqlite3_value_numeric_type);
|
||||||
|
DYNDEFINE(sqlite3_set_auxdata);
|
||||||
|
DYNDEFINE(sqlite3_result_blob);
|
||||||
|
// DYNDEFINE(sqlite3_result_blob64);
|
||||||
|
DYNDEFINE(sqlite3_result_double);
|
||||||
|
DYNDEFINE(sqlite3_result_error);
|
||||||
|
DYNDEFINE(sqlite3_result_error16);
|
||||||
|
DYNDEFINE(sqlite3_result_error_toobig);
|
||||||
|
DYNDEFINE(sqlite3_result_error_nomem);
|
||||||
|
DYNDEFINE(sqlite3_result_error_code);
|
||||||
|
DYNDEFINE(sqlite3_result_int);
|
||||||
|
DYNDEFINE(sqlite3_result_int64);
|
||||||
|
DYNDEFINE(sqlite3_result_null);
|
||||||
|
DYNDEFINE(sqlite3_result_text);
|
||||||
|
// DYNDEFINE(sqlite3_result_text64);
|
||||||
|
DYNDEFINE(sqlite3_result_text16);
|
||||||
|
DYNDEFINE(sqlite3_result_text16le);
|
||||||
|
DYNDEFINE(sqlite3_result_text16be);
|
||||||
|
DYNDEFINE(sqlite3_result_value);
|
||||||
|
DYNDEFINE(sqlite3_result_zeroblob);
|
||||||
|
DYNDEFINE(sqlite3_create_collation);
|
||||||
|
DYNDEFINE(sqlite3_create_collation_v2);
|
||||||
|
DYNDEFINE(sqlite3_create_collation16);
|
||||||
|
DYNDEFINE(sqlite3_collation_needed);
|
||||||
|
DYNDEFINE(sqlite3_collation_needed16);
|
||||||
|
|
||||||
|
#ifdef SQLITE_HAS_CODEC
|
||||||
|
|
||||||
|
DYNDEFINE(sqlite3_key);
|
||||||
|
DYNDEFINE(sqlite3_key_v2);
|
||||||
|
DYNDEFINE(sqlite3_rekey);
|
||||||
|
DYNDEFINE(sqlite3_rekey_v2);
|
||||||
|
DYNDEFINE(sqlite3_activate_see);
|
||||||
|
#endif
|
||||||
|
#ifdef SQLITE_ENABLE_CEROD
|
||||||
|
DYNDEFINE(sqlite3_activate_cerod);
|
||||||
|
#endif
|
||||||
|
DYNDEFINE(sqlite3_sleep);
|
||||||
|
DYNDEFINE(sqlite3_get_autocommit);
|
||||||
|
// DYNDEFINE(sqlite3_db_readonly);
|
||||||
|
DYNDEFINE(sqlite3_next_stmt);
|
||||||
|
DYNDEFINE(sqlite3_enable_shared_cache);
|
||||||
|
DYNDEFINE(sqlite3_release_memory);
|
||||||
|
// DYNDEFINE(sqlite3_db_release_memory);
|
||||||
|
// DYNDEFINE(sqlite3_soft_heap_limit64);
|
||||||
|
DYNDEFINE(sqlite3_table_column_metadata);
|
||||||
|
DYNDEFINE(sqlite3_load_extension);
|
||||||
|
DYNDEFINE(sqlite3_enable_load_extension);
|
||||||
|
DYNDEFINE(sqlite3_auto_extension);
|
||||||
|
// DYNDEFINE(sqlite3_cancel_auto_extension);
|
||||||
|
DYNDEFINE(sqlite3_reset_auto_extension);
|
||||||
|
DYNDEFINE(sqlite3_create_module);
|
||||||
|
DYNDEFINE(sqlite3_create_module_v2);
|
||||||
|
DYNDEFINE(sqlite3_declare_vtab);
|
||||||
|
DYNDEFINE(sqlite3_overload_function);
|
||||||
|
DYNDEFINE(sqlite3_blob_open);
|
||||||
|
DYNDEFINE(sqlite3_blob_close);
|
||||||
|
DYNDEFINE(sqlite3_blob_bytes);
|
||||||
|
DYNDEFINE(sqlite3_blob_read);
|
||||||
|
DYNDEFINE(sqlite3_blob_write);
|
||||||
|
DYNDEFINE(sqlite3_vfs_find);
|
||||||
|
DYNDEFINE(sqlite3_vfs_register);
|
||||||
|
DYNDEFINE(sqlite3_vfs_unregister);
|
||||||
|
DYNDEFINE(sqlite3_mutex_alloc);
|
||||||
|
DYNDEFINE(sqlite3_mutex_free);
|
||||||
|
DYNDEFINE(sqlite3_mutex_enter);
|
||||||
|
DYNDEFINE(sqlite3_mutex_try);
|
||||||
|
DYNDEFINE(sqlite3_mutex_leave);
|
||||||
|
// DYNDEFINE(sqlite3_mutex_held);
|
||||||
|
// DYNDEFINE(sqlite3_mutex_notheld);
|
||||||
|
DYNDEFINE(sqlite3_db_mutex);
|
||||||
|
DYNDEFINE(sqlite3_file_control);
|
||||||
|
DYNDEFINE(sqlite3_test_control);
|
||||||
|
DYNDEFINE(sqlite3_status);
|
||||||
|
DYNDEFINE(sqlite3_db_status);
|
||||||
|
DYNDEFINE(sqlite3_stmt_status);
|
||||||
|
DYNDEFINE(sqlite3_backup_init);
|
||||||
|
DYNDEFINE(sqlite3_backup_step);
|
||||||
|
DYNDEFINE(sqlite3_backup_finish);
|
||||||
|
DYNDEFINE(sqlite3_backup_remaining);
|
||||||
|
DYNDEFINE(sqlite3_backup_pagecount);
|
||||||
|
DYNDEFINE(sqlite3_unlock_notify);
|
||||||
|
// DYNDEFINE(sqlite3_stricmp);
|
||||||
|
// DYNDEFINE(sqlite3_strnicmp);
|
||||||
|
// DYNDEFINE(sqlite3_strglob);
|
||||||
|
// DYNDEFINE(sqlite3_log);
|
||||||
|
// DYNDEFINE(sqlite3_wal_autocheckpoint);
|
||||||
|
// DYNDEFINE(sqlite3_wal_checkpoint);
|
||||||
|
// DYNDEFINE(sqlite3_wal_checkpoint_v2);
|
||||||
|
// DYNDEFINE(sqlite3_vtab_config);
|
||||||
|
// DYNDEFINE(sqlite3_vtab_on_conflict);
|
||||||
|
// DYNDEFINE(sqlite3_rtree_geometry_callback);
|
||||||
|
// DYNDEFINE(sqlite3_rtree_query_callback);
|
||||||
|
|
||||||
|
#define STR(x) #x
|
||||||
|
#define GET_STR(x) STR(x)
|
||||||
|
|
||||||
|
#ifndef SQLPP_DYNAMIC_LOADING_FILENAME
|
||||||
|
#ifdef __linux__
|
||||||
|
#define SQLPP_DYNAMIC_LOADING_FILENAME libsqlite3.so
|
||||||
|
#elif __APPLE__
|
||||||
|
#define SQLPP_DYNAMIC_LOADING_FILENAME libsqlite3.dylib
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void init_sqlite(std::string libname)
|
||||||
|
{
|
||||||
|
if (libname.empty())
|
||||||
|
{
|
||||||
|
libname = GET_STR(SQLPP_DYNAMIC_LOADING_FILENAME);
|
||||||
|
}
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
void* handle = nullptr;
|
||||||
|
handle = dlopen(libname.c_str(), RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
#else
|
||||||
|
HINSTANCE handle = nullptr;
|
||||||
|
handle = LoadLibrary(libname.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef STR
|
||||||
|
#undef GET_STR
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
throw sqlpp::exception(std::string("Could not load library " + libname + ": ").append(dlerror()));
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
if (GetLastError() == 193)
|
||||||
|
{
|
||||||
|
throw sqlpp::exception(
|
||||||
|
"Could not load SQLite library - error code indicates you are mixing 32/64 bit DLLs (lib: " + libname +
|
||||||
|
")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw sqlpp::exception("Could not load lib using LoadLibrary (" + libname + ")");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
DYNLOAD(handle, sqlite3_libversion_number);
|
||||||
|
// DYNLOAD(handle, sqlite3_compileoption_used);
|
||||||
|
DYNLOAD(handle, sqlite3_threadsafe);
|
||||||
|
DYNLOAD(handle, sqlite3_close);
|
||||||
|
// DYNLOAD(handle, sqlite3_close_v2);
|
||||||
|
DYNLOAD(handle, sqlite3_exec);
|
||||||
|
DYNLOAD(handle, sqlite3_initialize);
|
||||||
|
DYNLOAD(handle, sqlite3_shutdown);
|
||||||
|
DYNLOAD(handle, sqlite3_os_init);
|
||||||
|
DYNLOAD(handle, sqlite3_os_end);
|
||||||
|
DYNLOAD(handle, sqlite3_config);
|
||||||
|
DYNLOAD(handle, sqlite3_db_config);
|
||||||
|
DYNLOAD(handle, sqlite3_extended_result_codes);
|
||||||
|
DYNLOAD(handle, sqlite3_last_insert_rowid);
|
||||||
|
DYNLOAD(handle, sqlite3_changes);
|
||||||
|
DYNLOAD(handle, sqlite3_total_changes);
|
||||||
|
DYNLOAD(handle, sqlite3_interrupt);
|
||||||
|
DYNLOAD(handle, sqlite3_complete);
|
||||||
|
DYNLOAD(handle, sqlite3_complete16);
|
||||||
|
DYNLOAD(handle, sqlite3_busy_handler);
|
||||||
|
DYNLOAD(handle, sqlite3_busy_timeout);
|
||||||
|
DYNLOAD(handle, sqlite3_get_table);
|
||||||
|
DYNLOAD(handle, sqlite3_free_table);
|
||||||
|
// DYNLOAD(handle, sqlite3_realloc64);
|
||||||
|
DYNLOAD(handle, sqlite3_free);
|
||||||
|
// DYNLOAD(handle, sqlite3_msize);
|
||||||
|
DYNLOAD(handle, sqlite3_memory_used);
|
||||||
|
DYNLOAD(handle, sqlite3_memory_highwater);
|
||||||
|
DYNLOAD(handle, sqlite3_randomness);
|
||||||
|
DYNLOAD(handle, sqlite3_set_authorizer);
|
||||||
|
DYNLOAD(handle, sqlite3_progress_handler);
|
||||||
|
DYNLOAD(handle, sqlite3_open);
|
||||||
|
DYNLOAD(handle, sqlite3_open16);
|
||||||
|
DYNLOAD(handle, sqlite3_open_v2);
|
||||||
|
// DYNLOAD(handle, sqlite3_uri_boolean);
|
||||||
|
// DYNLOAD(handle, sqlite3_uri_int64);
|
||||||
|
DYNLOAD(handle, sqlite3_errcode);
|
||||||
|
DYNLOAD(handle, sqlite3_errmsg);
|
||||||
|
DYNLOAD(handle, sqlite3_extended_errcode);
|
||||||
|
DYNLOAD(handle, sqlite3_limit);
|
||||||
|
DYNLOAD(handle, sqlite3_prepare);
|
||||||
|
DYNLOAD(handle, sqlite3_prepare_v2);
|
||||||
|
DYNLOAD(handle, sqlite3_prepare16);
|
||||||
|
DYNLOAD(handle, sqlite3_prepare16_v2);
|
||||||
|
// DYNLOAD(handle, sqlite3_stmt_readonly);
|
||||||
|
// DYNLOAD(handle, sqlite3_stmt_busy);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_blob);
|
||||||
|
// DYNLOAD(handle, sqlite3_bind_blob64);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_double);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_int);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_int64);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_null);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_text);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_text16);
|
||||||
|
// DYNLOAD(handle, sqlite3_bind_text64);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_value);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_zeroblob);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_parameter_count);
|
||||||
|
DYNLOAD(handle, sqlite3_bind_parameter_index);
|
||||||
|
DYNLOAD(handle, sqlite3_clear_bindings);
|
||||||
|
DYNLOAD(handle, sqlite3_column_count);
|
||||||
|
DYNLOAD(handle, sqlite3_step);
|
||||||
|
DYNLOAD(handle, sqlite3_data_count);
|
||||||
|
DYNLOAD(handle, sqlite3_column_bytes);
|
||||||
|
DYNLOAD(handle, sqlite3_column_bytes16);
|
||||||
|
DYNLOAD(handle, sqlite3_column_double);
|
||||||
|
DYNLOAD(handle, sqlite3_column_int);
|
||||||
|
DYNLOAD(handle, sqlite3_column_int64);
|
||||||
|
DYNLOAD(handle, sqlite3_column_text);
|
||||||
|
DYNLOAD(handle, sqlite3_column_type);
|
||||||
|
DYNLOAD(handle, sqlite3_column_value);
|
||||||
|
DYNLOAD(handle, sqlite3_column_blob);
|
||||||
|
DYNLOAD(handle, sqlite3_finalize);
|
||||||
|
DYNLOAD(handle, sqlite3_reset);
|
||||||
|
DYNLOAD(handle, sqlite3_create_function);
|
||||||
|
DYNLOAD(handle, sqlite3_create_function16);
|
||||||
|
// DYNLOAD(handle, sqlite3_create_function_v2);
|
||||||
|
DYNLOAD(handle, sqlite3_value_bytes);
|
||||||
|
DYNLOAD(handle, sqlite3_value_bytes16);
|
||||||
|
DYNLOAD(handle, sqlite3_value_double);
|
||||||
|
DYNLOAD(handle, sqlite3_value_int);
|
||||||
|
DYNLOAD(handle, sqlite3_value_int64);
|
||||||
|
DYNLOAD(handle, sqlite3_value_type);
|
||||||
|
DYNLOAD(handle, sqlite3_value_numeric_type);
|
||||||
|
DYNLOAD(handle, sqlite3_set_auxdata);
|
||||||
|
DYNLOAD(handle, sqlite3_result_blob);
|
||||||
|
// DYNLOAD(handle, sqlite3_result_blob64);
|
||||||
|
DYNLOAD(handle, sqlite3_result_double);
|
||||||
|
DYNLOAD(handle, sqlite3_result_error);
|
||||||
|
DYNLOAD(handle, sqlite3_result_error16);
|
||||||
|
DYNLOAD(handle, sqlite3_result_error_toobig);
|
||||||
|
DYNLOAD(handle, sqlite3_result_error_nomem);
|
||||||
|
DYNLOAD(handle, sqlite3_result_error_code);
|
||||||
|
DYNLOAD(handle, sqlite3_result_int);
|
||||||
|
DYNLOAD(handle, sqlite3_result_int64);
|
||||||
|
DYNLOAD(handle, sqlite3_result_null);
|
||||||
|
DYNLOAD(handle, sqlite3_result_text);
|
||||||
|
// DYNLOAD(handle, sqlite3_result_text64);
|
||||||
|
DYNLOAD(handle, sqlite3_result_text16);
|
||||||
|
DYNLOAD(handle, sqlite3_result_text16le);
|
||||||
|
DYNLOAD(handle, sqlite3_result_text16be);
|
||||||
|
DYNLOAD(handle, sqlite3_result_value);
|
||||||
|
DYNLOAD(handle, sqlite3_result_zeroblob);
|
||||||
|
DYNLOAD(handle, sqlite3_create_collation);
|
||||||
|
DYNLOAD(handle, sqlite3_create_collation_v2);
|
||||||
|
DYNLOAD(handle, sqlite3_create_collation16);
|
||||||
|
DYNLOAD(handle, sqlite3_collation_needed);
|
||||||
|
DYNLOAD(handle, sqlite3_collation_needed16);
|
||||||
|
|
||||||
|
#ifdef SQLITE_HAS_CODEC
|
||||||
|
DYNLOAD(handle, sqlite3_key);
|
||||||
|
DYNLOAD(handle, sqlite3_key_v2);
|
||||||
|
DYNLOAD(handle, sqlite3_rekey);
|
||||||
|
DYNLOAD(handle, sqlite3_rekey_v2);
|
||||||
|
DYNLOAD(handle, sqlite3_activate_see);
|
||||||
|
#endif
|
||||||
|
#ifdef SQLITE_ENABLE_CEROD
|
||||||
|
DYNLOAD(handle, sqlite3_activate_cerod);
|
||||||
|
#endif
|
||||||
|
DYNLOAD(handle, sqlite3_sleep);
|
||||||
|
DYNLOAD(handle, sqlite3_get_autocommit);
|
||||||
|
// DYNLOAD(handle, sqlite3_db_readonly);
|
||||||
|
DYNLOAD(handle, sqlite3_next_stmt);
|
||||||
|
DYNLOAD(handle, sqlite3_enable_shared_cache);
|
||||||
|
DYNLOAD(handle, sqlite3_release_memory);
|
||||||
|
// DYNLOAD(handle, sqlite3_db_release_memory);
|
||||||
|
// DYNLOAD(handle, sqlite3_soft_heap_limit64);
|
||||||
|
DYNLOAD(handle, sqlite3_table_column_metadata);
|
||||||
|
DYNLOAD(handle, sqlite3_load_extension);
|
||||||
|
DYNLOAD(handle, sqlite3_enable_load_extension);
|
||||||
|
DYNLOAD(handle, sqlite3_auto_extension);
|
||||||
|
// DYNLOAD(handle, sqlite3_cancel_auto_extension);
|
||||||
|
DYNLOAD(handle, sqlite3_reset_auto_extension);
|
||||||
|
DYNLOAD(handle, sqlite3_create_module);
|
||||||
|
DYNLOAD(handle, sqlite3_create_module_v2);
|
||||||
|
DYNLOAD(handle, sqlite3_declare_vtab);
|
||||||
|
DYNLOAD(handle, sqlite3_overload_function);
|
||||||
|
DYNLOAD(handle, sqlite3_blob_open);
|
||||||
|
DYNLOAD(handle, sqlite3_blob_close);
|
||||||
|
DYNLOAD(handle, sqlite3_blob_bytes);
|
||||||
|
DYNLOAD(handle, sqlite3_blob_read);
|
||||||
|
DYNLOAD(handle, sqlite3_blob_write);
|
||||||
|
DYNLOAD(handle, sqlite3_vfs_find);
|
||||||
|
DYNLOAD(handle, sqlite3_vfs_register);
|
||||||
|
DYNLOAD(handle, sqlite3_vfs_unregister);
|
||||||
|
DYNLOAD(handle, sqlite3_mutex_alloc);
|
||||||
|
DYNLOAD(handle, sqlite3_mutex_free);
|
||||||
|
DYNLOAD(handle, sqlite3_mutex_enter);
|
||||||
|
DYNLOAD(handle, sqlite3_mutex_try);
|
||||||
|
DYNLOAD(handle, sqlite3_mutex_leave);
|
||||||
|
// DYNLOAD(handle, sqlite3_mutex_held);
|
||||||
|
// DYNLOAD(handle, sqlite3_mutex_notheld);
|
||||||
|
DYNLOAD(handle, sqlite3_db_mutex);
|
||||||
|
DYNLOAD(handle, sqlite3_file_control);
|
||||||
|
DYNLOAD(handle, sqlite3_test_control);
|
||||||
|
DYNLOAD(handle, sqlite3_status);
|
||||||
|
DYNLOAD(handle, sqlite3_db_status);
|
||||||
|
DYNLOAD(handle, sqlite3_stmt_status);
|
||||||
|
DYNLOAD(handle, sqlite3_backup_init);
|
||||||
|
DYNLOAD(handle, sqlite3_backup_step);
|
||||||
|
DYNLOAD(handle, sqlite3_backup_finish);
|
||||||
|
DYNLOAD(handle, sqlite3_backup_remaining);
|
||||||
|
DYNLOAD(handle, sqlite3_backup_pagecount);
|
||||||
|
DYNLOAD(handle, sqlite3_unlock_notify);
|
||||||
|
// DYNLOAD(handle, sqlite3_stricmp);
|
||||||
|
// DYNLOAD(handle, sqlite3_strnicmp);
|
||||||
|
// DYNLOAD(handle, sqlite3_strglob);
|
||||||
|
// DYNLOAD(handle, sqlite3_log);
|
||||||
|
// DYNLOAD(handle, sqlite3_wal_autocheckpoint);
|
||||||
|
// DYNLOAD(handle, sqlite3_wal_checkpoint);
|
||||||
|
// DYNLOAD(handle, sqlite3_wal_checkpoint_v2);
|
||||||
|
// DYNLOAD(handle, sqlite3_vtab_config);
|
||||||
|
// DYNLOAD(handle, sqlite3_vtab_on_conflict);
|
||||||
|
// DYNLOAD(handle, sqlite3_rtree_geometry_callback);
|
||||||
|
// DYNLOAD(handle, sqlite3_rtree_query_callback);
|
||||||
|
|
||||||
|
// check some functions for nullptr to verify if loading worked, otherwise throw
|
||||||
|
if (sqlite3_shutdown == nullptr || sqlite3_exec == nullptr)
|
||||||
|
{
|
||||||
|
throw sqlpp::exception("Initializing dynamically loaded SQLite3 functions failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // dynamic
|
||||||
|
} // sqlite3
|
||||||
|
} // sqlpp
|
||||||
|
|
||||||
|
#undef DYNDEFINE
|
||||||
|
#undef DYNLOAD
|
||||||
|
#endif
|
96
src/sqlite3/detail/prepared_statement_handle.h
Normal file
96
src/sqlite3/detail/prepared_statement_handle.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2015, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_SQLITE3_DETAIL_PREPARED_STATEMENT_HANDLE_H
|
||||||
|
#define SQLPP_SQLITE3_DETAIL_PREPARED_STATEMENT_HANDLE_H
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
#include <sqlpp11/sqlite3/dynamic_libsqlite3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
using namespace dynamic;
|
||||||
|
#endif
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct prepared_statement_handle_t
|
||||||
|
{
|
||||||
|
sqlite3_stmt* sqlite_statement;
|
||||||
|
bool debug;
|
||||||
|
|
||||||
|
prepared_statement_handle_t(sqlite3_stmt* statement, bool debug_) : sqlite_statement(statement), debug(debug_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
prepared_statement_handle_t(const prepared_statement_handle_t&) = delete;
|
||||||
|
prepared_statement_handle_t(prepared_statement_handle_t&& rhs)
|
||||||
|
{
|
||||||
|
sqlite_statement = rhs.sqlite_statement;
|
||||||
|
rhs.sqlite_statement = nullptr;
|
||||||
|
|
||||||
|
debug = rhs.debug;
|
||||||
|
}
|
||||||
|
prepared_statement_handle_t& operator=(const prepared_statement_handle_t&) = delete;
|
||||||
|
prepared_statement_handle_t& operator=(prepared_statement_handle_t&& rhs)
|
||||||
|
{
|
||||||
|
if (sqlite_statement != rhs.sqlite_statement)
|
||||||
|
{
|
||||||
|
sqlite_statement = rhs.sqlite_statement;
|
||||||
|
rhs.sqlite_statement = nullptr;
|
||||||
|
}
|
||||||
|
debug = rhs.debug;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~prepared_statement_handle_t()
|
||||||
|
{
|
||||||
|
if (sqlite_statement)
|
||||||
|
{
|
||||||
|
sqlite3_finalize(sqlite_statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!() const
|
||||||
|
{
|
||||||
|
return !sqlite_statement;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace sqlite3
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#endif
|
245
src/sqlite3/prepared_statement.cpp
Normal file
245
src/sqlite3/prepared_statement.cpp
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "detail/prepared_statement_handle.h"
|
||||||
|
#include <ciso646>
|
||||||
|
#include <cmath>
|
||||||
|
#include <date/date.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sqlpp11/exception.h>
|
||||||
|
#include <sqlpp11/sqlite3/prepared_statement.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#if defined(__CYGWIN__)
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
// Workaround because cygwin gcc does not define to_string
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
std::string to_string(T t)
|
||||||
|
{
|
||||||
|
std::ostringstream stream;
|
||||||
|
|
||||||
|
stream << t;
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
} // namespace std
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
#include <sqlpp11/sqlite3/dynamic_libsqlite3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace sqlite3
|
||||||
|
{
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
using namespace dynamic;
|
||||||
|
#endif
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void check_bind_result(int result, const char* const type)
|
||||||
|
{
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case SQLITE_OK:
|
||||||
|
return;
|
||||||
|
case SQLITE_RANGE:
|
||||||
|
throw sqlpp::exception("Sqlite3 error: " + std::string(type) + " bind value out of range");
|
||||||
|
case SQLITE_NOMEM:
|
||||||
|
throw sqlpp::exception("Sqlite3 error: " + std::string(type) + " bind out of memory");
|
||||||
|
case SQLITE_TOOBIG:
|
||||||
|
throw sqlpp::exception("Sqlite3 error: " + std::string(type) + " bind too big");
|
||||||
|
default:
|
||||||
|
throw sqlpp::exception("Sqlite3 error: " + std::string(type) +
|
||||||
|
" bind returned unexpected value: " + std::to_string(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
prepared_statement_t::prepared_statement_t(std::shared_ptr<detail::prepared_statement_handle_t>&& handle)
|
||||||
|
: _handle(std::move(handle))
|
||||||
|
{
|
||||||
|
if (_handle and _handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: Constructing prepared_statement, using handle at " << _handle.get() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepared_statement_t::_reset()
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: resetting prepared statement" << std::endl;
|
||||||
|
sqlite3_reset(_handle->sqlite_statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepared_statement_t::_bind_boolean_parameter(size_t index, const signed char* value, bool is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding boolean parameter " << (*value ? "true" : "false")
|
||||||
|
<< " at index: " << index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if (not is_null)
|
||||||
|
result = sqlite3_bind_int(_handle->sqlite_statement, static_cast<int>(index + 1), *value);
|
||||||
|
else
|
||||||
|
result = sqlite3_bind_null(_handle->sqlite_statement, static_cast<int>(index + 1));
|
||||||
|
check_bind_result(result, "boolean");
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepared_statement_t::_bind_floating_point_parameter(size_t index, const double* value, bool is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding floating_point parameter " << *value << " at index: " << index
|
||||||
|
<< ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if (not is_null)
|
||||||
|
{
|
||||||
|
if (std::isnan(*value))
|
||||||
|
result = sqlite3_bind_text(_handle->sqlite_statement, static_cast<int>(index + 1), "NaN", 3, SQLITE_STATIC);
|
||||||
|
else if (std::isinf(*value))
|
||||||
|
{
|
||||||
|
if (*value > std::numeric_limits<double>::max())
|
||||||
|
result = sqlite3_bind_text(_handle->sqlite_statement, static_cast<int>(index + 1), "Inf", 3, SQLITE_STATIC);
|
||||||
|
else
|
||||||
|
result =
|
||||||
|
sqlite3_bind_text(_handle->sqlite_statement, static_cast<int>(index + 1), "-Inf", 4, SQLITE_STATIC);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = sqlite3_bind_double(_handle->sqlite_statement, static_cast<int>(index + 1), *value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = sqlite3_bind_null(_handle->sqlite_statement, static_cast<int>(index + 1));
|
||||||
|
check_bind_result(result, "floating_point");
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepared_statement_t::_bind_integral_parameter(size_t index, const int64_t* value, bool is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding integral parameter " << *value << " at index: " << index << ", being "
|
||||||
|
<< (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if (not is_null)
|
||||||
|
result = sqlite3_bind_int64(_handle->sqlite_statement, static_cast<int>(index + 1), *value);
|
||||||
|
else
|
||||||
|
result = sqlite3_bind_null(_handle->sqlite_statement, static_cast<int>(index + 1));
|
||||||
|
check_bind_result(result, "integral");
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepared_statement_t::_bind_unsigned_integral_parameter(size_t index, const uint64_t* value, bool is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding unsigned integral parameter " << *value << " at index: " << index
|
||||||
|
<< ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if (not is_null)
|
||||||
|
result =
|
||||||
|
sqlite3_bind_int64(_handle->sqlite_statement, static_cast<int>(index + 1), static_cast<int64_t>(*value));
|
||||||
|
else
|
||||||
|
result = sqlite3_bind_null(_handle->sqlite_statement, static_cast<int>(index + 1));
|
||||||
|
check_bind_result(result, "integral");
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepared_statement_t::_bind_text_parameter(size_t index, const std::string* value, bool is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding text parameter " << *value << " at index: " << index << ", being "
|
||||||
|
<< (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if (not is_null)
|
||||||
|
result = sqlite3_bind_text(_handle->sqlite_statement, static_cast<int>(index + 1), value->data(),
|
||||||
|
static_cast<int>(value->size()), SQLITE_STATIC);
|
||||||
|
else
|
||||||
|
result = sqlite3_bind_null(_handle->sqlite_statement, static_cast<int>(index + 1));
|
||||||
|
check_bind_result(result, "text");
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepared_statement_t::_bind_date_parameter(size_t index, const ::sqlpp::chrono::day_point* value, bool is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding date parameter "
|
||||||
|
<< " at index: " << index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if (not is_null)
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
const auto ymd = ::date::year_month_day{*value};
|
||||||
|
os << ymd;
|
||||||
|
const auto text = os.str();
|
||||||
|
result = sqlite3_bind_text(_handle->sqlite_statement, static_cast<int>(index + 1), text.data(),
|
||||||
|
static_cast<int>(text.size()), SQLITE_TRANSIENT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = sqlite3_bind_null(_handle->sqlite_statement, static_cast<int>(index + 1));
|
||||||
|
check_bind_result(result, "date");
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepared_statement_t::_bind_date_time_parameter(size_t index,
|
||||||
|
const ::sqlpp::chrono::microsecond_point* value,
|
||||||
|
bool is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding date_time parameter "
|
||||||
|
<< " at index: " << index << ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if (not is_null)
|
||||||
|
{
|
||||||
|
const auto dp = ::sqlpp::chrono::floor<::date::days>(*value);
|
||||||
|
const auto time = date::make_time(::sqlpp::chrono::floor<::std::chrono::milliseconds>(*value - dp));
|
||||||
|
const auto ymd = ::date::year_month_day{dp};
|
||||||
|
std::ostringstream os; // gcc-4.9 does not support auto os = std::ostringstream{};
|
||||||
|
os << ymd << ' ' << time;
|
||||||
|
const auto text = os.str();
|
||||||
|
result = sqlite3_bind_text(_handle->sqlite_statement, static_cast<int>(index + 1), text.data(),
|
||||||
|
static_cast<int>(text.size()), SQLITE_TRANSIENT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = sqlite3_bind_null(_handle->sqlite_statement, static_cast<int>(index + 1));
|
||||||
|
check_bind_result(result, "date");
|
||||||
|
}
|
||||||
|
void prepared_statement_t::_bind_blob_parameter(size_t index, const std::vector<uint8_t>* value, bool is_null)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "Sqlite3 debug: binding vector parameter size of " << value->size() << " at index: " << index
|
||||||
|
<< ", being " << (is_null ? "" : "not ") << "null" << std::endl;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if (not is_null)
|
||||||
|
result = sqlite3_bind_blob(_handle->sqlite_statement, static_cast<int>(index + 1), value->data(),
|
||||||
|
static_cast<int>(value->size()), SQLITE_STATIC);
|
||||||
|
else
|
||||||
|
result = sqlite3_bind_null(_handle->sqlite_statement, static_cast<int>(index + 1));
|
||||||
|
check_bind_result(result, "blob");
|
||||||
|
}
|
||||||
|
} // namespace sqlite3
|
||||||
|
} // namespace sqlpp
|
@ -1,13 +1,13 @@
|
|||||||
# Copyright (c) 2013-2016, Roland Bock
|
# Copyright (c) 2021-2021, Roland Bock
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
#
|
#
|
||||||
# Redistributions of source code must retain the above copyright notice, this
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
# list of conditions and the following disclaimer.
|
# list of conditions and the following disclaimer.
|
||||||
#
|
#
|
||||||
# Redistributions in binary form must reproduce the above copyright notice, this
|
# 2. Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
# list of conditions and the following disclaimer in the documentation and/or
|
# list of conditions and the following disclaimer in the documentation and/or
|
||||||
# other materials provided with the distribution.
|
# other materials provided with the distribution.
|
||||||
#
|
#
|
||||||
@ -21,59 +21,17 @@
|
|||||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
add_subdirectory(core/)
|
||||||
|
|
||||||
add_library(sqlpp11_testing INTERFACE)
|
if(MYSQL_CONNECTOR)
|
||||||
target_include_directories(sqlpp11_testing INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
add_subdirectory(mysql)
|
||||||
|
|
||||||
if (NOT MSVC)
|
|
||||||
target_compile_options(sqlpp11_testing INTERFACE -Wall -Wextra -pedantic)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(test_names
|
|
||||||
BooleanExpression
|
|
||||||
CustomQuery
|
|
||||||
DateTime
|
|
||||||
Interpret
|
|
||||||
Insert
|
|
||||||
Remove
|
|
||||||
Update
|
|
||||||
Select
|
|
||||||
SelectType
|
|
||||||
Function
|
|
||||||
Prepared
|
|
||||||
Minimalistic
|
|
||||||
Result
|
|
||||||
Union
|
|
||||||
With
|
|
||||||
)
|
|
||||||
|
|
||||||
find_package(Boost 1.50)
|
|
||||||
if(Boost_FOUND)
|
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
|
||||||
list(APPEND test_names Ppgen)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(POSTGRESQL_CONNECTOR)
|
||||||
create_test_sourcelist(test_sources test_main.cpp ${test_names})
|
add_subdirectory(postgresql)
|
||||||
add_executable(sqlpp11_tests ${test_sources})
|
|
||||||
target_link_libraries(sqlpp11_tests PRIVATE sqlpp11 sqlpp11_testing)
|
|
||||||
# conditionally bump to a higher C++ standard to test compatibility
|
|
||||||
if (SQLPP11_TESTS_CXX_STD)
|
|
||||||
set_property(TARGET sqlpp11_tests PROPERTY CXX_STANDARD ${SQLPP11_TESTS_CXX_STD})
|
|
||||||
set_property(TARGET sqlpp11_tests PROPERTY CXX_STANDARD_REQUIRED yes)
|
|
||||||
set_property(TARGET sqlpp11_tests PROPERTY CXX_EXTENSIONS no)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach(test IN LISTS test_names)
|
if(SQLITE3_CONNECTOR OR SQLCIPHER_CONNECTOR)
|
||||||
add_test(NAME sqlpp11.tests.${test}
|
add_subdirectory(sqlite3)
|
||||||
COMMAND sqlpp11_tests ${test}
|
endif()
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# if you want to use the generator, you can do something like this:
|
|
||||||
#find_package(PythonInterp REQUIRED)
|
|
||||||
#add_custom_command(
|
|
||||||
# OUTPUT "${CMAKE_CURRENT_LIST_DIR}/Sample.h"
|
|
||||||
# COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/ddl2cpp" "${CMAKE_CURRENT_LIST_DIR}/sample.sql" Sample test
|
|
||||||
# DEPENDS "${CMAKE_CURRENT_LIST_DIR}/sample.sql"
|
|
||||||
# VERBATIM)
|
|
||||||
|
29
tests/core/CMakeLists.txt
Normal file
29
tests/core/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Copyright (c) 2021-2021, Roland Bock
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
# other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
add_subdirectory(usage)
|
||||||
|
add_subdirectory(serialize)
|
||||||
|
add_subdirectory(constraints)
|
||||||
|
add_subdirectory(static_asserts)
|
||||||
|
|
||||||
|
|
79
tests/core/usage/CMakeLists.txt
Normal file
79
tests/core/usage/CMakeLists.txt
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# Copyright (c) 2013-2016, Roland Bock
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
# other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
add_library(sqlpp11_testing INTERFACE)
|
||||||
|
target_include_directories(sqlpp11_testing INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
if (NOT MSVC)
|
||||||
|
target_compile_options(sqlpp11_testing INTERFACE -Wall -Wextra -pedantic)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(test_names
|
||||||
|
BooleanExpression
|
||||||
|
CustomQuery
|
||||||
|
DateTime
|
||||||
|
Interpret
|
||||||
|
Insert
|
||||||
|
Remove
|
||||||
|
Update
|
||||||
|
Select
|
||||||
|
SelectType
|
||||||
|
Function
|
||||||
|
Prepared
|
||||||
|
Minimalistic
|
||||||
|
Result
|
||||||
|
Union
|
||||||
|
With
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(Boost 1.50)
|
||||||
|
if(Boost_FOUND)
|
||||||
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
list(APPEND test_names Ppgen)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
create_test_sourcelist(test_sources test_main.cpp ${test_names})
|
||||||
|
add_executable(sqlpp11_tests ${test_sources})
|
||||||
|
target_link_libraries(sqlpp11_tests PRIVATE sqlpp11 sqlpp11_testing)
|
||||||
|
# conditionally bump to a higher C++ standard to test compatibility
|
||||||
|
if (SQLPP11_TESTS_CXX_STD)
|
||||||
|
set_property(TARGET sqlpp11_tests PROPERTY CXX_STANDARD ${SQLPP11_TESTS_CXX_STD})
|
||||||
|
set_property(TARGET sqlpp11_tests PROPERTY CXX_STANDARD_REQUIRED yes)
|
||||||
|
set_property(TARGET sqlpp11_tests PROPERTY CXX_EXTENSIONS no)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
foreach(test IN LISTS test_names)
|
||||||
|
add_test(NAME sqlpp11.tests.${test}
|
||||||
|
COMMAND sqlpp11_tests ${test}
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# if you want to use the generator, you can do something like this:
|
||||||
|
#find_package(PythonInterp REQUIRED)
|
||||||
|
#add_custom_command(
|
||||||
|
# OUTPUT "${CMAKE_CURRENT_LIST_DIR}/Sample.h"
|
||||||
|
# COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/ddl2cpp" "${CMAKE_CURRENT_LIST_DIR}/sample.sql" Sample test
|
||||||
|
# DEPENDS "${CMAKE_CURRENT_LIST_DIR}/sample.sql"
|
||||||
|
# VERBATIM)
|
26
tests/sqlite3/CMakeLists.txt
Normal file
26
tests/sqlite3/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Copyright (c) 2021-2021, Roland Bock
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
# other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
add_subdirectory(usage)
|
||||||
|
|
||||||
|
|
75
tests/sqlite3/usage/AttachTest.cpp
Normal file
75
tests/sqlite3/usage/AttachTest.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TabSample.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection_config config;
|
||||||
|
config.path_to_database = ":memory:";
|
||||||
|
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
config.debug = true;
|
||||||
|
|
||||||
|
// Opening a connection to an in-memory database and creating a table in it
|
||||||
|
sql::connection db(config);
|
||||||
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
|
alpha INTEGER PRIMARY KEY,
|
||||||
|
beta varchar(255) DEFAULT NULL,
|
||||||
|
gamma bool DEFAULT NULL
|
||||||
|
))");
|
||||||
|
|
||||||
|
// Attaching another in-memory database and creating the same table in it
|
||||||
|
auto other = db.attach(config, "other");
|
||||||
|
db.execute(R"(CREATE TABLE other.tab_sample (
|
||||||
|
alpha INTEGER PRIMARY KEY,
|
||||||
|
beta varchar(255) DEFAULT NULL,
|
||||||
|
gamma bool DEFAULT NULL
|
||||||
|
))");
|
||||||
|
|
||||||
|
auto left = TabSample{};
|
||||||
|
auto right =
|
||||||
|
schema_qualified_table(other, TabSample{}).as(sqlpp::alias::right); // this is a table in the attached database
|
||||||
|
|
||||||
|
// inserting in one tab_sample
|
||||||
|
db(insert_into(left).default_values());
|
||||||
|
|
||||||
|
// selecting from the other tab_sample
|
||||||
|
assert(db(select(all_of(right)).from(right).unconditionally()).empty());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
69
tests/sqlite3/usage/AutoIncrementTest.cpp
Normal file
69
tests/sqlite3/usage/AutoIncrementTest.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TabSample.h"
|
||||||
|
#include <sqlpp11/custom_query.h>
|
||||||
|
#include <sqlpp11/sqlite3/sqlite3.h>
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection_config config;
|
||||||
|
config.path_to_database = ":memory:";
|
||||||
|
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
config.debug = true;
|
||||||
|
|
||||||
|
sql::connection db(config);
|
||||||
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
|
alpha INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
beta bool DEFAULT NULL,
|
||||||
|
gamma varchar(255) DEFAULT NULL
|
||||||
|
))");
|
||||||
|
|
||||||
|
const auto tab = TabSample{};
|
||||||
|
db(insert_into(tab).default_values());
|
||||||
|
db(insert_into(tab).default_values());
|
||||||
|
db(insert_into(tab).default_values());
|
||||||
|
|
||||||
|
std::set<int64_t> results;
|
||||||
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
results.insert(row.alpha);
|
||||||
|
};
|
||||||
|
const auto expected = std::set<int64_t>{1, 2, 3};
|
||||||
|
assert(results == expected);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
78
tests/sqlite3/usage/BlobSample.h
Normal file
78
tests/sqlite3/usage/BlobSample.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// generated by ../../sqlpp11/scripts/ddl2cpp -fail-on-parse BlobSample.sql BlobSample blob
|
||||||
|
#ifndef BLOB_BLOBSAMPLE_H
|
||||||
|
#define BLOB_BLOBSAMPLE_H
|
||||||
|
|
||||||
|
#include <sqlpp11/char_sequence.h>
|
||||||
|
#include <sqlpp11/data_types.h>
|
||||||
|
#include <sqlpp11/table.h>
|
||||||
|
|
||||||
|
namespace BlobSample_
|
||||||
|
{
|
||||||
|
struct Id
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "id";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T id;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = sqlpp::make_traits<sqlpp::integer, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "data";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T data;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = sqlpp::make_traits<sqlpp::blob, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
} // namespace BlobSample_
|
||||||
|
|
||||||
|
struct BlobSample : sqlpp::table_t<BlobSample, BlobSample_::Id, BlobSample_::Data>
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "blob_sample";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T blobSample;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return blobSample;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return blobSample;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#endif
|
4
tests/sqlite3/usage/BlobSample.sql
Normal file
4
tests/sqlite3/usage/BlobSample.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
CREATE TABLE blob_sample (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
data blob
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
102
tests/sqlite3/usage/BlobTest.cpp
Normal file
102
tests/sqlite3/usage/BlobTest.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#include "BlobSample.h"
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
const auto blob = BlobSample{};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* max default blob/text is 1,000,000,000
|
||||||
|
* But 999,999,993 is the biggest one SQLITE will accept
|
||||||
|
* without throwing SQLITE_TOOBIG
|
||||||
|
* But it takes too long (over 5s) to generate and check
|
||||||
|
*/
|
||||||
|
constexpr size_t blob_size = 1000 * 1000ul;
|
||||||
|
constexpr size_t blob_small_size = 999;
|
||||||
|
|
||||||
|
void verify_blob(sql::connection& db, const std::vector<uint8_t>& data, uint64_t id)
|
||||||
|
{
|
||||||
|
auto result = db(select(blob.data).from(blob).where(blob.id == id));
|
||||||
|
const auto& result_row = result.front();
|
||||||
|
std::cerr << "Insert size: " << data.size() << std::endl;
|
||||||
|
std::cerr << "Select size: " << result_row.data.len << std::endl;
|
||||||
|
if (data.size() != result_row.data.len)
|
||||||
|
{
|
||||||
|
std::cerr << "Size mismatch" << std::endl;
|
||||||
|
|
||||||
|
throw std::runtime_error("Size mismatch " + std::to_string(data.size()) +
|
||||||
|
" != " + std::to_string(result_row.data.len));
|
||||||
|
}
|
||||||
|
std::cerr << "Verifying content" << std::endl;
|
||||||
|
std::vector<uint8_t> result_blob(result_row.data.blob, result_row.data.blob + result_row.data.len);
|
||||||
|
if (data != result_blob)
|
||||||
|
{
|
||||||
|
std::cout << "Content mismatch ([row] original -> received)" << std::endl;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < data.size(); i++)
|
||||||
|
{
|
||||||
|
if (data[i] != result_row.data.blob[i])
|
||||||
|
{
|
||||||
|
std::cerr << "[" << i << "] " << static_cast<int>(data.at(i)) << " -> " << static_cast<int>(result_blob.at(i))
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Content mismatch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection_config config;
|
||||||
|
config.path_to_database = ":memory:";
|
||||||
|
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
config.debug = true;
|
||||||
|
|
||||||
|
sql::connection db(config);
|
||||||
|
db.execute(R"(CREATE TABLE blob_sample (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
data blob
|
||||||
|
))");
|
||||||
|
std::cerr << "Generating data " << blob_size << std::endl;
|
||||||
|
std::vector<uint8_t> data(blob_size);
|
||||||
|
std::uniform_int_distribution<unsigned short> distribution(0, 255);
|
||||||
|
std::mt19937 engine;
|
||||||
|
auto generator = std::bind(distribution, engine);
|
||||||
|
std::generate_n(data.begin(), blob_size, generator);
|
||||||
|
|
||||||
|
std::vector<uint8_t> data_smaller(blob_small_size);
|
||||||
|
std::generate_n(data_smaller.begin(), blob_small_size, generator);
|
||||||
|
|
||||||
|
// If we use the bigger blob it will trigger SQLITE_TOOBIG for the query
|
||||||
|
auto id = db(insert_into(blob).set(blob.data = data_smaller));
|
||||||
|
|
||||||
|
auto prepared_insert = db.prepare(insert_into(blob).set(blob.data = parameter(blob.data)));
|
||||||
|
prepared_insert.params.data = data;
|
||||||
|
auto prep_id = db(prepared_insert);
|
||||||
|
prepared_insert.params.data.set_null();
|
||||||
|
auto null_id = db(prepared_insert);
|
||||||
|
|
||||||
|
verify_blob(db, data_smaller, id);
|
||||||
|
verify_blob(db, data, prep_id);
|
||||||
|
{
|
||||||
|
auto result = db(select(blob.data).from(blob).where(blob.id == null_id));
|
||||||
|
const auto& result_row = result.front();
|
||||||
|
std::cerr << "Null blob is_null:\t" << std::boolalpha << result_row.data.is_null() << std::endl;
|
||||||
|
std::cerr << "Null blob len == 0:\t" << std::boolalpha << (result_row.data.len == 0) << std::endl;
|
||||||
|
std::cerr << "Null blob blob == nullptr:\t" << std::boolalpha << (result_row.data.blob == nullptr) << std::endl;
|
||||||
|
if (!result_row.data.is_null() || result_row.data.len != 0 || result_row.data.blob != nullptr)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Null blob has incorrect values");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
60
tests/sqlite3/usage/CMakeLists.txt
Normal file
60
tests/sqlite3/usage/CMakeLists.txt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
# other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||||
|
|
||||||
|
macro (build_and_run arg)
|
||||||
|
# Add headers to sources to enable file browsing in IDEs
|
||||||
|
add_executable(Sqlpp11Sqlite3${arg} ${arg}.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(Sqlpp11Sqlite3${arg} PRIVATE sqlpp11-connector-sqlite3)
|
||||||
|
if (NOT MSVC)
|
||||||
|
target_compile_options(Sqlpp11Sqlite3${arg} INTERFACE -Wall -Wextra -pedantic)
|
||||||
|
endif ()
|
||||||
|
add_test(NAME Sqlpp11Sqlite3${arg} COMMAND Sqlpp11Sqlite3${arg})
|
||||||
|
endmacro ()
|
||||||
|
|
||||||
|
build_and_run(DateTimeTest)
|
||||||
|
build_and_run(SampleTest)
|
||||||
|
build_and_run(SelectTest)
|
||||||
|
build_and_run(UnionTest)
|
||||||
|
build_and_run(WithTest)
|
||||||
|
build_and_run(AttachTest)
|
||||||
|
build_and_run(DynamicSelectTest)
|
||||||
|
build_and_run(AutoIncrementTest)
|
||||||
|
build_and_run(TransactionTest)
|
||||||
|
build_and_run(FloatingPointTest)
|
||||||
|
build_and_run(IntegralTest)
|
||||||
|
build_and_run(BlobTest)
|
||||||
|
|
||||||
|
# the dynamic loading test needs the extra option "SQLPP_DYNAMIC_LOADING" and does NOT link the sqlite libs
|
||||||
|
if (SQLPP_DYNAMIC_LOADING)
|
||||||
|
add_executable(Sqlpp11Sqlite3DynamicLoadingTest "DynamicLoadingTest.cpp" ${sqlpp_headers})
|
||||||
|
target_link_libraries(Sqlpp11Sqlite3DynamicLoadingTest sqlpp11-connector-sqlite3-dynamic)
|
||||||
|
if (NOT MSVC)
|
||||||
|
target_link_libraries(Sqlpp11Sqlite3DynamicLoadingTest dl)
|
||||||
|
target_compile_options(Sqlpp11Sqlite3DynamicLoadingTest INTERFACE -Wall -Wextra -pedantic)
|
||||||
|
endif ()
|
||||||
|
add_test(NAME Sqlpp11Sqlite3DynamicLoadingTest COMMAND Sqlpp11Sqlite3DynamicLoadingTest)
|
||||||
|
endif()
|
130
tests/sqlite3/usage/DateTimeTest.cpp
Normal file
130
tests/sqlite3/usage/DateTimeTest.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TabSample.h"
|
||||||
|
#include <sqlpp11/custom_query.h>
|
||||||
|
#include <sqlpp11/sqlite3/sqlite3.h>
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const auto now = ::sqlpp::chrono::floor<::std::chrono::milliseconds>(std::chrono::system_clock::now());
|
||||||
|
const auto today = ::sqlpp::chrono::floor<::sqlpp::chrono::days>(now);
|
||||||
|
const auto yesterday = today - ::sqlpp::chrono::days{1};
|
||||||
|
|
||||||
|
template <typename L, typename R>
|
||||||
|
auto require_equal(int line, const L& l, const R& r) -> void
|
||||||
|
{
|
||||||
|
if (l != r)
|
||||||
|
{
|
||||||
|
std::cerr << line << ": ";
|
||||||
|
serialize(::sqlpp::wrap_operand_t<L>{l}, std::cerr);
|
||||||
|
std::cerr << " != ";
|
||||||
|
serialize(::sqlpp::wrap_operand_t<R>{r}, std::cerr);
|
||||||
|
throw std::runtime_error("Unexpected result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sql::connection_config config;
|
||||||
|
config.path_to_database = ":memory:";
|
||||||
|
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
config.debug = true;
|
||||||
|
|
||||||
|
sql::connection db(config);
|
||||||
|
db.execute(R"(CREATE TABLE tab_date_time (
|
||||||
|
col_day_point DATE,
|
||||||
|
col_time_point DATETIME
|
||||||
|
))");
|
||||||
|
|
||||||
|
const auto tab = TabDateTime{};
|
||||||
|
db(insert_into(tab).default_values());
|
||||||
|
|
||||||
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
require_equal(__LINE__, row.colDayPoint.is_null(), true);
|
||||||
|
require_equal(__LINE__, row.colDayPoint.value(), ::sqlpp::chrono::day_point{});
|
||||||
|
require_equal(__LINE__, row.colTimePoint.is_null(), true);
|
||||||
|
require_equal(__LINE__, row.colTimePoint.value(), ::sqlpp::chrono::microsecond_point{});
|
||||||
|
}
|
||||||
|
|
||||||
|
db(update(tab).set(tab.colDayPoint = today, tab.colTimePoint = now).unconditionally());
|
||||||
|
|
||||||
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
require_equal(__LINE__, row.colDayPoint.value(), today);
|
||||||
|
require_equal(__LINE__, row.colTimePoint.value(), now);
|
||||||
|
}
|
||||||
|
|
||||||
|
db(update(tab).set(tab.colDayPoint = yesterday, tab.colTimePoint = today).unconditionally());
|
||||||
|
|
||||||
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
require_equal(__LINE__, row.colDayPoint.value(), yesterday);
|
||||||
|
require_equal(__LINE__, row.colTimePoint.value(), today);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prepared_update = db.prepare(
|
||||||
|
update(tab)
|
||||||
|
.set(tab.colDayPoint = parameter(tab.colDayPoint), tab.colTimePoint = parameter(tab.colTimePoint))
|
||||||
|
.unconditionally());
|
||||||
|
prepared_update.params.colDayPoint = today;
|
||||||
|
prepared_update.params.colTimePoint = now;
|
||||||
|
std::cout << "---- running prepared update ----" << std::endl;
|
||||||
|
db(prepared_update);
|
||||||
|
std::cout << "---- finished prepared update ----" << std::endl;
|
||||||
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
require_equal(__LINE__, row.colDayPoint.value(), today);
|
||||||
|
require_equal(__LINE__, row.colTimePoint.value(), now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Exception: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cerr << "Unknown exception: " << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
88
tests/sqlite3/usage/DynamicLoadingTest.cpp
Normal file
88
tests/sqlite3/usage/DynamicLoadingTest.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TabSample.h"
|
||||||
|
#include <sqlpp11/alias_provider.h>
|
||||||
|
#include <sqlpp11/functions.h>
|
||||||
|
#include <sqlpp11/insert.h>
|
||||||
|
#include <sqlpp11/remove.h>
|
||||||
|
#include <sqlpp11/select.h>
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
#include <sqlpp11/transaction.h>
|
||||||
|
#include <sqlpp11/update.h>
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <sqlpp11/sqlite3/dynamic_libsqlite3.h>
|
||||||
|
|
||||||
|
SQLPP_ALIAS_PROVIDER(left)
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection_config config;
|
||||||
|
config.path_to_database = ":memory:";
|
||||||
|
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
config.debug = true;
|
||||||
|
|
||||||
|
sql::connection db(config);
|
||||||
|
db.execute("CREATE TABLE tab_sample (\
|
||||||
|
alpha bigint(20) DEFAULT NULL,\
|
||||||
|
beta varchar(255) DEFAULT NULL,\
|
||||||
|
gamma bool DEFAULT NULL\
|
||||||
|
)");
|
||||||
|
|
||||||
|
const auto tab = TabSample{};
|
||||||
|
|
||||||
|
auto i = insert_into(tab).columns(tab.beta, tab.gamma);
|
||||||
|
i.values.add(tab.beta = "rhabarbertorte", tab.gamma = false);
|
||||||
|
// i.values.add(tab.beta = "cheesecake", tab.gamma = false)
|
||||||
|
// i.values.add(tab.beta = "kaesekuchen", tab.gamma = true)
|
||||||
|
auto last_insert_rowid = db(i);
|
||||||
|
|
||||||
|
std::cerr << "last insert rowid: " << last_insert_rowid << std::endl;
|
||||||
|
|
||||||
|
// Just to demonstrate that you can call basically any function
|
||||||
|
std::cerr << "last insert rowid: "
|
||||||
|
<< db(select(sqlpp::verbatim<sqlpp::integer>("last_insert_rowid()").as(tab.alpha))).front().alpha
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
// select a static (alpha) and a dynamic column (beta)
|
||||||
|
auto s = dynamic_select(db).dynamic_columns(tab.alpha.as(left)).from(tab).unconditionally();
|
||||||
|
s.selected_columns.add(tab.beta);
|
||||||
|
s.selected_columns.add(tab.gamma);
|
||||||
|
for (const auto& row : db(s))
|
||||||
|
{
|
||||||
|
std::cerr << "row.alpha: " << row.left << ", row.beta: " << row.at("beta") << ", row.gamma: " << row.at("gamma")
|
||||||
|
<< std::endl;
|
||||||
|
};
|
||||||
|
return 0;
|
||||||
|
}
|
86
tests/sqlite3/usage/DynamicSelectTest.cpp
Normal file
86
tests/sqlite3/usage/DynamicSelectTest.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TabSample.h"
|
||||||
|
#include <sqlpp11/alias_provider.h>
|
||||||
|
#include <sqlpp11/functions.h>
|
||||||
|
#include <sqlpp11/insert.h>
|
||||||
|
#include <sqlpp11/remove.h>
|
||||||
|
#include <sqlpp11/select.h>
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
#include <sqlpp11/transaction.h>
|
||||||
|
#include <sqlpp11/update.h>
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
SQLPP_ALIAS_PROVIDER(left)
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection_config config;
|
||||||
|
config.path_to_database = ":memory:";
|
||||||
|
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
config.debug = true;
|
||||||
|
|
||||||
|
sql::connection db(config);
|
||||||
|
db.execute("CREATE TABLE tab_sample (\
|
||||||
|
alpha bigint(20) DEFAULT NULL,\
|
||||||
|
beta varchar(255) DEFAULT NULL,\
|
||||||
|
gamma bool DEFAULT NULL\
|
||||||
|
)");
|
||||||
|
|
||||||
|
const auto tab = TabSample{};
|
||||||
|
|
||||||
|
auto i = insert_into(tab).columns(tab.beta, tab.gamma);
|
||||||
|
i.values.add(tab.beta = "rhabarbertorte", tab.gamma = false);
|
||||||
|
// i.values.add(tab.beta = "cheesecake", tab.gamma = false)
|
||||||
|
// i.values.add(tab.beta = "kaesekuchen", tab.gamma = true)
|
||||||
|
auto last_insert_rowid = db(i);
|
||||||
|
|
||||||
|
std::cerr << "last insert rowid: " << last_insert_rowid << std::endl;
|
||||||
|
|
||||||
|
// Just to demonstrate that you can call basically any function
|
||||||
|
std::cerr << "last insert rowid: "
|
||||||
|
<< db(select(sqlpp::verbatim<sqlpp::integer>("last_insert_rowid()").as(tab.alpha))).front().alpha
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
// select a static (alpha) and a dynamic column (beta)
|
||||||
|
auto s = dynamic_select(db).dynamic_columns(tab.alpha.as(left)).from(tab).unconditionally();
|
||||||
|
s.selected_columns.add(tab.beta);
|
||||||
|
s.selected_columns.add(tab.gamma);
|
||||||
|
for (const auto& row : db(s))
|
||||||
|
{
|
||||||
|
std::cerr << "row.alpha: " << row.left << ", row.beta: " << row.at("beta") << ", row.gamma: " << row.at("gamma")
|
||||||
|
<< std::endl;
|
||||||
|
};
|
||||||
|
return 0;
|
||||||
|
}
|
126
tests/sqlite3/usage/FloatingPointTest.cpp
Normal file
126
tests/sqlite3/usage/FloatingPointTest.cpp
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#include "FpSample.h"
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
|
||||||
|
const auto fp = FpSample{};
|
||||||
|
|
||||||
|
template <typename L, typename R>
|
||||||
|
auto require_equal(int line, const L& l, const R& r) -> void
|
||||||
|
{
|
||||||
|
if (l != r)
|
||||||
|
{
|
||||||
|
std::cerr << line << ": ";
|
||||||
|
serialize(::sqlpp::wrap_operand_t<L>{l}, std::cerr);
|
||||||
|
std::cerr << " != ";
|
||||||
|
serialize(::sqlpp::wrap_operand_t<R>{r}, std::cerr);
|
||||||
|
throw std::runtime_error("Unexpected result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto require(int line, bool condition) -> void
|
||||||
|
{
|
||||||
|
if (!condition)
|
||||||
|
{
|
||||||
|
std::cerr << line << " condition violated";
|
||||||
|
throw std::runtime_error("Unexpected result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection_config config;
|
||||||
|
config.path_to_database = ":memory:";
|
||||||
|
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
config.debug = true;
|
||||||
|
|
||||||
|
sql::connection db(config);
|
||||||
|
db.execute(R"(CREATE TABLE fp_sample (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
fp REAL
|
||||||
|
))");
|
||||||
|
|
||||||
|
db.execute("INSERT into fp_sample (id, fp) values(NULL, 1.0)");
|
||||||
|
db.execute("INSERT into fp_sample (id, fp) values(NULL, 'Inf')");
|
||||||
|
db.execute("INSERT into fp_sample (id, fp) values(NULL, 'Nan')");
|
||||||
|
db.execute("INSERT into fp_sample (id, fp) values(NULL, 'SomeString')");
|
||||||
|
db(insert_into(fp).set(fp.fp = std::numeric_limits<double>::quiet_NaN()));
|
||||||
|
db(insert_into(fp).set(fp.fp = std::numeric_limits<double>::infinity()));
|
||||||
|
db(insert_into(fp).set(fp.fp = -std::numeric_limits<double>::infinity()));
|
||||||
|
|
||||||
|
auto prepared_insert = db.prepare(insert_into(fp).set(fp.fp = parameter(fp.fp)));
|
||||||
|
prepared_insert.params.fp = std::numeric_limits<double>::quiet_NaN();
|
||||||
|
db(prepared_insert);
|
||||||
|
prepared_insert.params.fp = std::numeric_limits<double>::infinity();
|
||||||
|
db(prepared_insert);
|
||||||
|
prepared_insert.params.fp = -std::numeric_limits<double>::infinity();
|
||||||
|
db(prepared_insert);
|
||||||
|
|
||||||
|
auto q = select(fp.fp).from(fp).unconditionally();
|
||||||
|
auto rows = db(q);
|
||||||
|
|
||||||
|
// raw string inserts
|
||||||
|
require_equal(__LINE__, rows.front().fp, 1.0);
|
||||||
|
rows.pop_front();
|
||||||
|
require(__LINE__, std::isinf(rows.front().fp.value()));
|
||||||
|
rows.pop_front();
|
||||||
|
require(__LINE__, std::isnan(rows.front().fp.value()));
|
||||||
|
rows.pop_front();
|
||||||
|
require_equal(__LINE__, rows.front().fp, 0.0);
|
||||||
|
rows.pop_front();
|
||||||
|
|
||||||
|
// dsl inserts
|
||||||
|
require(__LINE__, std::isnan(rows.front().fp.value()));
|
||||||
|
rows.pop_front();
|
||||||
|
require(__LINE__, std::isinf(rows.front().fp.value()));
|
||||||
|
require(__LINE__, rows.front().fp.value() > std::numeric_limits<double>::max());
|
||||||
|
rows.pop_front();
|
||||||
|
require(__LINE__, std::isinf(rows.front().fp.value()));
|
||||||
|
require(__LINE__, rows.front().fp.value() < std::numeric_limits<double>::lowest());
|
||||||
|
|
||||||
|
// prepared dsl inserts
|
||||||
|
rows.pop_front();
|
||||||
|
require(__LINE__, std::isnan(rows.front().fp.value()));
|
||||||
|
rows.pop_front();
|
||||||
|
require(__LINE__, std::isinf(rows.front().fp.value()));
|
||||||
|
require(__LINE__, rows.front().fp.value() > std::numeric_limits<double>::max());
|
||||||
|
rows.pop_front();
|
||||||
|
require(__LINE__, std::isinf(rows.front().fp.value()));
|
||||||
|
require(__LINE__, rows.front().fp.value() < std::numeric_limits<double>::lowest());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
79
tests/sqlite3/usage/FpSample.h
Normal file
79
tests/sqlite3/usage/FpSample.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// generated by ../../sqlpp11/scripts/ddl2cpp -fail-on-parse FpSample.sql FpSample fp
|
||||||
|
#ifndef FP_FPSAMPLE_H
|
||||||
|
#define FP_FPSAMPLE_H
|
||||||
|
|
||||||
|
#include <sqlpp11/table.h>
|
||||||
|
#include <sqlpp11/data_types.h>
|
||||||
|
#include <sqlpp11/char_sequence.h>
|
||||||
|
|
||||||
|
namespace FpSample_
|
||||||
|
{
|
||||||
|
struct Id
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "id";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T id;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = sqlpp::make_traits<sqlpp::integer, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
struct Fp
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "fp";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T fp;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = sqlpp::make_traits<sqlpp::floating_point, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FpSample : sqlpp::table_t<FpSample, FpSample_::Id, FpSample_::Fp>
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "fp_sample";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T fpSample;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return fpSample;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return fpSample;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
4
tests/sqlite3/usage/FpSample.sql
Normal file
4
tests/sqlite3/usage/FpSample.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
CREATE TABLE fp_sample (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
fp DOUBLE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
79
tests/sqlite3/usage/IntegralSample.h
Normal file
79
tests/sqlite3/usage/IntegralSample.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#ifndef INTEGRAL_SAMPLE_H
|
||||||
|
#define INTEGRAL_SAMPLE_H
|
||||||
|
|
||||||
|
#include <sqlpp11/char_sequence.h>
|
||||||
|
#include <sqlpp11/data_types.h>
|
||||||
|
#include <sqlpp11/table.h>
|
||||||
|
|
||||||
|
namespace IntegralSample_
|
||||||
|
{
|
||||||
|
struct SignedValue
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "signed_value";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T signedValue;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return signedValue;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return signedValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = sqlpp::make_traits<sqlpp::integer, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
struct UnsignedValue
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "unsigned_value";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T unsignedValue;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return unsignedValue;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return unsignedValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = sqlpp::make_traits<sqlpp::integer_unsigned, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace IntegralSample_
|
||||||
|
|
||||||
|
struct IntegralSample : sqlpp::table_t<IntegralSample, IntegralSample_::SignedValue, IntegralSample_::UnsignedValue>
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "integral_sample";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T fpSample;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return fpSample;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return fpSample;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
119
tests/sqlite3/usage/IntegralTest.cpp
Normal file
119
tests/sqlite3/usage/IntegralTest.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#include "IntegralSample.h"
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
|
||||||
|
const auto intSample = IntegralSample{};
|
||||||
|
|
||||||
|
template <typename L, typename R>
|
||||||
|
auto require_equal(int line, const L& l, const R& r) -> void
|
||||||
|
{
|
||||||
|
if (l != r)
|
||||||
|
{
|
||||||
|
std::cerr << line << ": ";
|
||||||
|
serialize(::sqlpp::wrap_operand_t<L>{l}, std::cerr);
|
||||||
|
std::cerr << " != ";
|
||||||
|
serialize(::sqlpp::wrap_operand_t<R>{r}, std::cerr);
|
||||||
|
throw std::runtime_error("Unexpected result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection_config config;
|
||||||
|
config.path_to_database = ":memory:";
|
||||||
|
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
config.debug = true;
|
||||||
|
|
||||||
|
sql::connection db(config);
|
||||||
|
db.execute(R"(CREATE TABLE integral_sample (
|
||||||
|
signed_value INTEGER,
|
||||||
|
unsigned_value INTEGER
|
||||||
|
))");
|
||||||
|
|
||||||
|
// The connector supports uint64_t values and will always retrieve the correct value from the database.
|
||||||
|
// Sqlite3 stores the values as int64_t internally though, so big uint64_t values will be converted
|
||||||
|
// and the library has to intepret the int64_t values correctly as uint64_t.
|
||||||
|
// Therefore, we test uint64_t values in an out of the range of int64_t and test if they are retrieved
|
||||||
|
// correctly from the database in both cases.
|
||||||
|
uint64_t uint64_t_value_supported = std::numeric_limits<int64_t>::max();
|
||||||
|
int64_t int64_t_value_max = std::numeric_limits<int64_t>::max();
|
||||||
|
|
||||||
|
uint64_t uint64_t_value_unsupported = std::numeric_limits<uint64_t>::max();
|
||||||
|
int64_t int64_t_value_min = std::numeric_limits<int64_t>::min();
|
||||||
|
|
||||||
|
std::size_t size_t_value_max = std::numeric_limits<std::size_t>::max();
|
||||||
|
std::size_t size_t_value_min = std::numeric_limits<std::size_t>::min();
|
||||||
|
|
||||||
|
uint32_t uint32_t_value = std::numeric_limits<uint32_t>::max();
|
||||||
|
int32_t int32_t_value = std::numeric_limits<int32_t>::max();
|
||||||
|
|
||||||
|
db(insert_into(intSample).set(intSample.signedValue = int64_t_value_max,
|
||||||
|
intSample.unsignedValue = uint64_t_value_supported));
|
||||||
|
|
||||||
|
auto prepared_insert =
|
||||||
|
db.prepare(insert_into(intSample).set(intSample.signedValue = parameter(intSample.signedValue),
|
||||||
|
intSample.unsignedValue = parameter(intSample.unsignedValue)));
|
||||||
|
prepared_insert.params.signedValue = int64_t_value_min;
|
||||||
|
prepared_insert.params.unsignedValue = uint64_t_value_unsupported;
|
||||||
|
db(prepared_insert);
|
||||||
|
|
||||||
|
db(insert_into(intSample).set(intSample.signedValue = size_t_value_min, intSample.unsignedValue = size_t_value_max));
|
||||||
|
db(insert_into(intSample).set(intSample.signedValue = int32_t_value, intSample.unsignedValue = uint32_t_value));
|
||||||
|
|
||||||
|
auto q = select(intSample.signedValue, intSample.unsignedValue).from(intSample).unconditionally();
|
||||||
|
|
||||||
|
auto rows = db(q);
|
||||||
|
|
||||||
|
require_equal(__LINE__, rows.front().signedValue.value(), int64_t_value_max);
|
||||||
|
require_equal(__LINE__, rows.front().unsignedValue.value(), uint64_t_value_supported);
|
||||||
|
rows.pop_front();
|
||||||
|
|
||||||
|
require_equal(__LINE__, rows.front().signedValue.value(), int64_t_value_min);
|
||||||
|
require_equal(__LINE__, rows.front().unsignedValue.value(), uint64_t_value_unsupported);
|
||||||
|
rows.pop_front();
|
||||||
|
|
||||||
|
require_equal(__LINE__, rows.front().signedValue.value(), size_t_value_min);
|
||||||
|
require_equal(__LINE__, rows.front().unsignedValue.value(), size_t_value_max);
|
||||||
|
rows.pop_front();
|
||||||
|
|
||||||
|
require_equal(__LINE__, rows.front().signedValue.value(), int32_t_value);
|
||||||
|
require_equal(__LINE__, rows.front().unsignedValue.value(), uint32_t_value);
|
||||||
|
rows.pop_front();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
210
tests/sqlite3/usage/SampleTest.cpp
Normal file
210
tests/sqlite3/usage/SampleTest.cpp
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TabSample.h"
|
||||||
|
#include <sqlpp11/custom_query.h>
|
||||||
|
#include <sqlpp11/sqlite3/sqlite3.h>
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
SQLPP_ALIAS_PROVIDER(left)
|
||||||
|
SQLPP_ALIAS_PROVIDER(pragma)
|
||||||
|
SQLPP_ALIAS_PROVIDER(sub)
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection_config config;
|
||||||
|
config.path_to_database = ":memory:";
|
||||||
|
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
config.debug = true;
|
||||||
|
|
||||||
|
sql::connection db(config);
|
||||||
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
|
alpha INTEGER PRIMARY KEY,
|
||||||
|
beta varchar(255) DEFAULT NULL,
|
||||||
|
gamma bool DEFAULT NULL
|
||||||
|
))");
|
||||||
|
db.execute(R"(CREATE TABLE tab_foo (
|
||||||
|
omega bigint(20) DEFAULT NULL
|
||||||
|
))");
|
||||||
|
|
||||||
|
const auto tab = TabSample{};
|
||||||
|
|
||||||
|
// clear the table
|
||||||
|
db(remove_from(tab).unconditionally());
|
||||||
|
|
||||||
|
// explicit all_of(tab)
|
||||||
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
std::cerr << "row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma << std::endl;
|
||||||
|
};
|
||||||
|
std::cerr << __FILE__ << ": " << __LINE__ << std::endl;
|
||||||
|
// selecting a table implicitly expands to all_of(tab)
|
||||||
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
std::cerr << "row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma << std::endl;
|
||||||
|
};
|
||||||
|
// insert
|
||||||
|
std::cerr << "no of required columns: " << TabSample::_required_insert_columns::size::value << std::endl;
|
||||||
|
db(insert_into(tab).default_values());
|
||||||
|
std::cout << "Last Insert ID: " << db.last_insert_id() << "\n";
|
||||||
|
db(insert_into(tab).set(tab.gamma = true));
|
||||||
|
std::cout << "Last Insert ID: " << db.last_insert_id() << "\n";
|
||||||
|
auto di = dynamic_insert_into(db, tab).dynamic_set(tab.gamma = true);
|
||||||
|
di.insert_list.add(tab.beta = "");
|
||||||
|
db(di);
|
||||||
|
|
||||||
|
// update
|
||||||
|
db(update(tab).set(tab.gamma = false).where(tab.alpha.in(1)));
|
||||||
|
db(update(tab).set(tab.gamma = false).where(tab.alpha.in(sqlpp::value_list(std::vector<int>{1, 2, 3, 4}))));
|
||||||
|
|
||||||
|
// remove
|
||||||
|
db(remove_from(tab).where(tab.alpha == tab.alpha + 3));
|
||||||
|
|
||||||
|
auto result = db(select(all_of(tab)).from(tab).unconditionally());
|
||||||
|
std::cerr << "Accessing a field directly from the result (using the current row): " << result.begin()->alpha
|
||||||
|
<< std::endl;
|
||||||
|
std::cerr << "Can do that again, no problem: " << result.begin()->alpha << std::endl;
|
||||||
|
|
||||||
|
auto tx = start_transaction(db);
|
||||||
|
TabFoo foo;
|
||||||
|
for (const auto& row : db(select(all_of(tab), select(max(foo.omega)).from(foo).where(foo.omega > tab.alpha))
|
||||||
|
.from(tab)
|
||||||
|
.unconditionally()))
|
||||||
|
{
|
||||||
|
int x = row.alpha;
|
||||||
|
int a = row.max;
|
||||||
|
std::cout << x << ", " << a << std::endl;
|
||||||
|
}
|
||||||
|
tx.commit();
|
||||||
|
|
||||||
|
for (const auto& row : db(select(tab.alpha).from(tab.join(foo).on(tab.alpha == foo.omega)).unconditionally()))
|
||||||
|
{
|
||||||
|
std::cerr << row.alpha << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& row :
|
||||||
|
db(select(tab.alpha).from(tab.left_outer_join(foo).on(tab.alpha == foo.omega)).unconditionally()))
|
||||||
|
{
|
||||||
|
std::cerr << row.alpha << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ps = db.prepare(select(all_of(tab))
|
||||||
|
.from(tab)
|
||||||
|
.where(tab.alpha != parameter(tab.alpha) and tab.beta != parameter(tab.beta) and
|
||||||
|
tab.gamma != parameter(tab.gamma)));
|
||||||
|
ps.params.alpha = 7;
|
||||||
|
ps.params.beta = "wurzelbrunft";
|
||||||
|
ps.params.gamma = true;
|
||||||
|
for (const auto& row : db(ps))
|
||||||
|
{
|
||||||
|
std::cerr << "bound result: alpha: " << row.alpha << std::endl;
|
||||||
|
std::cerr << "bound result: beta: " << row.beta << std::endl;
|
||||||
|
std::cerr << "bound result: gamma: " << row.gamma << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "--------" << std::endl;
|
||||||
|
ps.params.alpha = sqlpp::eval<sqlpp::integer>(db, "last_insert_rowid()");
|
||||||
|
ps.params.gamma = "false";
|
||||||
|
for (const auto& row : db(ps))
|
||||||
|
{
|
||||||
|
std::cerr << "bound result: alpha: " << row.alpha << std::endl;
|
||||||
|
std::cerr << "bound result: beta: " << row.beta << std::endl;
|
||||||
|
std::cerr << "bound result: gamma: " << row.gamma << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "--------" << std::endl;
|
||||||
|
ps.params.beta = "kaesekuchen";
|
||||||
|
for (const auto& row : db(ps))
|
||||||
|
{
|
||||||
|
std::cerr << "bound result: alpha: " << row.alpha << std::endl;
|
||||||
|
std::cerr << "bound result: beta: " << row.beta << std::endl;
|
||||||
|
std::cerr << "bound result: gamma: " << row.gamma << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pi = db.prepare(insert_into(tab).set(tab.beta = parameter(tab.beta), tab.gamma = true));
|
||||||
|
pi.params.beta = "prepared cake";
|
||||||
|
std::cerr << "Inserted: " << db(pi) << std::endl;
|
||||||
|
|
||||||
|
auto pu = db.prepare(update(tab).set(tab.gamma = parameter(tab.gamma)).where(tab.beta == "prepared cake"));
|
||||||
|
pu.params.gamma = false;
|
||||||
|
std::cerr << "Updated: " << db(pu) << std::endl;
|
||||||
|
|
||||||
|
auto pr = db.prepare(remove_from(tab).where(tab.beta != parameter(tab.beta)));
|
||||||
|
pr.params.beta = "prepared cake";
|
||||||
|
std::cerr << "Deleted lines: " << db(pr) << std::endl;
|
||||||
|
|
||||||
|
// Check that a prepared select is default-constructible
|
||||||
|
{
|
||||||
|
auto s = select(all_of(tab))
|
||||||
|
.from(tab)
|
||||||
|
.where((tab.beta.like(parameter(tab.beta)) and tab.alpha == parameter(tab.alpha)) or
|
||||||
|
tab.gamma != parameter(tab.gamma));
|
||||||
|
using P = decltype(db.prepare(s));
|
||||||
|
P p; // You must not use this one yet!
|
||||||
|
p = db.prepare(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto i = db(sqlpp::sqlite3::insert_or_replace_into(tab).set(tab.beta = "test", tab.gamma = true));
|
||||||
|
std::cerr << i << std::endl;
|
||||||
|
|
||||||
|
i = db(sqlpp::sqlite3::insert_or_ignore_into(tab).set(tab.beta = "test", tab.gamma = true));
|
||||||
|
std::cerr << i << std::endl;
|
||||||
|
|
||||||
|
assert(db(select(count(tab.alpha)).from(tab).unconditionally()).begin()->count);
|
||||||
|
assert(
|
||||||
|
db(select(all_of(tab)).from(tab).where(tab.alpha.not_in(select(tab.alpha).from(tab).unconditionally()))).empty());
|
||||||
|
|
||||||
|
auto x = custom_query(sqlpp::verbatim("PRAGMA user_version = "), 1);
|
||||||
|
db(x);
|
||||||
|
int pragmaValue =
|
||||||
|
db(custom_query(sqlpp::verbatim("PRAGMA user_version")).with_result_type_of(select(sqlpp::value(1).as(pragma))))
|
||||||
|
.front()
|
||||||
|
.pragma;
|
||||||
|
std::cerr << pragmaValue << std::endl;
|
||||||
|
|
||||||
|
// Testing sub select tables and unconditional joins
|
||||||
|
const auto subQuery = select(tab.alpha).from(tab).unconditionally().as(sub);
|
||||||
|
for (const auto& row : db(select(subQuery.alpha).from(subQuery).unconditionally()))
|
||||||
|
{
|
||||||
|
std::cerr << row.alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& row : db(select(subQuery.alpha).from(tab.inner_join(subQuery).unconditionally()).unconditionally()))
|
||||||
|
{
|
||||||
|
std::cerr << row.alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
173
tests/sqlite3/usage/SelectTest.cpp
Normal file
173
tests/sqlite3/usage/SelectTest.cpp
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* Copyright (c) 2017, Juan Dent
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TabSample.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <sqlpp11/alias_provider.h>
|
||||||
|
#include <sqlpp11/functions.h>
|
||||||
|
#include <sqlpp11/insert.h>
|
||||||
|
#include <sqlpp11/remove.h>
|
||||||
|
#include <sqlpp11/select.h>
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
#include <sqlpp11/transaction.h>
|
||||||
|
#include <sqlpp11/update.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
SQLPP_ALIAS_PROVIDER(left)
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
const auto tab = TabSample{};
|
||||||
|
|
||||||
|
void testSelectAll(sql::connection& db, size_t expectedRowCount)
|
||||||
|
{
|
||||||
|
std::cerr << "--------------------------------------" << std::endl;
|
||||||
|
size_t i = 0;
|
||||||
|
for (const auto& row : db(sqlpp::select(all_of(tab)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
||||||
|
<< std::endl;
|
||||||
|
assert(static_cast<size_t>(row.alpha) == i);
|
||||||
|
};
|
||||||
|
assert(i == expectedRowCount);
|
||||||
|
|
||||||
|
auto preparedSelectAll = db.prepare(sqlpp::select(all_of(tab)).from(tab).unconditionally());
|
||||||
|
i = 0;
|
||||||
|
for (const auto& row : db(preparedSelectAll))
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
||||||
|
<< std::endl;
|
||||||
|
assert(static_cast<size_t>(row.alpha) == i);
|
||||||
|
};
|
||||||
|
assert(i == expectedRowCount);
|
||||||
|
std::cerr << "--------------------------------------" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace string_util
|
||||||
|
{
|
||||||
|
std::string ltrim(std::string str, const std::string& chars = "\t\n\v\f\r ")
|
||||||
|
{
|
||||||
|
str.erase(0, str.find_first_not_of(chars));
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rtrim(std::string str, const std::string& chars = "\t\n\v\f\r ")
|
||||||
|
{
|
||||||
|
str.erase(str.find_last_not_of(chars) + 1);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string trim(std::string str, const std::string& chars = "\t\n\v\f\r ")
|
||||||
|
{
|
||||||
|
return ltrim(rtrim(str, chars), chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection db({":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "", true});
|
||||||
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
|
alpha INTEGER PRIMARY KEY,
|
||||||
|
beta varchar(255) DEFAULT NULL,
|
||||||
|
gamma bool DEFAULT NULL
|
||||||
|
))");
|
||||||
|
|
||||||
|
testSelectAll(db, 0);
|
||||||
|
db(insert_into(tab).default_values());
|
||||||
|
testSelectAll(db, 1);
|
||||||
|
db(insert_into(tab).set(tab.gamma = true, tab.beta = " cheesecake "));
|
||||||
|
testSelectAll(db, 2);
|
||||||
|
db(insert_into(tab).set(tab.gamma = true, tab.beta = " cheesecake "));
|
||||||
|
testSelectAll(db, 3);
|
||||||
|
|
||||||
|
// test functions and operators
|
||||||
|
db(select(all_of(tab)).from(tab).where(tab.alpha.is_null()));
|
||||||
|
db(select(all_of(tab)).from(tab).where(tab.alpha.is_not_null()));
|
||||||
|
db(select(all_of(tab)).from(tab).where(tab.alpha.in(1, 2, 3)));
|
||||||
|
db(select(all_of(tab)).from(tab).where(tab.alpha.in(sqlpp::value_list(std::vector<int>{1, 2, 3, 4}))));
|
||||||
|
db(select(all_of(tab)).from(tab).where(tab.alpha.not_in(1, 2, 3)));
|
||||||
|
db(select(all_of(tab)).from(tab).where(tab.alpha.not_in(sqlpp::value_list(std::vector<int>{1, 2, 3, 4}))));
|
||||||
|
db(select(count(tab.alpha)).from(tab).unconditionally());
|
||||||
|
db(select(avg(tab.alpha)).from(tab).unconditionally());
|
||||||
|
db(select(max(tab.alpha)).from(tab).unconditionally());
|
||||||
|
db(select(min(tab.alpha)).from(tab).unconditionally());
|
||||||
|
db(select(exists(select(tab.alpha).from(tab).where(tab.alpha > 7))).from(tab).unconditionally());
|
||||||
|
db(select(trim(tab.beta)).from(tab).unconditionally());
|
||||||
|
|
||||||
|
// db(select(not_exists(select(tab.alpha).from(tab).where(tab.alpha > 7))).from(tab));
|
||||||
|
// db(select(all_of(tab)).from(tab).where(tab.alpha == any(select(tab.alpha).from(tab).where(tab.alpha < 3))));
|
||||||
|
|
||||||
|
db(select(all_of(tab)).from(tab).where((tab.alpha + tab.alpha) > 3));
|
||||||
|
db(select(all_of(tab)).from(tab).where((tab.beta + tab.beta) == ""));
|
||||||
|
db(select(all_of(tab)).from(tab).where((tab.beta + tab.beta).like(R"(%'\"%)")));
|
||||||
|
|
||||||
|
// update
|
||||||
|
db(update(tab).set(tab.gamma = false).where(tab.alpha.in(1)));
|
||||||
|
db(update(tab).set(tab.gamma = false).where(tab.alpha.in(sqlpp::value_list(std::vector<int>{1, 2, 3, 4}))));
|
||||||
|
|
||||||
|
// remove
|
||||||
|
db(remove_from(tab).where(tab.alpha == tab.alpha + 3));
|
||||||
|
|
||||||
|
auto result = db(select(all_of(tab)).from(tab).unconditionally());
|
||||||
|
std::cerr << "Accessing a field directly from the result (using the current row): " << result.begin()->alpha
|
||||||
|
<< std::endl;
|
||||||
|
std::cerr << "Can do that again, no problem: " << result.begin()->alpha << std::endl;
|
||||||
|
|
||||||
|
std::cerr << "--------------------------------------" << std::endl;
|
||||||
|
auto tx = start_transaction(db);
|
||||||
|
for (const auto& row : db(select(all_of(tab), select(max(tab.alpha)).from(tab)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
int x = row.alpha;
|
||||||
|
int a = row.max;
|
||||||
|
std::cout << ">>>" << x << ", " << a << std::endl;
|
||||||
|
}
|
||||||
|
for (const auto& row :
|
||||||
|
db(select(tab.alpha, tab.beta, tab.gamma, trim(tab.beta))
|
||||||
|
.from(tab)
|
||||||
|
.unconditionally()))
|
||||||
|
{
|
||||||
|
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
||||||
|
<< ", row.trim: '" << row.trim << "'" << std::endl;
|
||||||
|
// check trim
|
||||||
|
assert(string_util::trim(row.beta.value()) == row.trim.value());
|
||||||
|
// end
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& row : db(select(all_of(tab), select(trim(tab.beta)).from(tab)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
int x = row.alpha;
|
||||||
|
std::string a = row.trim;
|
||||||
|
std::cout << ">>>" << x << ", " << a << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.commit();
|
||||||
|
std::cerr << "--------------------------------------" << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
250
tests/sqlite3/usage/TabSample.h
Normal file
250
tests/sqlite3/usage/TabSample.h
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2015, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_TAB_SAMPLE_H
|
||||||
|
#define SQLPP_TAB_SAMPLE_H
|
||||||
|
|
||||||
|
#include <sqlpp11/table.h>
|
||||||
|
#include <sqlpp11/char_sequence.h>
|
||||||
|
#include <sqlpp11/column_types.h>
|
||||||
|
|
||||||
|
namespace TabFoo_
|
||||||
|
{
|
||||||
|
struct Omega
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "omega";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T omega;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return omega;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return omega;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = ::sqlpp::make_traits<::sqlpp::bigint>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TabFoo : sqlpp::table_t<TabFoo, TabFoo_::Omega>
|
||||||
|
{
|
||||||
|
using _value_type = sqlpp::no_value_t;
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "tab_foo";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T tabFoo;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return tabFoo;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return tabFoo;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace TabSample_
|
||||||
|
{
|
||||||
|
struct Alpha
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "alpha";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T alpha;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = ::sqlpp::make_traits<::sqlpp::bigint,
|
||||||
|
::sqlpp::tag::must_not_insert,
|
||||||
|
::sqlpp::tag::must_not_update,
|
||||||
|
::sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Beta
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "beta";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T beta;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return beta;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return beta;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = ::sqlpp::make_traits<::sqlpp::varchar, ::sqlpp::tag::must_not_update, ::sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Gamma
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "gamma";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T gamma;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return gamma;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return gamma;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = ::sqlpp::make_traits<::sqlpp::boolean>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TabSample : sqlpp::table_t<TabSample, TabSample_::Alpha, TabSample_::Beta, TabSample_::Gamma>
|
||||||
|
{
|
||||||
|
using _value_type = sqlpp::no_value_t;
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "tab_sample";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T tabSample;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return tabSample;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return tabSample;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace TabDateTime_
|
||||||
|
{
|
||||||
|
struct ColDayPoint
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "col_day_point";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T colDayPoint;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return colDayPoint;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return colDayPoint;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = sqlpp::make_traits<sqlpp::day_point, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
struct ColTimePoint
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "col_time_point";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T colTimePoint;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return colTimePoint;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return colTimePoint;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
using _traits = sqlpp::make_traits<sqlpp::time_point, sqlpp::tag::can_be_null>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TabDateTime : sqlpp::table_t<TabDateTime, TabDateTime_::ColDayPoint, TabDateTime_::ColTimePoint>
|
||||||
|
{
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
static constexpr const char _literal[] = "tab_date_time";
|
||||||
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
|
template <typename T>
|
||||||
|
struct _member_t
|
||||||
|
{
|
||||||
|
T tabDateTime;
|
||||||
|
T& operator()()
|
||||||
|
{
|
||||||
|
return tabDateTime;
|
||||||
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return tabDateTime;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
5
tests/sqlite3/usage/TabSample.sql
Normal file
5
tests/sqlite3/usage/TabSample.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE tab_sample (
|
||||||
|
alpha bigint(20) DEFAULT NULL,
|
||||||
|
beta tinyint(1) DEFAULT NULL,
|
||||||
|
gamma varchar(255) DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
84
tests/sqlite3/usage/TransactionTest.cpp
Normal file
84
tests/sqlite3/usage/TransactionTest.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TabSample.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <sqlpp11/alias_provider.h>
|
||||||
|
#include <sqlpp11/custom_query.h>
|
||||||
|
#include <sqlpp11/functions.h>
|
||||||
|
#include <sqlpp11/insert.h>
|
||||||
|
#include <sqlpp11/remove.h>
|
||||||
|
#include <sqlpp11/select.h>
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
#include <sqlpp11/transaction.h>
|
||||||
|
#include <sqlpp11/update.h>
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
|
||||||
|
SQLPP_ALIAS_PROVIDER(pragma)
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection db({":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "", true});
|
||||||
|
|
||||||
|
std::cerr << "--------------------------------------" << std::endl;
|
||||||
|
|
||||||
|
auto current_level = db.get_default_isolation_level();
|
||||||
|
std::cout << "Expecting default isolation level = 1, is " << static_cast<int>(current_level) << std::endl;
|
||||||
|
assert(current_level == sqlpp::isolation_level::serializable);
|
||||||
|
|
||||||
|
int pragmaValue = db(custom_query(sqlpp::verbatim("PRAGMA read_uncommitted"))
|
||||||
|
.with_result_type_of(select(sqlpp::value(1).as(pragma))))
|
||||||
|
.front()
|
||||||
|
.pragma;
|
||||||
|
assert(pragmaValue == 0);
|
||||||
|
|
||||||
|
std::cerr << "Expecting read_uncommitted = 0, is: " << pragmaValue << std::endl;
|
||||||
|
db.set_default_isolation_level(sqlpp::isolation_level::read_uncommitted);
|
||||||
|
auto tx = start_transaction(db);
|
||||||
|
pragmaValue = db(custom_query(sqlpp::verbatim("PRAGMA read_uncommitted"))
|
||||||
|
.with_result_type_of(select(sqlpp::value(1).as(pragma))))
|
||||||
|
.front()
|
||||||
|
.pragma;
|
||||||
|
std::cerr << "Now expecting read_uncommitted = 1, is: " << pragmaValue << std::endl;
|
||||||
|
assert(pragmaValue == 1);
|
||||||
|
|
||||||
|
current_level = db.get_default_isolation_level();
|
||||||
|
std::cout << "Now expecting default isolation level = 4, is " << static_cast<int>(current_level) << std::endl;
|
||||||
|
assert(current_level == sqlpp::isolation_level::read_uncommitted);
|
||||||
|
|
||||||
|
tx.commit();
|
||||||
|
std::cerr << "--------------------------------------" << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
67
tests/sqlite3/usage/UnionTest.cpp
Normal file
67
tests/sqlite3/usage/UnionTest.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 - 2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TabSample.h"
|
||||||
|
#include <sqlpp11/sqlite3/connection.h>
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#ifdef SQLPP_USE_SQLCIPHER
|
||||||
|
#include <sqlcipher/sqlite3.h>
|
||||||
|
#else
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace sql = sqlpp::sqlite3;
|
||||||
|
const auto tab = TabSample{};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
sql::connection_config config;
|
||||||
|
config.path_to_database = ":memory:";
|
||||||
|
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
config.debug = true;
|
||||||
|
|
||||||
|
sql::connection db(config);
|
||||||
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
|
alpha INTEGER PRIMARY KEY,
|
||||||
|
beta varchar(255) DEFAULT NULL,
|
||||||
|
gamma bool DEFAULT NULL
|
||||||
|
))");
|
||||||
|
|
||||||
|
auto u = select(all_of(tab)).from(tab).unconditionally().union_all(select(all_of(tab)).from(tab).unconditionally());
|
||||||
|
|
||||||
|
for (const auto& row : db(u))
|
||||||
|
{
|
||||||
|
std::cout << row.alpha << row.beta << row.gamma << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& row : db(u.union_distinct(select(all_of(tab)).from(tab).unconditionally())))
|
||||||
|
{
|
||||||
|
std::cout << row.alpha << row.beta << row.gamma << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user