diff --git a/CMakeLists.txt b/CMakeLists.txt index f67b6338..7fdf2415 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,9 +78,6 @@ add_subdirectory(dependencies) add_library(sqlpp11 INTERFACE) add_library(sqlpp11::sqlpp11 ALIAS sqlpp11) -# Connector targets -add_subdirectory(src) - target_link_libraries(sqlpp11 INTERFACE date::date) target_include_directories(sqlpp11 INTERFACE diff --git a/include/sqlpp11/sqlite3/bind_result.h b/include/sqlpp11/sqlite3/bind_result.h index f72403aa..171db71e 100644 --- a/include/sqlpp11/sqlite3/bind_result.h +++ b/include/sqlpp11/sqlite3/bind_result.h @@ -28,8 +28,11 @@ #define SQLPP_SQLITE3_BIND_RESULT_H #include +#include #include +#include #include +#include #ifdef _MSC_VER #pragma warning(push) @@ -42,8 +45,33 @@ namespace sqlpp { namespace detail { - struct prepared_statement_handle_t; - } + const auto date_digits = std::vector{1, 1, 1, 1, 0, 1, 1, 0, 1, 1}; // 2015-10-28 + const auto time_digits = std::vector{0, 1, 1, 0, 1, 1, 0, 1, 1}; // T23:00:12 + const auto ms_digits = std::vector{0, 1, 1, 1}; // .123 + + auto check_digits(const char* text, const std::vector& 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 { @@ -51,7 +79,12 @@ namespace sqlpp public: bind_result_t() = default; - bind_result_t(const std::shared_ptr& handle); + bind_result_t(const std::shared_ptr& 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(bind_result_t&& rhs) = default; 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_floating_point_result(size_t index, double* value, bool* is_null); - void _bind_integral_result(size_t index, int64_t* value, bool* is_null); - void _bind_unsigned_integral_result(size_t index, uint64_t* value, bool* is_null); - void _bind_text_result(size_t index, const char** text, size_t* len); - void _bind_blob_result(size_t index, const uint8_t** text, size_t* len); - void _bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null); - void _bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null); + void _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(sqlite3_column_int(_handle->sqlite_statement, static_cast(index))); + *is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast(index)) == SQLITE_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(index))) + { + case (SQLITE3_TEXT): + *value = atof( + reinterpret_cast(sqlite3_column_text(_handle->sqlite_statement, static_cast(index)))); + break; + default: + *value = sqlite3_column_double(_handle->sqlite_statement, static_cast(index)); + } + *is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast(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(index)); + *is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast(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(sqlite3_column_int64(_handle->sqlite_statement, static_cast(index))); + *is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast(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(sqlite3_column_text(_handle->sqlite_statement, static_cast(index)))); + *len = sqlite3_column_bytes(_handle->sqlite_statement, static_cast(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(sqlite3_column_blob(_handle->sqlite_statement, static_cast(index)))); + *len = sqlite3_column_bytes(_handle->sqlite_statement, static_cast(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(index)) == SQLITE_NULL; + if (*is_null) + { + *value = {}; + return; + } + + const auto date_string = + reinterpret_cast(sqlite3_column_text(_handle->sqlite_statement, static_cast(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(index)) == SQLITE_NULL; + if (*is_null) + { + *value = {}; + return; + } + + const auto date_time_string = + reinterpret_cast(sqlite3_column_text(_handle->sqlite_statement, static_cast(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: - 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 sqlpp diff --git a/include/sqlpp11/sqlite3/connection.h b/include/sqlpp11/sqlite3/connection.h index 709ee098..28c866b2 100644 --- a/include/sqlpp11/sqlite3/connection.h +++ b/include/sqlpp11/sqlite3/connection.h @@ -33,17 +33,22 @@ #include #endif #include +#include #include #include #include #include #include +#include #include #include -#include #include #include +#ifdef SQLPP_DYNAMIC_LOADING +#include +#endif + #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4251) @@ -53,9 +58,97 @@ namespace sqlpp { namespace sqlite3 { +#ifdef SQLPP_DYNAMIC_LOADING + using namespace dynamic; +#endif + 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(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; @@ -107,18 +200,81 @@ namespace sqlpp transaction_status_type _transaction_status = transaction_status_type::none; // direct execution - bind_result_t select_impl(const std::string& statement); - size_t insert_impl(const std::string& statement); - size_t update_impl(const std::string& statement); - size_t remove_impl(const std::string& statement); + bind_result_t select_impl(const std::string& statement) + { + std::unique_ptr 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)}; + } + + 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_statement_t prepare_impl(const std::string& statement); - bind_result_t run_prepared_select_impl(prepared_statement_t& prepared_statement); - size_t run_prepared_execute_impl(prepared_statement_t& prepared_statement); - size_t run_prepared_insert_impl(prepared_statement_t& prepared_statement); - size_t run_prepared_update_impl(prepared_statement_t& prepared_statement); - size_t run_prepared_remove_impl(prepared_statement_t& prepared_statement); + prepared_statement_t prepare_impl(const std::string& statement) + { + return {std::unique_ptr( + new detail::prepared_statement_handle_t(prepare_statement(*_handle, 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: using _prepared_statement_t = prepared_statement_t; @@ -143,10 +299,15 @@ namespace sqlpp return ::sqlpp::serialize(t, context); } - connection(connection_config config); - connection(connection&&) noexcept; - connection& operator=(connection&&) noexcept; - ~connection(); + connection(connection_config config) : _handle(new detail::connection_handle(std::move(config))) + { + } + + connection(connection&&) noexcept = default; + connection& operator=(connection&&) noexcept = default; + + ~connection() = default; + connection(const connection&) = delete; connection& operator=(const connection&) = delete; @@ -251,7 +412,12 @@ namespace sqlpp } //! 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 < typename Execute, @@ -280,7 +446,20 @@ namespace sqlpp } //! 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 template @@ -317,30 +496,98 @@ namespace sqlpp } //! 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 - 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 - 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) - 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 // 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) - 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 - 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) diff --git a/include/sqlpp11/sqlite3/prepared_statement.h b/include/sqlpp11/sqlite3/prepared_statement.h index 2497c979..05381b52 100644 --- a/include/sqlpp11/sqlite3/prepared_statement.h +++ b/include/sqlpp11/sqlite3/prepared_statement.h @@ -28,10 +28,16 @@ #define SQLPP_SQLITE3_PREPARED_STATEMENT_H #include -#include -#include +#include +#include #include #include +#include + +#include +#include + +#include #ifdef _MSC_VER #pragma warning(push) @@ -42,12 +48,28 @@ namespace sqlpp { namespace sqlite3 { - class connection; - 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 { @@ -56,7 +78,12 @@ namespace sqlpp public: prepared_statement_t() = default; - prepared_statement_t(std::shared_ptr&& handle); + prepared_statement_t(std::shared_ptr&& 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(prepared_statement_t&& rhs) = default; prepared_statement_t& operator=(const prepared_statement_t&) = delete; @@ -68,15 +95,158 @@ namespace sqlpp return _handle == rhs._handle; } - void _reset(); - void _bind_boolean_parameter(size_t index, const signed char* value, bool is_null); - void _bind_floating_point_parameter(size_t index, const double* value, bool is_null); - void _bind_integral_parameter(size_t index, const int64_t* value, bool is_null); - void _bind_unsigned_integral_parameter(size_t index, const uint64_t* value, bool is_null); - void _bind_text_parameter(size_t index, const std::string* value, bool is_null); - void _bind_date_parameter(size_t index, const ::sqlpp::chrono::day_point* value, bool is_null); - void _bind_date_time_parameter(size_t index, const ::sqlpp::chrono::microsecond_point* value, bool is_null); - void _bind_blob_parameter(size_t index, const std::vector* value, bool is_null); + void _reset() + { + if (_handle->debug) + std::cerr << "Sqlite3 debug: resetting prepared statement" << std::endl; + sqlite3_reset(_handle->sqlite_statement); + } + + void _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(index + 1), *value); + else + result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), "NaN", 3, SQLITE_STATIC); + else if (std::isinf(*value)) + { + if (*value > std::numeric_limits::max()) + result = sqlite3_bind_text(_handle->sqlite_statement, static_cast(index + 1), "Inf", 3, SQLITE_STATIC); + else + result = + sqlite3_bind_text(_handle->sqlite_statement, static_cast(index + 1), "-Inf", 4, SQLITE_STATIC); + } + else + result = sqlite3_bind_double(_handle->sqlite_statement, static_cast(index + 1), *value); + } + else + result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), *value); + else + result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), static_cast(*value)); + else + result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), value->data(), + static_cast(value->size()), SQLITE_STATIC); + else + result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), text.data(), + static_cast(text.size()), SQLITE_TRANSIENT); + } + else + result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), text.data(), + static_cast(text.size()), SQLITE_TRANSIENT); + } + else + result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(index + 1)); + detail::check_bind_result(result, "date"); + } + + void _bind_blob_parameter(size_t index, const std::vector* 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(index + 1), value->data(), + static_cast(value->size()), SQLITE_STATIC); + else + result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(index + 1)); + detail::check_bind_result(result, "blob"); + } }; } // namespace sqlite3 } // namespace sqlpp diff --git a/src/sqlite3/detail/prepared_statement_handle.h b/include/sqlpp11/sqlite3/prepared_statement_handle.h similarity index 87% rename from src/sqlite3/detail/prepared_statement_handle.h rename to include/sqlpp11/sqlite3/prepared_statement_handle.h index fad66475..36bb2600 100644 --- a/src/sqlite3/detail/prepared_statement_handle.h +++ b/include/sqlpp11/sqlite3/prepared_statement_handle.h @@ -24,26 +24,26 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_SQLITE3_DETAIL_PREPARED_STATEMENT_HANDLE_H -#define SQLPP_SQLITE3_DETAIL_PREPARED_STATEMENT_HANDLE_H +#ifndef SQLPP_SQLITE3_PREPARED_STATEMENT_HANDLE_H +#define SQLPP_SQLITE3_PREPARED_STATEMENT_HANDLE_H -#ifdef SQLPP_USE_SQLCIPHER -#include -#else -#include -#endif +#include +#include +#include +#include +#include -#ifdef SQLPP_DYNAMIC_LOADING -#include +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4251) #endif namespace sqlpp { namespace sqlite3 { -#ifdef SQLPP_DYNAMIC_LOADING - using namespace dynamic; -#endif + class connection; + namespace detail { struct prepared_statement_handle_t @@ -89,8 +89,13 @@ namespace sqlpp return !sqlite_statement; } }; - } // namespace detail - } // namespace sqlite3 + } + + } // namespace sqlite3 } // namespace sqlpp +#ifdef _MSC_VER +#pragma warning(pop) +#endif + #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 6219cf70..00000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -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() - diff --git a/src/mysql/CMakeLists.txt b/src/mysql/CMakeLists.txt deleted file mode 100644 index 65c0f1e6..00000000 --- a/src/mysql/CMakeLists.txt +++ /dev/null @@ -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 - $ -) - -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 -) diff --git a/src/mysql/bind_result.cpp b/src/mysql/bind_result.cpp deleted file mode 100644 index 5cf09d32..00000000 --- a/src/mysql/bind_result.cpp +++ /dev/null @@ -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 -#include -#include -#include "sqlpp_mysql.h" -#include -#include - -namespace sqlpp -{ - namespace mysql - { - - } -} diff --git a/src/mysql/char_result.cpp b/src/mysql/char_result.cpp deleted file mode 100644 index 413734c2..00000000 --- a/src/mysql/char_result.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace mysql - { - namespace - { - } - - - } -} diff --git a/src/mysql/connection.cpp b/src/mysql/connection.cpp deleted file mode 100644 index 157fbb45..00000000 --- a/src/mysql/connection.cpp +++ /dev/null @@ -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 -#include -#include "detail/connection_handle.h" -#include "detail/prepared_statement_handle.h" -#include "detail/result_handle.h" -#include -#include - -namespace sqlpp -{ - namespace mysql - { - - } -} diff --git a/src/mysql/connection.cpp.orig b/src/mysql/connection.cpp.orig deleted file mode 100644 index 4b7403dc..00000000 --- a/src/mysql/connection.cpp.orig +++ /dev/null @@ -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 -#include -#include "detail/connection_handle.h" -#include "detail/prepared_statement_handle.h" -#include "detail/result_handle.h" -#include -#include - -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 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( - 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& 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::get_config() - { - return _handle->config; - } - - char_result_t connection::select_impl(const std::string& statement) - { - execute_statement(*_handle, statement); - std::unique_ptr 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 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(); - } - } -} diff --git a/src/mysql/detail/connection_handle.cpp b/src/mysql/detail/connection_handle.cpp deleted file mode 100644 index 5cae0ae8..00000000 --- a/src/mysql/detail/connection_handle.cpp +++ /dev/null @@ -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 -#include -#include - -namespace sqlpp -{ - namespace mysql - { - namespace detail - { - } - } -} diff --git a/src/mysql/detail/connection_handle.h b/src/mysql/detail/connection_handle.h deleted file mode 100644 index 6791bc4d..00000000 --- a/src/mysql/detail/connection_handle.h +++ /dev/null @@ -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 -#include "../sqlpp_mysql.h" - -namespace sqlpp -{ - namespace mysql - { - struct connection_config; - - namespace detail - { - } // namespace detail - } // namespace mysql -} - -#endif diff --git a/src/mysql/detail/prepared_statement_handle.h b/src/mysql/detail/prepared_statement_handle.h deleted file mode 100644 index 9d27ca9f..00000000 --- a/src/mysql/detail/prepared_statement_handle.h +++ /dev/null @@ -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 - -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 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 stmt_params; - std::vector stmt_date_time_param_buffer; - std::vector stmt_param_is_null; // my_bool is bool after 8.0, and vector is bad - std::vector result_params; - std::vector 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 diff --git a/src/mysql/detail/result_handle.h b/src/mysql/detail/result_handle.h deleted file mode 100644 index 2aa0f52b..00000000 --- a/src/mysql/detail/result_handle.h +++ /dev/null @@ -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 diff --git a/src/mysql/prepared_statement.cpp b/src/mysql/prepared_statement.cpp deleted file mode 100644 index baabdbdd..00000000 --- a/src/mysql/prepared_statement.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include - -namespace sqlpp -{ - namespace mysql - { - } -} diff --git a/src/mysql/sqlpp-mysql-config.cmake.in b/src/mysql/sqlpp-mysql-config.cmake.in deleted file mode 100644 index 598d410a..00000000 --- a/src/mysql/sqlpp-mysql-config.cmake.in +++ /dev/null @@ -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) diff --git a/src/mysql/sqlpp_mysql.h b/src/mysql/sqlpp_mysql.h deleted file mode 100644 index f497e44c..00000000 --- a/src/mysql/sqlpp_mysql.h +++ /dev/null @@ -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 - -namespace sqlpp -{ - namespace mysql - { -#if LIBMYSQL_VERSION_ID >= 80000 - using my_bool = bool; -#endif - } -} - -#endif diff --git a/src/sqlite3/CMakeLists.txt b/src/sqlite3/CMakeLists.txt deleted file mode 100644 index 22cc1062..00000000 --- a/src/sqlite3/CMakeLists.txt +++ /dev/null @@ -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 - $ - $) - - target_link_libraries(sqlpp11-connector-sqlite3-dynamic PUBLIC sqlpp11::sqlpp11) -endif() - -target_include_directories(sqlpp11-connector-sqlite3 PUBLIC - $ - $) - -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() diff --git a/src/sqlite3/bind_result.cpp b/src/sqlite3/bind_result.cpp deleted file mode 100644 index 0385cf86..00000000 --- a/src/sqlite3/bind_result.cpp +++ /dev/null @@ -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 -#include -#include // Howard Hinnant's date library -#include -#include -#include -#include - -#ifdef SQLPP_DYNAMIC_LOADING -#include -#endif - -namespace sqlpp -{ - namespace sqlite3 - { -#ifdef SQLPP_DYNAMIC_LOADING - using namespace dynamic; -#endif - - bind_result_t::bind_result_t(const std::shared_ptr& 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(sqlite3_column_int(_handle->sqlite_statement, static_cast(index))); - *is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast(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(index))) - { - case (SQLITE3_TEXT): - *value = atof( - reinterpret_cast(sqlite3_column_text(_handle->sqlite_statement, static_cast(index)))); - break; - default: - *value = sqlite3_column_double(_handle->sqlite_statement, static_cast(index)); - } - *is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast(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(index)); - *is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast(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(sqlite3_column_int64(_handle->sqlite_statement, static_cast(index))); - *is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast(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(sqlite3_column_text(_handle->sqlite_statement, static_cast(index)))); - *len = sqlite3_column_bytes(_handle->sqlite_statement, static_cast(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(sqlite3_column_blob(_handle->sqlite_statement, static_cast(index)))); - *len = sqlite3_column_bytes(_handle->sqlite_statement, static_cast(index)); - } - - namespace - { - const auto date_digits = std::vector{1, 1, 1, 1, 0, 1, 1, 0, 1, 1}; // 2015-10-28 - const auto time_digits = std::vector{0, 1, 1, 0, 1, 1, 0, 1, 1}; // T23:00:12 - const auto ms_digits = std::vector{0, 1, 1, 1}; // .123 - - auto check_digits(const char* text, const std::vector& 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(index)) == SQLITE_NULL; - if (*is_null) - { - *value = {}; - return; - } - - const auto date_string = - reinterpret_cast(sqlite3_column_text(_handle->sqlite_statement, static_cast(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(index)) == SQLITE_NULL; - if (*is_null) - { - *value = {}; - return; - } - - const auto date_time_string = - reinterpret_cast(sqlite3_column_text(_handle->sqlite_statement, static_cast(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 diff --git a/src/sqlite3/connection.cpp b/src/sqlite3/connection.cpp deleted file mode 100644 index ab5305e4..00000000 --- a/src/sqlite3/connection.cpp +++ /dev/null @@ -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 -#include -#include - -#ifdef SQLPP_DYNAMIC_LOADING -#include -#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(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 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( - 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}; - } - } -} diff --git a/src/sqlite3/detail/connection_handle.cpp b/src/sqlite3/detail/connection_handle.cpp deleted file mode 100644 index 9466632b..00000000 --- a/src/sqlite3/detail/connection_handle.cpp +++ /dev/null @@ -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 -#include -#include -#include "connection_handle.h" - -#ifdef SQLPP_DYNAMIC_LOADING -#include -#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; - } - } - } - } -} diff --git a/src/sqlite3/detail/connection_handle.h b/src/sqlite3/detail/connection_handle.h deleted file mode 100644 index 3a8a4bf1..00000000 --- a/src/sqlite3/detail/connection_handle.h +++ /dev/null @@ -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 -#else -#include -#endif -#include - -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 diff --git a/src/sqlite3/detail/dynamic_libsqlite3.cpp b/src/sqlite3/detail/dynamic_libsqlite3.cpp deleted file mode 100644 index 3f02975d..00000000 --- a/src/sqlite3/detail/dynamic_libsqlite3.cpp +++ /dev/null @@ -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 -#include - -#if defined(__linux__) || defined(__APPLE__) -#include -#else -#include -#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(dlsym(HNDL, #NAME)) -#else -#define DYNLOAD(HNDL, NAME) NAME = reinterpret_cast(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 diff --git a/src/sqlite3/prepared_statement.cpp b/src/sqlite3/prepared_statement.cpp deleted file mode 100644 index 5d4b85e8..00000000 --- a/src/sqlite3/prepared_statement.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include - -#if defined(__CYGWIN__) -#include - -// Workaround because cygwin gcc does not define to_string -namespace std -{ - template - std::string to_string(T t) - { - std::ostringstream stream; - - stream << t; - return stream.str(); - } -} // namespace std -#endif - -#ifdef SQLPP_DYNAMIC_LOADING -#include -#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&& 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(index + 1), *value); - else - result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), "NaN", 3, SQLITE_STATIC); - else if (std::isinf(*value)) - { - if (*value > std::numeric_limits::max()) - result = sqlite3_bind_text(_handle->sqlite_statement, static_cast(index + 1), "Inf", 3, SQLITE_STATIC); - else - result = - sqlite3_bind_text(_handle->sqlite_statement, static_cast(index + 1), "-Inf", 4, SQLITE_STATIC); - } - else - result = sqlite3_bind_double(_handle->sqlite_statement, static_cast(index + 1), *value); - } - else - result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), *value); - else - result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), static_cast(*value)); - else - result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), value->data(), - static_cast(value->size()), SQLITE_STATIC); - else - result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), text.data(), - static_cast(text.size()), SQLITE_TRANSIENT); - } - else - result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(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(index + 1), text.data(), - static_cast(text.size()), SQLITE_TRANSIENT); - } - else - result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(index + 1)); - check_bind_result(result, "date"); - } - void prepared_statement_t::_bind_blob_parameter(size_t index, const std::vector* 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(index + 1), value->data(), - static_cast(value->size()), SQLITE_STATIC); - else - result = sqlite3_bind_null(_handle->sqlite_statement, static_cast(index + 1)); - check_bind_result(result, "blob"); - } - } // namespace sqlite3 -} // namespace sqlpp diff --git a/tests/sqlite3/usage/CMakeLists.txt b/tests/sqlite3/usage/CMakeLists.txt index 63264be1..84b66620 100644 --- a/tests/sqlite3/usage/CMakeLists.txt +++ b/tests/sqlite3/usage/CMakeLists.txt @@ -28,11 +28,18 @@ macro (build_and_run arg) # Add headers to sources to enable file browsing in IDEs add_executable(Sqlpp11Sqlite3${arg} ${arg}.cpp) - target_link_libraries(Sqlpp11Sqlite3${arg} PRIVATE sqlpp11-connector-sqlite3) - if (NOT MSVC) - target_compile_options(Sqlpp11Sqlite3${arg} INTERFACE -Wall -Wextra -pedantic) - endif () - add_test(NAME Sqlpp11Sqlite3${arg} COMMAND Sqlpp11Sqlite3${arg}) + target_link_libraries(Sqlpp11Sqlite3${arg} PRIVATE sqlpp11::sqlpp11) + if (SQLCIPHER) + target_compile_definitions(Sqlpp11Sqlite3${arg} PRIVATE SQLPP_USE_SQLCIPHER) + target_link_libraries(Sqlpp11Sqlite3${arg} PRIVATE SQLCipher::SQLCipher) + 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 () build_and_run(DateTimeTest)