mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Make sqlite3 connector header-only
This commit is contained in:
parent
2bb68cc443
commit
64aba48cb9
@ -78,9 +78,6 @@ add_subdirectory(dependencies)
|
|||||||
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
|
||||||
|
@ -28,8 +28,11 @@
|
|||||||
#define SQLPP_SQLITE3_BIND_RESULT_H
|
#define SQLPP_SQLITE3_BIND_RESULT_H
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
#include <sqlpp11/chrono.h>
|
#include <sqlpp11/chrono.h>
|
||||||
|
#include <sqlpp11/exception.h>
|
||||||
#include <sqlpp11/sqlite3/export.h>
|
#include <sqlpp11/sqlite3/export.h>
|
||||||
|
#include <sqlpp11/sqlite3/prepared_statement_handle.h>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
@ -42,8 +45,33 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
struct prepared_statement_handle_t;
|
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 detail
|
||||||
|
|
||||||
class SQLPP11_SQLITE3_EXPORT bind_result_t
|
class SQLPP11_SQLITE3_EXPORT bind_result_t
|
||||||
{
|
{
|
||||||
@ -51,7 +79,12 @@ namespace sqlpp
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
bind_result_t() = default;
|
bind_result_t() = default;
|
||||||
bind_result_t(const std::shared_ptr<detail::prepared_statement_handle_t>& handle);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
bind_result_t(const bind_result_t&) = delete;
|
bind_result_t(const bind_result_t&) = delete;
|
||||||
bind_result_t(bind_result_t&& rhs) = default;
|
bind_result_t(bind_result_t&& rhs) = default;
|
||||||
bind_result_t& operator=(const bind_result_t&) = delete;
|
bind_result_t& operator=(const bind_result_t&) = delete;
|
||||||
@ -87,17 +120,172 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_boolean_result(size_t index, signed char* value, bool* is_null);
|
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);
|
if (_handle->debug)
|
||||||
void _bind_unsigned_integral_result(size_t index, uint64_t* value, bool* is_null);
|
std::cerr << "Sqlite3 debug: binding boolean result " << *value << " at index: " << index << std::endl;
|
||||||
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);
|
*value = static_cast<signed char>(sqlite3_column_int(_handle->sqlite_statement, static_cast<int>(index)));
|
||||||
void _bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null);
|
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
||||||
void _bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null);
|
}
|
||||||
|
|
||||||
|
void _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_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_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_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_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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _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 (detail::check_digits(date_string, detail::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_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 (detail::check_digits(date_time_string, detail::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 (detail::check_digits(time_string, detail::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 (detail::check_digits(ms_string, detail::ms_digits) and ms_string[4] == '\0')
|
||||||
|
{
|
||||||
|
*value += ::std::chrono::milliseconds(std::atoi(ms_string + 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool next_impl();
|
bool 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 sqlite3
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
@ -33,17 +33,22 @@
|
|||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sqlpp11/connection.h>
|
#include <sqlpp11/connection.h>
|
||||||
|
#include <sqlpp11/exception.h>
|
||||||
#include <sqlpp11/schema.h>
|
#include <sqlpp11/schema.h>
|
||||||
#include <sqlpp11/serialize.h>
|
#include <sqlpp11/serialize.h>
|
||||||
#include <sqlpp11/sqlite3/bind_result.h>
|
#include <sqlpp11/sqlite3/bind_result.h>
|
||||||
#include <sqlpp11/sqlite3/connection_config.h>
|
#include <sqlpp11/sqlite3/connection_config.h>
|
||||||
#include <sqlpp11/sqlite3/prepared_statement.h>
|
#include <sqlpp11/sqlite3/prepared_statement.h>
|
||||||
|
#include <sqlpp11/sqlite3/export.h>
|
||||||
#include <sqlpp11/transaction.h>
|
#include <sqlpp11/transaction.h>
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/sqlite3/export.h>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
#include <sqlpp11/sqlite3/dynamic_libsqlite3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable:4251)
|
#pragma warning(disable:4251)
|
||||||
@ -53,9 +58,97 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
namespace sqlite3
|
namespace sqlite3
|
||||||
{
|
{
|
||||||
|
#ifdef SQLPP_DYNAMIC_LOADING
|
||||||
|
using namespace dynamic;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
struct connection_handle;
|
struct connection_handle
|
||||||
|
{
|
||||||
|
connection_config config;
|
||||||
|
::sqlite3* sqlite;
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
auto rc = sqlite3_close(sqlite);
|
||||||
|
if (rc != SQLITE_OK)
|
||||||
|
{
|
||||||
|
std::cerr << "Sqlite3 error: Can't close database: " << sqlite3_errmsg(sqlite) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connection_handle(const connection_handle&) = delete;
|
||||||
|
connection_handle(connection_handle&&) = delete;
|
||||||
|
connection_handle& operator=(const connection_handle&) = delete;
|
||||||
|
connection_handle& operator=(connection_handle&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class connection;
|
class connection;
|
||||||
@ -107,18 +200,81 @@ namespace sqlpp
|
|||||||
transaction_status_type _transaction_status = transaction_status_type::none;
|
transaction_status_type _transaction_status = transaction_status_type::none;
|
||||||
|
|
||||||
// direct execution
|
// direct execution
|
||||||
bind_result_t select_impl(const std::string& statement);
|
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);
|
std::unique_ptr<detail::prepared_statement_handle_t> prepared(
|
||||||
size_t remove_impl(const std::string& statement);
|
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)};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t insert_impl(const std::string& statement)
|
||||||
|
{
|
||||||
|
auto prepared = prepare_statement(*_handle, statement);
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
|
||||||
|
return sqlite3_last_insert_rowid(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t update_impl(const std::string& statement)
|
||||||
|
{
|
||||||
|
auto prepared = prepare_statement(*_handle, statement);
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t remove_impl(const std::string& statement)
|
||||||
|
{
|
||||||
|
auto prepared = prepare_statement(*_handle, statement);
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// prepared execution
|
// prepared execution
|
||||||
prepared_statement_t prepare_impl(const std::string& statement);
|
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);
|
return {std::unique_ptr<detail::prepared_statement_handle_t>(
|
||||||
size_t run_prepared_insert_impl(prepared_statement_t& prepared_statement);
|
new detail::prepared_statement_handle_t(prepare_statement(*_handle, statement)))};
|
||||||
size_t run_prepared_update_impl(prepared_statement_t& prepared_statement);
|
}
|
||||||
size_t run_prepared_remove_impl(prepared_statement_t& prepared_statement);
|
|
||||||
|
bind_result_t run_prepared_select_impl(prepared_statement_t& prepared_statement)
|
||||||
|
{
|
||||||
|
return {prepared_statement._handle};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t 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 run_prepared_update_impl(prepared_statement_t& prepared_statement)
|
||||||
|
{
|
||||||
|
execute_statement(*_handle, *prepared_statement._handle.get());
|
||||||
|
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t run_prepared_remove_impl(prepared_statement_t& prepared_statement)
|
||||||
|
{
|
||||||
|
execute_statement(*_handle, *prepared_statement._handle.get());
|
||||||
|
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t run_prepared_execute_impl(prepared_statement_t& prepared_statement)
|
||||||
|
{
|
||||||
|
execute_statement(*_handle, *prepared_statement._handle.get());
|
||||||
|
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using _prepared_statement_t = prepared_statement_t;
|
using _prepared_statement_t = prepared_statement_t;
|
||||||
@ -143,10 +299,15 @@ namespace sqlpp
|
|||||||
return ::sqlpp::serialize(t, context);
|
return ::sqlpp::serialize(t, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
connection(connection_config config);
|
connection(connection_config config) : _handle(new detail::connection_handle(std::move(config)))
|
||||||
connection(connection&&) noexcept;
|
{
|
||||||
connection& operator=(connection&&) noexcept;
|
}
|
||||||
~connection();
|
|
||||||
|
connection(connection&&) noexcept = default;
|
||||||
|
connection& operator=(connection&&) noexcept = default;
|
||||||
|
|
||||||
|
~connection() = default;
|
||||||
|
|
||||||
connection(const connection&) = delete;
|
connection(const connection&) = delete;
|
||||||
connection& operator=(const connection&) = delete;
|
connection& operator=(const connection&) = delete;
|
||||||
|
|
||||||
@ -251,7 +412,12 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! execute arbitrary command (e.g. create a table)
|
//! execute arbitrary command (e.g. create a table)
|
||||||
size_t execute(const std::string& command);
|
size_t execute(const std::string& statement)
|
||||||
|
{
|
||||||
|
auto prepared = prepare_statement(*_handle, statement);
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
return sqlite3_changes(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename Execute,
|
typename Execute,
|
||||||
@ -280,7 +446,20 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! escape given string (does not quote, though)
|
//! escape given string (does not quote, though)
|
||||||
std::string escape(const std::string& s) const;
|
std::string 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;
|
||||||
|
}
|
||||||
|
|
||||||
//! call run on the argument
|
//! call run on the argument
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -317,30 +496,98 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! set the transaction isolation level for this connection
|
//! set the transaction isolation level for this connection
|
||||||
void set_default_isolation_level(isolation_level level);
|
void 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//! get the currently active transaction isolation level
|
//! get the currently active transaction isolation level
|
||||||
isolation_level get_default_isolation_level();
|
sqlpp::isolation_level 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;
|
||||||
|
}
|
||||||
|
|
||||||
//! start transaction
|
//! start transaction
|
||||||
void start_transaction();
|
void 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;
|
||||||
|
}
|
||||||
|
|
||||||
//! commit transaction (or throw if the transaction has been finished already)
|
//! commit transaction (or throw if the transaction has been finished already)
|
||||||
void commit_transaction();
|
void 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;
|
||||||
|
}
|
||||||
|
|
||||||
//! rollback transaction with or without reporting the rollback (or throw if the transaction has been finished
|
//! rollback transaction with or without reporting the rollback (or throw if the transaction has been finished
|
||||||
// already)
|
// already)
|
||||||
void rollback_transaction(bool report);
|
void 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;
|
||||||
|
}
|
||||||
|
|
||||||
//! report a rollback failure (will be called by transactions in case of a rollback failure in the destructor)
|
//! 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;
|
void report_rollback_failure(const std::string message) noexcept
|
||||||
|
{
|
||||||
|
std::cerr << "Sqlite3 message:" << message << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
//! get the last inserted id
|
//! get the last inserted id
|
||||||
uint64_t last_insert_id() noexcept;
|
uint64_t last_insert_id() noexcept
|
||||||
|
{
|
||||||
|
return sqlite3_last_insert_rowid(_handle->sqlite);
|
||||||
|
}
|
||||||
|
|
||||||
::sqlite3* native_handle();
|
::sqlite3* native_handle()
|
||||||
|
{
|
||||||
|
return _handle->sqlite;
|
||||||
|
}
|
||||||
|
|
||||||
auto attach(const connection_config&, const std::string name) -> schema_t;
|
schema_t attach(const connection_config& config, const std::string name)
|
||||||
|
{
|
||||||
|
auto prepared =
|
||||||
|
prepare_statement(*_handle, "ATTACH '" + escape(config.path_to_database) + "' AS " + escape(name));
|
||||||
|
execute_statement(*_handle, prepared);
|
||||||
|
|
||||||
|
return {name};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::string serializer_t::escape(std::string arg)
|
inline std::string serializer_t::escape(std::string arg)
|
||||||
|
@ -28,10 +28,16 @@
|
|||||||
#define SQLPP_SQLITE3_PREPARED_STATEMENT_H
|
#define SQLPP_SQLITE3_PREPARED_STATEMENT_H
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sqlpp11/chrono.h>
|
#include <ciso646>
|
||||||
#include <sqlpp11/sqlite3/export.h>
|
#include <cmath>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <date/date.h>
|
||||||
|
|
||||||
|
#include <sqlpp11/chrono.h>
|
||||||
|
#include <sqlpp11/sqlite3/export.h>
|
||||||
|
|
||||||
|
#include <sqlpp11/sqlite3/prepared_statement_handle.h>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
@ -42,12 +48,28 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
namespace sqlite3
|
namespace sqlite3
|
||||||
{
|
{
|
||||||
class connection;
|
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
struct prepared_statement_handle_t;
|
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 detail
|
||||||
|
|
||||||
|
class connection;
|
||||||
|
|
||||||
class SQLPP11_SQLITE3_EXPORT prepared_statement_t
|
class SQLPP11_SQLITE3_EXPORT prepared_statement_t
|
||||||
{
|
{
|
||||||
@ -56,7 +78,12 @@ namespace sqlpp
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
prepared_statement_t() = default;
|
prepared_statement_t() = default;
|
||||||
prepared_statement_t(std::shared_ptr<detail::prepared_statement_handle_t>&& handle);
|
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;
|
||||||
|
}
|
||||||
prepared_statement_t(const prepared_statement_t&) = delete;
|
prepared_statement_t(const prepared_statement_t&) = delete;
|
||||||
prepared_statement_t(prepared_statement_t&& rhs) = default;
|
prepared_statement_t(prepared_statement_t&& rhs) = default;
|
||||||
prepared_statement_t& operator=(const prepared_statement_t&) = delete;
|
prepared_statement_t& operator=(const prepared_statement_t&) = delete;
|
||||||
@ -68,15 +95,158 @@ namespace sqlpp
|
|||||||
return _handle == rhs._handle;
|
return _handle == rhs._handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _reset();
|
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);
|
if (_handle->debug)
|
||||||
void _bind_integral_parameter(size_t index, const int64_t* value, bool is_null);
|
std::cerr << "Sqlite3 debug: resetting prepared statement" << std::endl;
|
||||||
void _bind_unsigned_integral_parameter(size_t index, const uint64_t* value, bool is_null);
|
sqlite3_reset(_handle->sqlite_statement);
|
||||||
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_boolean_parameter(size_t index, const signed char* value, bool is_null)
|
||||||
void _bind_blob_parameter(size_t index, const std::vector<uint8_t>* 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));
|
||||||
|
detail::check_bind_result(result, "boolean");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _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));
|
||||||
|
detail::check_bind_result(result, "floating_point");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _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));
|
||||||
|
detail::check_bind_result(result, "integral");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _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));
|
||||||
|
detail::check_bind_result(result, "integral");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _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));
|
||||||
|
detail::check_bind_result(result, "text");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _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));
|
||||||
|
detail::check_bind_result(result, "date");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _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));
|
||||||
|
detail::check_bind_result(result, "date");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _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));
|
||||||
|
detail::check_bind_result(result, "blob");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace sqlite3
|
} // namespace sqlite3
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
@ -24,26 +24,26 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SQLPP_SQLITE3_DETAIL_PREPARED_STATEMENT_HANDLE_H
|
#ifndef SQLPP_SQLITE3_PREPARED_STATEMENT_HANDLE_H
|
||||||
#define SQLPP_SQLITE3_DETAIL_PREPARED_STATEMENT_HANDLE_H
|
#define SQLPP_SQLITE3_PREPARED_STATEMENT_HANDLE_H
|
||||||
|
|
||||||
#ifdef SQLPP_USE_SQLCIPHER
|
#include <memory>
|
||||||
#include <sqlcipher/sqlite3.h>
|
#include <sqlpp11/chrono.h>
|
||||||
#else
|
#include <sqlpp11/sqlite3/export.h>
|
||||||
#include <sqlite3.h>
|
#include <string>
|
||||||
#endif
|
#include <vector>
|
||||||
|
|
||||||
#ifdef SQLPP_DYNAMIC_LOADING
|
#ifdef _MSC_VER
|
||||||
#include <sqlpp11/sqlite3/dynamic_libsqlite3.h>
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace sqlite3
|
namespace sqlite3
|
||||||
{
|
{
|
||||||
#ifdef SQLPP_DYNAMIC_LOADING
|
class connection;
|
||||||
using namespace dynamic;
|
|
||||||
#endif
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
struct prepared_statement_handle_t
|
struct prepared_statement_handle_t
|
||||||
@ -89,8 +89,13 @@ namespace sqlpp
|
|||||||
return !sqlite_statement;
|
return !sqlite_statement;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace detail
|
}
|
||||||
} // namespace sqlite3
|
|
||||||
|
} // namespace sqlite3
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,27 +0,0 @@
|
|||||||
# 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(SQLITE3_CONNECTOR OR SQLCIPHER_CONNECTOR)
|
|
||||||
add_subdirectory(sqlite3)
|
|
||||||
endif()
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
|||||||
set(PUBLIC_HEADERS_DIR "${PROJECT_SOURCE_DIR}/include/")
|
|
||||||
|
|
||||||
add_library(sqlpp-mysql
|
|
||||||
bind_result.cpp
|
|
||||||
char_result.cpp
|
|
||||||
connection.cpp
|
|
||||||
prepared_statement.cpp
|
|
||||||
detail/connection_handle.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(sqlpp-mysql PUBLIC
|
|
||||||
$<BUILD_INTERFACE:${PUBLIC_HEADERS_DIR}>
|
|
||||||
)
|
|
||||||
|
|
||||||
find_package(date REQUIRED)
|
|
||||||
find_package(Sqlpp11 REQUIRED)
|
|
||||||
|
|
||||||
target_link_libraries(sqlpp-mysql PUBLIC sqlpp11::sqlpp11)
|
|
||||||
target_link_libraries(sqlpp-mysql PRIVATE MySQL::MySQL)
|
|
||||||
target_link_libraries(sqlpp-mysql PRIVATE date::date)
|
|
||||||
|
|
||||||
# Installation
|
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
|
|
||||||
add_library(sqlpp11::mysql ALIAS sqlpp-mysql)
|
|
||||||
set_target_properties(sqlpp-mysql PROPERTIES EXPORT_NAME sqlpp11::mysql)
|
|
||||||
|
|
||||||
install(
|
|
||||||
TARGETS sqlpp-mysql
|
|
||||||
EXPORT sqlpp-mysql-targets
|
|
||||||
COMPONENT sqlpp11::mysql
|
|
||||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
|
||||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
|
||||||
DIRECTORY ${PUBLIC_HEADERS_DIR}
|
|
||||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
|
||||||
COMPONENT sqlpp11::mysql
|
|
||||||
)
|
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
|
|
||||||
set(cmake_config_path "${CMAKE_INSTALL_LIBDIR}/cmake/sqlpp-mysql")
|
|
||||||
|
|
||||||
configure_package_config_file(
|
|
||||||
sqlpp-mysql-config.cmake.in
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/sqlpp-mysql-config.cmake"
|
|
||||||
INSTALL_DESTINATION "${cmake_config_path}"
|
|
||||||
)
|
|
||||||
|
|
||||||
write_basic_package_version_file(
|
|
||||||
sqlpp-mysql-config-version.cmake
|
|
||||||
VERSION ${VERSION}
|
|
||||||
COMPATIBILITY SameMajorVersion
|
|
||||||
${extra_version_file_args}
|
|
||||||
)
|
|
||||||
|
|
||||||
install(FILES
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/sqlpp-mysql-config.cmake"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/sqlpp-mysql-config-version.cmake"
|
|
||||||
DESTINATION "${cmake_config_path}"
|
|
||||||
COMPONENT sqlpp11::mysql
|
|
||||||
)
|
|
||||||
|
|
||||||
install(FILES
|
|
||||||
"${PROJECT_SOURCE_DIR}/cmake/FindMySQL.cmake"
|
|
||||||
DESTINATION "${cmake_config_path}"
|
|
||||||
COMPONENT sqlpp11::mysql
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
|
||||||
EXPORT sqlpp-mysql-targets
|
|
||||||
FILE sqlpp-mysql-targets.cmake
|
|
||||||
DESTINATION "${cmake_config_path}"
|
|
||||||
COMPONENT sqlpp11::mysql
|
|
||||||
)
|
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <date/date.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include "sqlpp_mysql.h"
|
|
||||||
#include <sqlpp11/exception.h>
|
|
||||||
#include <sqlpp11/mysql/bind_result.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace mysql
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 "detail/result_handle.h"
|
|
||||||
#include <cctype>
|
|
||||||
#include <ciso646>
|
|
||||||
#include <date/date.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sqlpp11/mysql/char_result.h>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace mysql
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <ciso646>
|
|
||||||
#include <iostream>
|
|
||||||
#include "detail/connection_handle.h"
|
|
||||||
#include "detail/prepared_statement_handle.h"
|
|
||||||
#include "detail/result_handle.h"
|
|
||||||
#include <sqlpp11/exception.h>
|
|
||||||
#include <sqlpp11/mysql/connection.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace mysql
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,293 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <ciso646>
|
|
||||||
#include <iostream>
|
|
||||||
#include "detail/connection_handle.h"
|
|
||||||
#include "detail/prepared_statement_handle.h"
|
|
||||||
#include "detail/result_handle.h"
|
|
||||||
#include <sqlpp11/exception.h>
|
|
||||||
#include <sqlpp11/mysql/connection.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace mysql
|
|
||||||
{
|
|
||||||
scoped_library_initializer_t::scoped_library_initializer_t(int argc, char** argv, char** groups)
|
|
||||||
{
|
|
||||||
mysql_library_init(argc, argv, groups);
|
|
||||||
}
|
|
||||||
|
|
||||||
scoped_library_initializer_t::~scoped_library_initializer_t()
|
|
||||||
{
|
|
||||||
mysql_library_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void global_library_init(int argc, char** argv, char** groups)
|
|
||||||
{
|
|
||||||
static const auto global_init_and_end = scoped_library_initializer_t(argc, argv, groups);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
struct MySqlThreadInitializer
|
|
||||||
{
|
|
||||||
MySqlThreadInitializer()
|
|
||||||
{
|
|
||||||
if (!mysql_thread_safe())
|
|
||||||
{
|
|
||||||
throw sqlpp::exception("MySQL error: Operating on a non-threadsafe client");
|
|
||||||
}
|
|
||||||
mysql_thread_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
~MySqlThreadInitializer()
|
|
||||||
{
|
|
||||||
mysql_thread_end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void thread_init()
|
|
||||||
{
|
|
||||||
thread_local MySqlThreadInitializer threadInitializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute_statement(detail::connection_handle_t& handle, const std::string& statement)
|
|
||||||
{
|
|
||||||
thread_init();
|
|
||||||
|
|
||||||
if (handle.config->debug)
|
|
||||||
std::cerr << "MySQL debug: Executing: '" << statement << "'" << std::endl;
|
|
||||||
|
|
||||||
if (mysql_query(handle.mysql.get(), statement.c_str()))
|
|
||||||
{
|
|
||||||
throw sqlpp::exception("MySQL error: Could not execute MySQL-statement: " +
|
|
||||||
std::string(mysql_error(handle.mysql.get())) + " (statement was >>" + statement +
|
|
||||||
"<<\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute_prepared_statement(detail::prepared_statement_handle_t& prepared_statement)
|
|
||||||
{
|
|
||||||
thread_init();
|
|
||||||
|
|
||||||
if (prepared_statement.debug)
|
|
||||||
std::cerr << "MySQL debug: Executing prepared_statement" << std::endl;
|
|
||||||
|
|
||||||
if (mysql_stmt_bind_param(prepared_statement.mysql_stmt, prepared_statement.stmt_params.data()))
|
|
||||||
{
|
|
||||||
throw sqlpp::exception(std::string("MySQL error: Could not bind parameters to statement") +
|
|
||||||
mysql_stmt_error(prepared_statement.mysql_stmt));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mysql_stmt_execute(prepared_statement.mysql_stmt))
|
|
||||||
{
|
|
||||||
throw sqlpp::exception(std::string("MySQL error: Could not execute prepared statement: ") +
|
|
||||||
mysql_stmt_error(prepared_statement.mysql_stmt));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<detail::prepared_statement_handle_t> prepare_statement(detail::connection_handle_t& handle,
|
|
||||||
const std::string& statement,
|
|
||||||
size_t no_of_parameters,
|
|
||||||
size_t no_of_columns)
|
|
||||||
{
|
|
||||||
thread_init();
|
|
||||||
|
|
||||||
if (handle.config->debug)
|
|
||||||
std::cerr << "MySQL debug: Preparing: '" << statement << "'" << std::endl;
|
|
||||||
|
|
||||||
auto prepared_statement = std::make_shared<detail::prepared_statement_handle_t>(
|
|
||||||
mysql_stmt_init(handle.mysql.get()), no_of_parameters, no_of_columns, handle.config->debug);
|
|
||||||
if (not prepared_statement)
|
|
||||||
{
|
|
||||||
throw sqlpp::exception("MySQL error: Could not allocate prepared statement\n");
|
|
||||||
}
|
|
||||||
if (mysql_stmt_prepare(prepared_statement->mysql_stmt, statement.data(), statement.size()))
|
|
||||||
{
|
|
||||||
throw sqlpp::exception("MySQL error: Could not prepare statement: " +
|
|
||||||
std::string(mysql_error(handle.mysql.get())) + " (statement was >>" + statement +
|
|
||||||
"<<\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return prepared_statement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
connection::connection(const std::shared_ptr<connection_config>& config)
|
|
||||||
: _handle(new detail::connection_handle_t(config))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
connection::~connection()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
connection::connection(connection&& other)
|
|
||||||
{
|
|
||||||
this->_transaction_active = other._transaction_active;
|
|
||||||
this->_handle = std::move(other._handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool connection::is_valid()
|
|
||||||
{
|
|
||||||
return _handle->is_valid();
|
|
||||||
}
|
|
||||||
void connection::reconnect()
|
|
||||||
{
|
|
||||||
return _handle->reconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::shared_ptr<connection_config> connection::get_config()
|
|
||||||
{
|
|
||||||
return _handle->config;
|
|
||||||
}
|
|
||||||
|
|
||||||
char_result_t connection::select_impl(const std::string& statement)
|
|
||||||
{
|
|
||||||
execute_statement(*_handle, statement);
|
|
||||||
std::unique_ptr<detail::result_handle> result_handle(
|
|
||||||
new detail::result_handle(mysql_store_result(_handle->mysql.get()), _handle->config->debug));
|
|
||||||
if (!*result_handle)
|
|
||||||
{
|
|
||||||
throw sqlpp::exception("MySQL error: Could not store result set: " +
|
|
||||||
std::string(mysql_error(_handle->mysql.get())));
|
|
||||||
}
|
|
||||||
|
|
||||||
return {std::move(result_handle)};
|
|
||||||
}
|
|
||||||
|
|
||||||
bind_result_t connection::run_prepared_select_impl(prepared_statement_t& prepared_statement)
|
|
||||||
{
|
|
||||||
execute_prepared_statement(*prepared_statement._handle);
|
|
||||||
return prepared_statement._handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t connection::run_prepared_insert_impl(prepared_statement_t& prepared_statement)
|
|
||||||
{
|
|
||||||
execute_prepared_statement(*prepared_statement._handle);
|
|
||||||
return mysql_stmt_insert_id(prepared_statement._handle->mysql_stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t connection::run_prepared_update_impl(prepared_statement_t& prepared_statement)
|
|
||||||
{
|
|
||||||
execute_prepared_statement(*prepared_statement._handle);
|
|
||||||
return mysql_stmt_affected_rows(prepared_statement._handle->mysql_stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t connection::run_prepared_remove_impl(prepared_statement_t& prepared_statement)
|
|
||||||
{
|
|
||||||
execute_prepared_statement(*prepared_statement._handle);
|
|
||||||
return mysql_stmt_affected_rows(prepared_statement._handle->mysql_stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
prepared_statement_t connection::prepare_impl(const std::string& statement,
|
|
||||||
size_t no_of_parameters,
|
|
||||||
size_t no_of_columns)
|
|
||||||
{
|
|
||||||
return prepare_statement(*_handle, statement, no_of_parameters, no_of_columns);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t connection::insert_impl(const std::string& statement)
|
|
||||||
{
|
|
||||||
execute_statement(*_handle, statement);
|
|
||||||
|
|
||||||
return mysql_insert_id(_handle->mysql.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void connection::execute(const std::string& command)
|
|
||||||
{
|
|
||||||
execute_statement(*_handle, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t connection::update_impl(const std::string& statement)
|
|
||||||
{
|
|
||||||
execute_statement(*_handle, statement);
|
|
||||||
return mysql_affected_rows(_handle->mysql.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t connection::remove_impl(const std::string& statement)
|
|
||||||
{
|
|
||||||
execute_statement(*_handle, statement);
|
|
||||||
return mysql_affected_rows(_handle->mysql.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string connection::escape(const std::string& s) const
|
|
||||||
{
|
|
||||||
std::unique_ptr<char[]> dest(new char[s.size() * 2 + 1]);
|
|
||||||
mysql_real_escape_string(_handle->mysql.get(), dest.get(), s.c_str(), s.size());
|
|
||||||
return dest.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void connection::start_transaction()
|
|
||||||
{
|
|
||||||
if (_transaction_active)
|
|
||||||
{
|
|
||||||
throw sqlpp::exception("MySQL: Cannot have more than one open transaction per connection");
|
|
||||||
}
|
|
||||||
execute_statement(*_handle, "START TRANSACTION");
|
|
||||||
_transaction_active = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void connection::commit_transaction()
|
|
||||||
{
|
|
||||||
if (not _transaction_active)
|
|
||||||
{
|
|
||||||
throw sqlpp::exception("MySQL: Cannot commit a finished or failed transaction");
|
|
||||||
}
|
|
||||||
_transaction_active = false;
|
|
||||||
execute_statement(*_handle, "COMMIT");
|
|
||||||
}
|
|
||||||
|
|
||||||
void connection::rollback_transaction(bool report)
|
|
||||||
{
|
|
||||||
if (not _transaction_active)
|
|
||||||
{
|
|
||||||
throw sqlpp::exception("MySQL: Cannot rollback a finished or failed transaction");
|
|
||||||
}
|
|
||||||
if (report)
|
|
||||||
{
|
|
||||||
std::cerr << "MySQL warning: Rolling back unfinished transaction" << std::endl;
|
|
||||||
}
|
|
||||||
_transaction_active = false;
|
|
||||||
execute_statement(*_handle, "ROLLBACK");
|
|
||||||
}
|
|
||||||
|
|
||||||
void connection::report_rollback_failure(const std::string message) noexcept
|
|
||||||
{
|
|
||||||
std::cerr << "MySQL message:" << message << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
<<<<<<< Updated upstream
|
|
||||||
MYSQL* connection::get_handle(){
|
|
||||||
=======
|
|
||||||
MYSQL* connection::get_handle()
|
|
||||||
{
|
|
||||||
>>>>>>> Stashed changes
|
|
||||||
return _handle->mysql.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 "connection_handle.h"
|
|
||||||
#include <ciso646>
|
|
||||||
#include <sqlpp11/exception.h>
|
|
||||||
#include <sqlpp11/mysql/connection_config.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace mysql
|
|
||||||
{
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_MYSQL_CONNECTION_HANDLE_H
|
|
||||||
#define SQLPP_MYSQL_CONNECTION_HANDLE_H
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include "../sqlpp_mysql.h"
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace mysql
|
|
||||||
{
|
|
||||||
struct connection_config;
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace mysql
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_MYSQL_DETAIL_PREPARED_STATEMENT_HANDLE_H
|
|
||||||
#define SQLPP_MYSQL_DETAIL_PREPARED_STATEMENT_HANDLE_H
|
|
||||||
|
|
||||||
#include "../sqlpp_mysql.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace mysql
|
|
||||||
{
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
struct result_meta_data_t
|
|
||||||
{
|
|
||||||
size_t index;
|
|
||||||
unsigned long bound_len;
|
|
||||||
my_bool bound_is_null;
|
|
||||||
my_bool bound_error;
|
|
||||||
std::vector<char> bound_text_buffer; // also for blobs
|
|
||||||
const char** text_buffer;
|
|
||||||
size_t* len;
|
|
||||||
bool* is_null;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct prepared_statement_handle_t
|
|
||||||
{
|
|
||||||
struct wrapped_bool
|
|
||||||
{
|
|
||||||
my_bool value;
|
|
||||||
|
|
||||||
wrapped_bool() : value(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
wrapped_bool(bool v) : value(v)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
wrapped_bool(const wrapped_bool&) = default;
|
|
||||||
wrapped_bool(wrapped_bool&&) = default;
|
|
||||||
wrapped_bool& operator=(const wrapped_bool&) = default;
|
|
||||||
wrapped_bool& operator=(wrapped_bool&&) = default;
|
|
||||||
~wrapped_bool() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
MYSQL_STMT* mysql_stmt;
|
|
||||||
std::vector<MYSQL_BIND> stmt_params;
|
|
||||||
std::vector<MYSQL_TIME> stmt_date_time_param_buffer;
|
|
||||||
std::vector<wrapped_bool> stmt_param_is_null; // my_bool is bool after 8.0, and vector<bool> is bad
|
|
||||||
std::vector<MYSQL_BIND> result_params;
|
|
||||||
std::vector<result_meta_data_t> result_param_meta_data;
|
|
||||||
bool debug;
|
|
||||||
|
|
||||||
prepared_statement_handle_t(MYSQL_STMT* stmt, size_t no_of_parameters, size_t no_of_columns, bool debug_)
|
|
||||||
: mysql_stmt(stmt),
|
|
||||||
stmt_params(no_of_parameters, MYSQL_BIND{}),
|
|
||||||
stmt_date_time_param_buffer(no_of_parameters, MYSQL_TIME{}),
|
|
||||||
stmt_param_is_null(no_of_parameters, false),
|
|
||||||
result_params(no_of_columns, MYSQL_BIND{}),
|
|
||||||
result_param_meta_data(no_of_columns, result_meta_data_t{}),
|
|
||||||
debug(debug_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
prepared_statement_handle_t(const prepared_statement_handle_t&) = delete;
|
|
||||||
prepared_statement_handle_t(prepared_statement_handle_t&&) = default;
|
|
||||||
prepared_statement_handle_t& operator=(const prepared_statement_handle_t&) = delete;
|
|
||||||
prepared_statement_handle_t& operator=(prepared_statement_handle_t&&) = default;
|
|
||||||
|
|
||||||
~prepared_statement_handle_t()
|
|
||||||
{
|
|
||||||
if (mysql_stmt)
|
|
||||||
mysql_stmt_close(mysql_stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!() const
|
|
||||||
{
|
|
||||||
return !mysql_stmt;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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_MYSQL_DETAIL_RESULT_HANDLE_H
|
|
||||||
#define SQLPP_MYSQL_DETAIL_RESULT_HANDLE_H
|
|
||||||
|
|
||||||
#include "../sqlpp_mysql.h"
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace mysql
|
|
||||||
{
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
struct result_handle
|
|
||||||
{
|
|
||||||
MYSQL_RES* mysql_res;
|
|
||||||
bool debug;
|
|
||||||
|
|
||||||
result_handle(MYSQL_RES* res, bool debug_) : mysql_res(res), debug(debug_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
result_handle(const result_handle&) = delete;
|
|
||||||
result_handle(result_handle&&) = default;
|
|
||||||
result_handle& operator=(const result_handle&) = delete;
|
|
||||||
result_handle& operator=(result_handle&&) = default;
|
|
||||||
|
|
||||||
~result_handle()
|
|
||||||
{
|
|
||||||
if (mysql_res)
|
|
||||||
mysql_free_result(mysql_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!() const
|
|
||||||
{
|
|
||||||
return !mysql_res;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// It seems that Windows.h will be included directly and indirectly.
|
|
||||||
// These defines prevent min/max macros and a bunch of other stuff
|
|
||||||
// to be defined in that header.
|
|
||||||
#ifndef NOMINMAX
|
|
||||||
#define NOMINMAX
|
|
||||||
#endif
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
#include "detail/prepared_statement_handle.h"
|
|
||||||
#include <ciso646>
|
|
||||||
#include <date/date.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sqlpp11/mysql/prepared_statement.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace mysql
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
@PACKAGE_INIT@
|
|
||||||
|
|
||||||
include(CMakeFindDependencyMacro)
|
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|
||||||
|
|
||||||
find_dependency(Sqlpp11 REQUIRED)
|
|
||||||
find_dependency(MySQL REQUIRED)
|
|
||||||
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/sqlpp-mysql-targets.cmake")
|
|
||||||
|
|
||||||
check_required_components(sqlpp-mysql)
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018 - 2018, 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_MYSQL_MYSQL_H
|
|
||||||
#define SQLPP_MYSQL_MYSQL_H
|
|
||||||
|
|
||||||
#include <mysql.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace mysql
|
|
||||||
{
|
|
||||||
#if LIBMYSQL_VERSION_ID >= 80000
|
|
||||||
using my_bool = bool;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,96 +0,0 @@
|
|||||||
# 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()
|
|
@ -1,249 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
@ -1,280 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
@ -1,466 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
@ -1,245 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
@ -28,11 +28,18 @@ macro (build_and_run arg)
|
|||||||
# Add headers to sources to enable file browsing in IDEs
|
# Add headers to sources to enable file browsing in IDEs
|
||||||
add_executable(Sqlpp11Sqlite3${arg} ${arg}.cpp)
|
add_executable(Sqlpp11Sqlite3${arg} ${arg}.cpp)
|
||||||
|
|
||||||
target_link_libraries(Sqlpp11Sqlite3${arg} PRIVATE sqlpp11-connector-sqlite3)
|
target_link_libraries(Sqlpp11Sqlite3${arg} PRIVATE sqlpp11::sqlpp11)
|
||||||
if (NOT MSVC)
|
if (SQLCIPHER)
|
||||||
target_compile_options(Sqlpp11Sqlite3${arg} INTERFACE -Wall -Wextra -pedantic)
|
target_compile_definitions(Sqlpp11Sqlite3${arg} PRIVATE SQLPP_USE_SQLCIPHER)
|
||||||
endif ()
|
target_link_libraries(Sqlpp11Sqlite3${arg} PRIVATE SQLCipher::SQLCipher)
|
||||||
add_test(NAME Sqlpp11Sqlite3${arg} COMMAND Sqlpp11Sqlite3${arg})
|
if (SQLPP_DYNAMIC_LOADING)
|
||||||
|
target_include_directories(Sqlpp11Sqlite3${arg} PRIVATE ${SQLCIPHER_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
target_link_libraries(Sqlpp11Sqlite3${arg} PRIVATE SQLite::SQLite3)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_test(NAME Sqlpp11Sqlite3${arg} COMMAND Sqlpp11Sqlite3${arg})
|
||||||
endmacro ()
|
endmacro ()
|
||||||
|
|
||||||
build_and_run(DateTimeTest)
|
build_and_run(DateTimeTest)
|
||||||
|
Loading…
Reference in New Issue
Block a user