Improve sqlite helpers a bit

This commit is contained in:
King_DuckZ 2020-08-15 02:29:43 +01:00
parent 928cabfe34
commit 5df60661d3
2 changed files with 71 additions and 25 deletions

View file

@ -177,13 +177,11 @@ namespace {
return {*row_id_opt, false};
}
else {
m_ins.bind(1, shop.title);
m_ins.bind(2, shop.owner);
m_ins.bindNoCopy(3, shop_creation_date);
m_ins.bind(4, shop.location.map);
m_ins.bind(5, shop.location.x);
m_ins.bind(6, shop.location.y);
m_ins.bind(7, static_cast<int>(shop.type.value));
bind_all(m_ins, shop.title, shop.owner,
no_copy(shop_creation_date), shop.location.map,
shop.location.x, shop.location.y,
static_cast<int>(shop.type.value)
);
m_ins.exec();
m_ins.reset();
@ -203,8 +201,7 @@ namespace {
const oro::Timestamp& creation_timestamp
) {
SQLite::Statement query_shop(db, "SELECT title, owner, creation_date, loc_map, loc_x, loc_y, type, id FROM shops where owner = ? AND creation_date = ?");
query_shop.bind(1, owner);
query_shop.bind(2, to_sqlite_string(creation_timestamp));
bind_all(query_shop, owner, to_sqlite_string(creation_timestamp));
if (not query_shop.executeStep())
return {};
@ -305,13 +302,10 @@ void OriginsDB::update (const Items& items) {
);
SQLite::Transaction transaction(db);
for (const auto& item : items.items) {
query.bind(1, item.item_id);
query.bind(2, item.unique_name);
query.bind(3, item.name);
query.bind(4, static_cast<int>(item.type.value));
bind<int>(query, 5, item.subtype);
query.bind(6, item.npc_price);
bind(query, 7, item.slots);
bind_all(query, item.item_id, no_copy(item.unique_name),
no_copy(item.name), static_cast<int>(item.type.value),
cast<int>(item.subtype), item.npc_price, item.slots
);
query.exec();
query.reset();

View file

@ -24,8 +24,50 @@
namespace oro {
namespace detail {
template <typename T>
struct NoCopy {
explicit NoCopy (T& v) :
val(v)
{ }
T& val;
};
template <typename To, typename From>
struct Cast {
explicit Cast (From& v) :
val(v)
{ }
From& val;
};
template <typename CastT=void, typename T=void>
void bind_impl (SQLite::Statement& st, int idx, Cast<CastT, T>&& val);
template <typename CastT=void, typename T=void>
void bind_impl (SQLite::Statement& st, int idx, NoCopy<T>&& val);
template <typename CastT=void, typename T=void>
void bind_impl (SQLite::Statement& st, int idx, T&& val);
template <typename CastT=void, typename T=void>
void bind_impl (SQLite::Statement& st, int idx, const std::optional<T>& val);
template <typename CastT=void, typename T=void>
inline void bind_impl (SQLite::Statement& st, int idx, Cast<CastT, T>&& val) {
bind_impl<CastT, T>(st, idx, val.val);
}
template <typename CastT=void, typename T=void>
inline void bind_impl (SQLite::Statement& st, int idx, NoCopy<T>&& val) {
st.bindNoCopy(idx, val.val);
}
template <typename CastT=void, typename T=void>
void bind (SQLite::Statement& st, int idx, T&& val) {
inline void bind_impl (SQLite::Statement& st, int idx, T&& val) {
if constexpr (std::is_same_v<std::decay_t<T>, std::decay_t<CastT>> or std::is_same_v<void, CastT>) {
st.bind(idx, std::forward<T>(val));
}
@ -35,35 +77,45 @@ namespace detail {
}
template <typename CastT=void, typename T=void>
void bind (SQLite::Statement& st, int idx, const std::optional<T>& val) {
inline void bind_impl (SQLite::Statement& st, int idx, const std::optional<T>& val) {
if (val)
detail::bind (st, idx, *val);
detail::bind_impl<CastT> (st, idx, *val);
else
st.bind(idx, nullptr);
}
template <int... Indices, typename... Args>
void bind_many (SQLite::Statement& st, std::integer_sequence<int, Indices...>, Args&&... args) {
inline void bind_all (SQLite::Statement& st, std::integer_sequence<int, Indices...>, Args&&... args) {
const int dummy = (
bind(st, Indices + 1, std::forward<Args>(args)), ..., 0
bind_impl(st, Indices + 1, std::forward<Args>(args)), ..., 0
);
static_cast<void>(dummy);
}
} //namespace detail
template <typename T>
inline detail::NoCopy<T> no_copy (T& val) {
return detail::NoCopy<T>{val};
}
template <typename To, typename From>
inline detail::Cast<To, From> cast (From& val) {
return detail::Cast<To, From>(val);
}
template <typename... Args>
inline void bind (SQLite::Statement& st, Args&&... args) {
detail::bind_many(st, std::make_integer_sequence<int, sizeof...(Args)>{}, std::forward<Args>(args)...);
inline void bind_all (SQLite::Statement& st, Args&&... args) {
detail::bind_all(st, std::make_integer_sequence<int, sizeof...(Args)>{}, std::forward<Args>(args)...);
}
template <typename CastT=void, typename T=void>
inline void bind (SQLite::Statement& st, int index, T&& val) {
detail::bind<CastT>(st, index, std::forward<T>(val));
detail::bind_impl<CastT>(st, index, std::forward<T>(val));
}
template <typename T, typename... Args>
inline std::optional<T> exec_first_res (SQLite::Statement& st, Args&&... args) {
detail::bind_many(st, std::make_integer_sequence<int, sizeof...(Args)>{}, std::forward<Args>(args)...);
detail::bind_all(st, std::make_integer_sequence<int, sizeof...(Args)>{}, std::forward<Args>(args)...);
std::optional<T> retval;
if (st.executeStep()) {