0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-15 20:31:16 +08:00

Cleanup SQLite3 connector code (#514)

* Move the code for sqlpp::sqlite3::detail::prepared_statement_handle_t to include/sqlpp11/sqlite3/detail/prepared_statement_handle.h

* Whitespace

* Move the code for sqlpp::sqlite3::detail::connection_handle to include/sqlpp11/sqlite3/detail/connection_handle.h

* Rename sqlpp::sqlite3::serializer_t -> sqlpp::sqlite3::context_t

* Add const qualifiers to sqlpp::mysql::context_t::escape() and its parameter.

* Change method argument types "const std::string" -> "const std::string&"

* Remove a superfluous function that forwards the call to sqlite3_close().

* Move initialization of sqlpp::sqlite3::detail::prepared_statement_handle_t data members from the constructor into the member initialization list.

* Rename method parameter from CamelCase to snake_case.
This commit is contained in:
MeanSquaredError 2023-08-17 08:26:54 +03:00 committed by GitHub
parent 4a9da95fda
commit c550dca89e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 140 additions and 95 deletions

View File

@ -30,8 +30,8 @@
#include <iostream> #include <iostream>
#include <sqlpp11/chrono.h> #include <sqlpp11/chrono.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
#include <sqlpp11/sqlite3/detail/prepared_statement_handle.h>
#include <sqlpp11/sqlite3/export.h> #include <sqlpp11/sqlite3/export.h>
#include <sqlpp11/sqlite3/prepared_statement_handle.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#include <iso646.h> #include <iso646.h>
@ -45,9 +45,9 @@ namespace sqlpp
{ {
namespace detail namespace detail
{ {
inline auto check_first_digit(const char* text, bool digitFlag) -> bool inline auto check_first_digit(const char* text, bool digit_flag) -> bool
{ {
if (digitFlag) if (digit_flag)
{ {
if (not std::isdigit(*text)) if (not std::isdigit(*text))
{ {
@ -66,9 +66,9 @@ namespace sqlpp
inline auto check_date_digits(const char* text) -> bool inline auto check_date_digits(const char* text) -> bool
{ {
for (const auto digitFlag : {true, true, true, true, false, true, true, false, true, true}) // YYYY-MM-DD for (const auto digit_flag : {true, true, true, true, false, true, true, false, true, true}) // YYYY-MM-DD
{ {
if (not check_first_digit(text, digitFlag)) if (not check_first_digit(text, digit_flag))
return false; return false;
++text; ++text;
} }
@ -77,9 +77,9 @@ namespace sqlpp
inline auto check_time_digits(const char* text) -> bool inline auto check_time_digits(const char* text) -> bool
{ {
for (const auto digitFlag : {true, true, false, true, true, false, true, true}) // hh:mm:ss for (const auto digit_flag : {true, true, false, true, true, false, true, true}) // hh:mm:ss
{ {
if (not check_first_digit(text, digitFlag)) if (not check_first_digit(text, digit_flag))
return false; return false;
++text; ++text;
} }
@ -88,9 +88,9 @@ namespace sqlpp
inline auto check_ms_digits(const char* text) -> bool inline auto check_ms_digits(const char* text) -> bool
{ {
for (const auto digitFlag : {true, true, true}) for (const auto digit_flag : {true, true, true})
{ {
if (not check_first_digit(text, digitFlag)) if (not check_first_digit(text, digit_flag))
return false; return false;
++text; ++text;
} }

View File

@ -39,6 +39,7 @@
#include <sqlpp11/serialize.h> #include <sqlpp11/serialize.h>
#include <sqlpp11/sqlite3/bind_result.h> #include <sqlpp11/sqlite3/bind_result.h>
#include <sqlpp11/sqlite3/connection_config.h> #include <sqlpp11/sqlite3/connection_config.h>
#include <sqlpp11/sqlite3/detail/connection_handle.h>
#include <sqlpp11/sqlite3/prepared_statement.h> #include <sqlpp11/sqlite3/prepared_statement.h>
#include <sqlpp11/sqlite3/export.h> #include <sqlpp11/sqlite3/export.h>
#include <sqlpp11/transaction.h> #include <sqlpp11/transaction.h>
@ -65,66 +66,6 @@ namespace sqlpp
namespace detail namespace detail
{ {
inline void handle_cleanup(::sqlite3* sqlite)
{
sqlite3_close(sqlite);
}
struct connection_handle
{
std::shared_ptr<const connection_config> config;
std::unique_ptr<::sqlite3, void (*)(::sqlite3*)> sqlite;
connection_handle(const std::shared_ptr<const connection_config>& conf) :
config(conf),
sqlite(nullptr, handle_cleanup)
{
#ifdef SQLPP_DYNAMIC_LOADING
init_sqlite("");
#endif
::sqlite3* sqlite_ptr;
const auto rc = sqlite3_open_v2(conf->path_to_database.c_str(), &sqlite_ptr, conf->flags,
conf->vfs.empty() ? nullptr : conf->vfs.c_str());
if (rc != SQLITE_OK)
{
const std::string msg = sqlite3_errmsg(sqlite_ptr);
sqlite3_close(sqlite_ptr);
throw sqlpp::exception("Sqlite3 error: Can't open database: " + msg);
}
sqlite.reset(sqlite_ptr);
#ifdef SQLITE_HAS_CODEC
if (conf->password.size() > 0)
{
int ret = sqlite3_key(native_handle(), conf->password.data(), conf->password.size());
if (ret != SQLITE_OK)
{
const std::string msg = sqlite3_errmsg(native_handle());
sqlite3_close(native_handle());
throw sqlpp::exception("Sqlite3 error: Can't set password to database: " + msg);
}
}
#endif
}
connection_handle(const connection_handle&) = delete;
connection_handle(connection_handle&&) = default;
connection_handle& operator=(const connection_handle&) = delete;
connection_handle& operator=(connection_handle&&) = default;
::sqlite3* native_handle() const
{
return sqlite.get();
}
bool check_connection() const
{
return native_handle() != nullptr;
}
};
inline detail::prepared_statement_handle_t prepare_statement(std::unique_ptr<connection_handle>& handle, inline detail::prepared_statement_handle_t prepare_statement(std::unique_ptr<connection_handle>& handle,
const std::string& statement) const std::string& statement)
{ {
@ -167,9 +108,9 @@ namespace sqlpp
// Forward declaration // Forward declaration
class connection_base; class connection_base;
struct serializer_t struct context_t
{ {
serializer_t(const connection_base& db) : _db(db), _count(1) context_t(const connection_base& db) : _db(db), _count(1)
{ {
} }
@ -179,7 +120,7 @@ namespace sqlpp
return _os << t; return _os << t;
} }
std::string escape(std::string arg); std::string escape(const std::string& arg) const;
std::string str() const std::string str() const
{ {
@ -297,7 +238,7 @@ namespace sqlpp
using _handle_ptr_t = std::unique_ptr<_handle_t>; using _handle_ptr_t = std::unique_ptr<_handle_t>;
using _prepared_statement_t = prepared_statement_t; using _prepared_statement_t = prepared_statement_t;
using _context_t = serializer_t; using _context_t = context_t;
using _serializer_context_t = _context_t; using _serializer_context_t = _context_t;
using _interpreter_context_t = _context_t; using _interpreter_context_t = _context_t;
@ -572,7 +513,7 @@ namespace sqlpp
} }
//! report a rollback failure (will be called by transactions in case of a rollback failure in the destructor) //! report a rollback failure (will be called by transactions in case of a rollback failure in the destructor)
void report_rollback_failure(const std::string message) noexcept void report_rollback_failure(const std::string& message) noexcept
{ {
std::cerr << "Sqlite3 message:" << message << std::endl; std::cerr << "Sqlite3 message:" << message << std::endl;
} }
@ -588,7 +529,7 @@ namespace sqlpp
return _handle->native_handle(); return _handle->native_handle();
} }
schema_t attach(const connection_config& config, const std::string name) schema_t attach(const connection_config& config, const std::string& name)
{ {
auto prepared = auto prepared =
prepare_statement(_handle, "ATTACH '" + escape(config.path_to_database) + "' AS " + escape(name)); prepare_statement(_handle, "ATTACH '" + escape(config.path_to_database) + "' AS " + escape(name));
@ -608,7 +549,7 @@ namespace sqlpp
}; };
// Method definition moved outside of class because it needs connection_base // Method definition moved outside of class because it needs connection_base
inline std::string serializer_t::escape(std::string arg) inline std::string context_t::escape(const std::string& arg) const
{ {
return _db.escape(arg); return _db.escape(arg);
} }

View File

@ -0,0 +1,106 @@
#pragma once
/*
* Copyright (c) 2013 - 2016, Roland Bock
* Copyright (c) 2023, Vesselin Atanasov
* 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 SQLPP_USE_SQLCIPHER
#include <sqlcipher/sqlite3.h>
#else
#include <sqlite3.h>
#endif
#ifdef SQLPP_DYNAMIC_LOADING
#include <sqlpp11/sqlite3/dynamic_libsqlite3.h>
#endif
namespace sqlpp
{
namespace sqlite3
{
#ifdef SQLPP_DYNAMIC_LOADING
using namespace dynamic;
#endif
namespace detail
{
struct connection_handle
{
std::shared_ptr<const connection_config> config;
std::unique_ptr<::sqlite3, int (*)(::sqlite3*)> sqlite;
connection_handle(const std::shared_ptr<const connection_config>& conf) :
config(conf),
sqlite(nullptr, sqlite3_close)
{
#ifdef SQLPP_DYNAMIC_LOADING
init_sqlite("");
#endif
::sqlite3* sqlite_ptr;
const auto rc = sqlite3_open_v2(conf->path_to_database.c_str(), &sqlite_ptr, conf->flags,
conf->vfs.empty() ? nullptr : conf->vfs.c_str());
if (rc != SQLITE_OK)
{
const std::string msg = sqlite3_errmsg(sqlite_ptr);
sqlite3_close(sqlite_ptr);
throw sqlpp::exception("Sqlite3 error: Can't open database: " + msg);
}
sqlite.reset(sqlite_ptr);
#ifdef SQLITE_HAS_CODEC
if (conf->password.size() > 0)
{
int ret = sqlite3_key(native_handle(), conf->password.data(), conf->password.size());
if (ret != SQLITE_OK)
{
const std::string msg = sqlite3_errmsg(native_handle());
sqlite3_close(native_handle());
throw sqlpp::exception("Sqlite3 error: Can't set password to database: " + msg);
}
}
#endif
}
connection_handle(const connection_handle&) = delete;
connection_handle(connection_handle&&) = default;
connection_handle& operator=(const connection_handle&) = delete;
connection_handle& operator=(connection_handle&&) = default;
::sqlite3* native_handle() const
{
return sqlite.get();
}
bool check_connection() const
{
return native_handle() != nullptr;
}
};
} // namespace detail
} // namespace sqlite3
} // namespace sqlpp

View File

@ -53,12 +53,11 @@ namespace sqlpp
} }
prepared_statement_handle_t(const prepared_statement_handle_t&) = delete; prepared_statement_handle_t(const prepared_statement_handle_t&) = delete;
prepared_statement_handle_t(prepared_statement_handle_t&& rhs) prepared_statement_handle_t(prepared_statement_handle_t&& rhs) :
sqlite_statement(rhs.sqlite_statement),
debug(rhs.debug)
{ {
sqlite_statement = rhs.sqlite_statement;
rhs.sqlite_statement = nullptr; rhs.sqlite_statement = nullptr;
debug = rhs.debug;
} }
prepared_statement_handle_t& operator=(const prepared_statement_handle_t&) = delete; prepared_statement_handle_t& operator=(const prepared_statement_handle_t&) = delete;
prepared_statement_handle_t& operator=(prepared_statement_handle_t&& rhs) prepared_statement_handle_t& operator=(prepared_statement_handle_t&& rhs)
@ -87,7 +86,6 @@ namespace sqlpp
} }
}; };
} }
} // namespace sqlite3 } // namespace sqlite3
} // namespace sqlpp } // namespace sqlpp

View File

@ -136,13 +136,13 @@ namespace sqlpp
return {blank_insert_or_ignore_t<Database>().into(table)}; return {blank_insert_or_ignore_t<Database>().into(table)};
} }
inline sqlite3::serializer_t& serialize(const sqlite3::insert_or_replace_name_t&, sqlite3::serializer_t& context) inline sqlite3::context_t& serialize(const sqlite3::insert_or_replace_name_t&, sqlite3::context_t& context)
{ {
context << "INSERT OR REPLACE "; context << "INSERT OR REPLACE ";
return context; return context;
} }
inline sqlite3::serializer_t& serialize(const sqlite3::insert_or_ignore_name_t&, sqlite3::serializer_t& context) inline sqlite3::context_t& serialize(const sqlite3::insert_or_ignore_name_t&, sqlite3::context_t& context)
{ {
context << "INSERT OR IGNORE "; context << "INSERT OR IGNORE ";
return context; return context;

View File

@ -37,7 +37,7 @@
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
#include <sqlpp11/sqlite3/export.h> #include <sqlpp11/sqlite3/export.h>
#include <sqlpp11/sqlite3/prepared_statement_handle.h> #include <sqlpp11/sqlite3/detail/prepared_statement_handle.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)

View File

@ -48,7 +48,7 @@ namespace sqlpp
{ {
// Serialize parameters // Serialize parameters
template <typename ValueType, typename NameType> template <typename ValueType, typename NameType>
sqlite3::serializer_t& serialize(const parameter_t<ValueType, NameType>&, sqlite3::serializer_t& context) sqlite3::context_t& serialize(const parameter_t<ValueType, NameType>&, sqlite3::context_t& context)
{ {
context << "?" << context.count(); context << "?" << context.count();
context.pop_count(); context.pop_count();
@ -58,7 +58,7 @@ namespace sqlpp
// disable some stuff that won't work with sqlite3 // disable some stuff that won't work with sqlite3
#if SQLITE_VERSION_NUMBER < 3008003 #if SQLITE_VERSION_NUMBER < 3008003
template <typename Database, typename... Expressions> template <typename Database, typename... Expressions>
sqlite3::serializer_t& serialize(const with_data_t<Database, Expressions...>&, sqlite3::serializer_t& context) sqlite3::context_t& serialize(const with_data_t<Database, Expressions...>&, sqlite3::context_t& context)
{ {
static_assert(wrong_t<Expressions...>::value, "Sqlite3: No support for with before version 3.8.3"); static_assert(wrong_t<Expressions...>::value, "Sqlite3: No support for with before version 3.8.3");
return context; return context;
@ -66,28 +66,28 @@ namespace sqlpp
#endif #endif
template <typename Select> template <typename Select>
sqlite3::serializer_t& serialize(const any_t<Select>&, sqlite3::serializer_t& context) sqlite3::context_t& serialize(const any_t<Select>&, sqlite3::context_t& context)
{ {
static_assert(wrong_t<Select>::value, "Sqlite3: No support for any()"); static_assert(wrong_t<Select>::value, "Sqlite3: No support for any()");
return context; return context;
} }
template <typename Select> template <typename Select>
sqlite3::serializer_t& serialize(const some_t<Select>&, sqlite3::serializer_t& context) sqlite3::context_t& serialize(const some_t<Select>&, sqlite3::context_t& context)
{ {
static_assert(wrong_t<Select>::value, "Sqlite3: No support for some()"); static_assert(wrong_t<Select>::value, "Sqlite3: No support for some()");
return context; return context;
} }
template <typename Lhs, typename Rhs> template <typename Lhs, typename Rhs>
sqlite3::serializer_t& serialize(const pre_join_t<outer_join_t, Lhs, Rhs>&, sqlite3::serializer_t& context) sqlite3::context_t& serialize(const pre_join_t<outer_join_t, Lhs, Rhs>&, sqlite3::context_t& context)
{ {
static_assert(wrong_t<Lhs, Rhs>::value, "Sqlite3: No support for outer join"); static_assert(wrong_t<Lhs, Rhs>::value, "Sqlite3: No support for outer join");
return context; return context;
} }
template <typename Lhs, typename Rhs> template <typename Lhs, typename Rhs>
sqlite3::serializer_t& serialize(const pre_join_t<right_outer_join_t, Lhs, Rhs>&, sqlite3::serializer_t& context) sqlite3::context_t& serialize(const pre_join_t<right_outer_join_t, Lhs, Rhs>&, sqlite3::context_t& context)
{ {
static_assert(wrong_t<Lhs, Rhs>::value, "Sqlite3: No support for right_outer join"); static_assert(wrong_t<Lhs, Rhs>::value, "Sqlite3: No support for right_outer join");
return context; return context;
@ -95,7 +95,7 @@ namespace sqlpp
// Some special treatment of data types // Some special treatment of data types
template <typename Period> template <typename Period>
sqlite3::serializer_t& serialize(const time_point_operand<Period>& t, sqlite3::serializer_t& context) sqlite3::context_t& serialize(const time_point_operand<Period>& t, sqlite3::context_t& context)
{ {
const auto dp = ::sqlpp::chrono::floor<::date::days>(t._t); const auto dp = ::sqlpp::chrono::floor<::date::days>(t._t);
const auto time = ::date::make_time(t._t - dp); const auto time = ::date::make_time(t._t - dp);
@ -104,14 +104,14 @@ namespace sqlpp
return context; return context;
} }
inline sqlite3::serializer_t& serialize(const day_point_operand& t, sqlite3::serializer_t& context) inline sqlite3::context_t& serialize(const day_point_operand& t, sqlite3::context_t& context)
{ {
const auto ymd = ::date::year_month_day{t._t}; const auto ymd = ::date::year_month_day{t._t};
context << "DATE('" << ymd << "')"; context << "DATE('" << ymd << "')";
return context; return context;
} }
inline sqlite3::serializer_t& serialize(const floating_point_operand& t, sqlite3::serializer_t& context) inline sqlite3::context_t& serialize(const floating_point_operand& t, sqlite3::context_t& context)
{ {
if (std::isnan(t._t)) if (std::isnan(t._t))
context << "'NaN'"; context << "'NaN'";
@ -129,7 +129,7 @@ namespace sqlpp
// sqlite3 accepts only signed integers, // sqlite3 accepts only signed integers,
// so we MUST perform a conversion from unsigned to signed // so we MUST perform a conversion from unsigned to signed
inline sqlite3::serializer_t& serialize(const unsigned_integral_operand& t, sqlite3::serializer_t& context) inline sqlite3::context_t& serialize(const unsigned_integral_operand& t, sqlite3::context_t& context)
{ {
context << static_cast<typename integral_operand::_value_t>(t._t); context << static_cast<typename integral_operand::_value_t>(t._t);
return context; return context;

View File

@ -51,7 +51,7 @@ namespace
config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
config.debug = true; config.debug = true;
sqlpp::sqlite3::connection connection{config}; sqlpp::sqlite3::connection connection{config};
sqlpp::sqlite3::serializer_t printer{connection}; sqlpp::sqlite3::context_t printer{connection};
const auto result = serialize(expr, printer).str(); const auto result = serialize(expr, printer).str();