Same treatment as items table, don't drop/re-create

This works in a much simpler way than the items table.
Here we just upsert new values, with the unique constraint
on the internal item_id (not the upstream one, which is
never entered into this table).
This should mean that if an item from the items table with
eg: item_id=501,id=9 gets marked as deleted and re-entered as
item_id=501,id=5000, then icon with item_id=9 should remain
in the table (there is no delete ever), and a new one with
item_id=5000 gets added. Originally they both referred to
item 501 and they still do, but because of how the items
table now works, icons should also benefit and historical
data should remain in the face of upstream changes.
This commit is contained in:
King_DuckZ 2020-08-12 01:33:13 +01:00
parent 326914f92a
commit 80ef2afbee

View file

@ -46,14 +46,15 @@ namespace {
class ItemIdToTableId {
public:
explicit ItemIdToTableId (SQLite::Database& db) :
explicit ItemIdToTableId (SQLite::Database& db, bool with_caching=true) :
m_db(db),
m_query(m_db, "SELECT id FROM items WHERE item_id = ? AND removal_date IS NULL")
m_query(m_db, "SELECT id FROM items WHERE item_id = ? AND removal_date IS NULL"),
m_use_cache(with_caching)
{
}
int64_t operator() (int item_id) {
{
if (m_use_cache) {
auto it_found = m_cache.find(item_id);
if (m_cache.end() != it_found)
return it_found->second;
@ -67,7 +68,9 @@ namespace {
const int64_t table_id = m_query.getColumn(0);
m_query.reset();
m_cache[item_id] = table_id;
if (m_use_cache)
m_cache[item_id] = table_id;
return table_id;
}
@ -75,6 +78,7 @@ namespace {
std::unordered_map<int, int64_t> m_cache;
SQLite::Database& m_db;
SQLite::Statement m_query;
bool m_use_cache;
};
template <typename CastT=void, typename T=void>
@ -149,6 +153,16 @@ namespace {
", removal_date TEXT"
")";
}
std::string string_query_create_icons (std::string_view table) {
return std::string(
"CREATE TABLE IF NOT EXISTS ").append(table) + " ("
"id INTEGER PRIMARY KEY NOT NULL"
", item_id INTEGER NOT NULL"
", icon TEXT"
", FOREIGN KEY(item_id) REFERENCES items(id)"
")";
}
} //unnamed namespace
OriginsDB::OriginsDB (std::string_view path) :
@ -226,23 +240,30 @@ void OriginsDB::update (const Icons& icons) {
//}
Database db(m_db_mutex, m_path);
db.exec("DROP TABLE IF EXISTS icons");
db.exec(
"CREATE TABLE icons("
"item_id INTEGER PRIMARY KEY NOT NULL"
", icon TEXT"
")"
);
SQLite::Statement query(db, "INSERT INTO icons(item_id, icon) VALUES(?, ?)");
db.exec(string_query_create_icons("icons_staging"));
db.exec(string_query_create_icons("icons"));
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS icons_item_id_idx ON icons(item_id)");
SQLite::Statement query(db, "INSERT INTO icons_staging(item_id, icon) VALUES(?, ?)");
ItemIdToTableId item_id_to_table_id(db, false);
SQLite::Transaction transaction(db);
for (const auto& ico : icons.icons) {
query.bind(1, ico.item_id);
query.bind(1, item_id_to_table_id(ico.item_id));
query.bind(2, ico.icon);
query.exec();
query.reset();
//base64_decode(std::string_view(ico.icon).substr(std::string_view("data:image/png;base64,").size()));
}
db.exec(
"INSERT INTO icons (item_id, icon) "
"SELECT item_id, icon FROM icons_staging WHERE true "
"ON CONFLICT(item_id) DO UPDATE SET "
"icon=excluded.icon"
);
db.exec("DROP TABLE icons_staging");
transaction.commit();
}
void OriginsDB::update (const Shops& shops) {