Making progress with shop snapshots
This commit is contained in:
parent
afb4fd2d4d
commit
928cabfe34
2 changed files with 123 additions and 31 deletions
|
@ -26,16 +26,20 @@
|
|||
#include "oro/creators.hpp"
|
||||
#include "oro/private/dateconv.hpp"
|
||||
#include "oro/private/tiger.hpp"
|
||||
#include "oro/private/sqlite_helpers.hpp"
|
||||
#include "duckhandy/int_conv.hpp"
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace oro {
|
||||
|
||||
namespace {
|
||||
typedef decltype(std::declval<SQLite::Column>().getInt64()) SQLiteID;
|
||||
|
||||
constexpr const char g_create_fame_list[] =
|
||||
"CREATE TABLE IF NOT EXISTS fame_list("
|
||||
"id INTEGER PRIMARY KEY NOT NULL"
|
||||
|
@ -86,7 +90,6 @@ namespace {
|
|||
", loc_x INTEGER"
|
||||
", loc_y INTEGER"
|
||||
", type TINYINT"
|
||||
", seen_date TEXT DEFAULT CURRENT_TIMESTAMP"
|
||||
")";
|
||||
constexpr const char g_create_items_a[] = "CREATE TABLE IF NOT EXISTS ";
|
||||
constexpr const char g_create_items_b[] =
|
||||
|
@ -157,20 +160,42 @@ namespace {
|
|||
bool m_use_cache;
|
||||
};
|
||||
|
||||
template <typename CastT=void, typename T=void>
|
||||
void bind (SQLite::Statement& st, int idx, const std::optional<T>& val) {
|
||||
if (val) {
|
||||
if constexpr (std::is_same_v<T, CastT> or std::is_same_v<void, CastT>) {
|
||||
st.bind(idx, *val);
|
||||
class InsertShopIfn {
|
||||
public:
|
||||
explicit InsertShopIfn (SQLite::Database& db) :
|
||||
m_sel(db, "SELECT id FROM shops WHERE creation_date = ? AND owner = ?"),
|
||||
m_ins(db, "INSERT INTO shops(title, owner, creation_date, loc_map, loc_x, loc_y, type) VALUES(?, ?, ?, ?, ?, ?, ?)"),
|
||||
m_db(db)
|
||||
{
|
||||
}
|
||||
|
||||
std::pair<SQLiteID, bool> operator() (const oro::Shop& shop) {
|
||||
std::string shop_creation_date = to_sqlite_string(shop.creation_date);
|
||||
|
||||
auto row_id_opt = exec_first_res<SQLiteID>(m_sel, shop_creation_date, shop.owner);
|
||||
if (row_id_opt) {
|
||||
return {*row_id_opt, false};
|
||||
}
|
||||
else {
|
||||
st.bind(idx, static_cast<CastT>(*val));
|
||||
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));
|
||||
m_ins.exec();
|
||||
m_ins.reset();
|
||||
|
||||
return {m_db.getLastInsertRowid(), true};
|
||||
}
|
||||
}
|
||||
else {
|
||||
st.bind(idx, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SQLite::Statement m_sel;
|
||||
SQLite::Statement m_ins;
|
||||
const SQLite::Database& m_db;
|
||||
};
|
||||
|
||||
std::optional<oro::Shop> fetch_shop (
|
||||
SQLite::Database& db,
|
||||
|
@ -364,37 +389,28 @@ void OriginsDB::update (const Shops& shops) {
|
|||
|
||||
Database db(m_db_mutex, m_path);
|
||||
db.exec(g_create_shops);
|
||||
db.exec(g_create_shop_snapshots);
|
||||
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS shops_owner_idx ON shops(owner, creation_date)");
|
||||
db.exec(g_create_shop_snapshots);
|
||||
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS shop_snapshots_shop_hash_idx ON shop_snapshots(shop_id, hash)");
|
||||
db.exec(g_create_shop_items);
|
||||
db.exec(g_create_slotted_cards);
|
||||
|
||||
SQLite::Statement ins_shop(db, "INSERT INTO shops(title, owner, creation_date, loc_map, loc_x, loc_y, type) VALUES(?, ?, ?, ?, ?, ?, ?)");
|
||||
SQLite::Statement ins_sshot(db, "INSERT INTO shop_snapshots(shop_id, hash) VALUES(?, ?)");
|
||||
SQLite::Statement ins_sshot(db, "INSERT OR IGNORE INTO shop_snapshots(shop_id, hash) VALUES(?, ?)");
|
||||
SQLite::Statement sel_sshot(db, "SELECT id FROM shop_snapshots WHERE shop_id = ? AND hash = ?");
|
||||
SQLite::Statement ins_item(db, "INSERT INTO shop_items(snapshot_id, item_id, amount, price, refine, star_crumbs, element, creator, beloved) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
SQLite::Statement ins_card(db, "INSERT INTO slotted_cards(shop_item_id, card_id) VALUES(?, ?)");
|
||||
|
||||
InsertShopIfn insert_shop_ifn(db);
|
||||
ItemIdToTableId item_id_to_table_id(db);
|
||||
SQLite::Transaction transaction(db);
|
||||
for (const auto& shop : shops.shops) {
|
||||
std::optional<oro::Shop> old_shop = fetch_shop(db, shop.owner, shop.creation_date);
|
||||
|
||||
if (old_shop)
|
||||
continue;
|
||||
|
||||
ins_shop.bind(1, shop.title);
|
||||
ins_shop.bind(2, shop.owner);
|
||||
ins_shop.bind(3, to_sqlite_string(shop.creation_date));
|
||||
ins_shop.bind(4, shop.location.map);
|
||||
ins_shop.bind(5, shop.location.x);
|
||||
ins_shop.bind(6, shop.location.y);
|
||||
ins_shop.bind(7, static_cast<int>(shop.type.value));
|
||||
ins_shop.exec();
|
||||
ins_shop.reset();
|
||||
|
||||
{
|
||||
const auto shop_id = db.getLastInsertRowid();
|
||||
ins_sshot.bind(1, shop_id);
|
||||
const auto shop_id_ins = insert_shop_ifn(shop);
|
||||
auto sshot_id_ins = exec_first_res<SQLiteID>(sel_sshot, shop_id_ins.first, shop_hash(shop));
|
||||
if (sshot_id_ins)
|
||||
continue;
|
||||
|
||||
ins_sshot.bind(1, shop_id_ins.first);
|
||||
ins_sshot.bind(2, shop_hash(shop));
|
||||
ins_sshot.exec();
|
||||
ins_sshot.reset();
|
||||
|
|
76
src/oro/private/sqlite_helpers.hpp
Normal file
76
src/oro/private/sqlite_helpers.hpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* Copyright 2020, Michele Santullo
|
||||
* This file is part of orotool.
|
||||
*
|
||||
* Orotool is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Orotool is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Orotool. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SQLiteCpp/Statement.h"
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
namespace oro {
|
||||
namespace detail {
|
||||
template <typename CastT=void, typename T=void>
|
||||
void bind (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));
|
||||
}
|
||||
else {
|
||||
st.bind(idx, static_cast<CastT>(val));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename CastT=void, typename T=void>
|
||||
void bind (SQLite::Statement& st, int idx, const std::optional<T>& val) {
|
||||
if (val)
|
||||
detail::bind (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) {
|
||||
const int dummy = (
|
||||
bind(st, Indices + 1, std::forward<Args>(args)), ..., 0
|
||||
);
|
||||
static_cast<void>(dummy);
|
||||
}
|
||||
} //namespace detail
|
||||
|
||||
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)...);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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)...);
|
||||
|
||||
std::optional<T> retval;
|
||||
if (st.executeStep()) {
|
||||
retval = st.getColumn(0);
|
||||
}
|
||||
|
||||
st.reset();
|
||||
return retval;
|
||||
}
|
||||
} //namespace oro
|
Loading…
Reference in a new issue