Add shop snapshots table

It contains the snapshot of each shop and a unique hash.
This is not complete yet, running this update twice will
just corrupt the table.
This commit is contained in:
King_DuckZ 2020-08-14 19:48:14 +01:00
parent 3262ce8d25
commit d4fd25b151

View file

@ -25,6 +25,8 @@
#include "oro/shops.hpp"
#include "oro/creators.hpp"
#include "oro/private/dateconv.hpp"
#include "oro/private/tiger.hpp"
#include "duckhandy/int_conv.hpp"
#include <mutex>
#include <optional>
#include <type_traits>
@ -163,6 +165,36 @@ namespace {
", FOREIGN KEY(item_id) REFERENCES items(id)"
")";
}
std::string shop_hash (const oro::Shop& shop) {
using dhandy::int_to_ary;
mchlib::TigerHash th;
mchlib::tiger_init_hash(th);
std::string buff;
for (const oro::ShopItem& itm : shop.items) {
buff.clear();
buff.append(int_to_ary(itm.item_id).to_string_view()).append("|");
buff.append(int_to_ary(itm.amount).to_string_view()).append("|");
buff.append(int_to_ary(itm.price).to_string_view()).append("|");
buff.append(int_to_ary(itm.refine).to_string_view()).append("|");
buff.append(int_to_ary(itm.star_crumbs).to_string_view()).append("|");
for (unsigned int id : itm.cards) {
buff.append(int_to_ary(id).to_string_view()).append("|");
}
if (itm.element)
buff.append(*itm.element).append("|");
if (itm.creator)
buff.append(int_to_ary(*itm.creator).to_string_view()).append("|");
if (itm.beloved)
buff.append(int_to_ary(*itm.beloved).to_string_view()).append("|");
tiger_data(buff, th);
}
return mchlib::tiger_to_string(th);
}
} //unnamed namespace
OriginsDB::OriginsDB (std::string_view path) :
@ -294,10 +326,19 @@ void OriginsDB::update (const Shops& shops) {
", seen_date TEXT DEFAULT CURRENT_TIMESTAMP"
")"
);
db.exec("CREATE TABLE IF NOT EXISTS shop_snapshots("
"id INTEGER PRIMARY KEY NOT NULL"
", shop_id INTEGER NOT NULL"
", hash TEXT NOT NULL"
", discovery_date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP"
", last_seen_date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP"
", FOREIGN KEY(shop_id) REFERENCES shops(id)"
")"
);
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS shops_owner_idx ON shops(owner, creation_date)");
db.exec("CREATE TABLE IF NOT EXISTS shop_items("
"id INTEGER PRIMARY KEY NOT NULL"
", shop_id INTEGER NOT NULL"
", snapshot_id INTEGER NOT NULL"
", item_id INTEGER NOT NULL"
", amount INTEGER NOT NULL"
", price INTEGER NOT NULL"
@ -306,7 +347,7 @@ void OriginsDB::update (const Shops& shops) {
", element TEXT"
", creator INTEGER"
", beloved TINYINT"
", FOREIGN KEY(shop_id) REFERENCES shops(id)"
", FOREIGN KEY(snapshot_id) REFERENCES shop_snapshots(id)"
", FOREIGN KEY(item_id) REFERENCES items(id)"
")"
);
@ -320,7 +361,8 @@ void OriginsDB::update (const Shops& shops) {
);
SQLite::Statement ins_shop(db, "INSERT INTO shops(title, owner, creation_date, loc_map, loc_x, loc_y, type) VALUES(?, ?, ?, ?, ?, ?, ?)");
SQLite::Statement ins_item(db, "INSERT INTO shop_items(shop_id, item_id, amount, price, refine, star_crumbs, element, creator, beloved) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
SQLite::Statement ins_sshot(db, "INSERT INTO shop_snapshots(shop_id, hash) VALUES(?, ?)");
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(?, ?)");
ItemIdToTableId item_id_to_table_id(db);
@ -328,7 +370,7 @@ void OriginsDB::update (const Shops& shops) {
for (const auto& shop : shops.shops) {
std::optional<oro::Shop> old_shop = fetch_shop(db, shop.owner, shop.creation_date);
if ( old_shop)
if (old_shop)
continue;
ins_shop.bind(1, shop.title);
@ -341,9 +383,17 @@ void OriginsDB::update (const Shops& shops) {
ins_shop.exec();
ins_shop.reset();
const auto shop_id = db.getLastInsertRowid();
{
const auto shop_id = db.getLastInsertRowid();
ins_sshot.bind(1, shop_id);
ins_sshot.bind(2, shop_hash(shop));
ins_sshot.exec();
ins_sshot.reset();
}
const auto sshot_id = db.getLastInsertRowid();
for (const auto& item : shop.items) {
ins_item.bind(1, shop_id);
ins_item.bind(1, sshot_id);
ins_item.bind(2, item_id_to_table_id(item.item_id));
ins_item.bind(3, item.amount);
ins_item.bind(4, item.price);