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:
parent
326914f92a
commit
80ef2afbee
1 changed files with 34 additions and 13 deletions
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue