diff --git a/ocdb.cpp b/ocdb.cpp index b9950d9..12cf1bb 100644 --- a/ocdb.cpp +++ b/ocdb.cpp @@ -55,8 +55,8 @@ bool OCdb::init(const std::string& dump_path) { throw 1; if (!request("CREATE TABLE IF NOT EXISTS revision (revision INTEGER PRIMARY KEY);") || - !request("CREATE TABLE IF NOT EXISTS caches (code TEXT PRIMARY KEY, name TEXT, location TEXT, type TEXT, status INTEGER, size TEXT, difficulty INTEGER, terrain INTEGER, country TEXT, region TEXT, owner TEXT);") || - !request("CREATE TABLE IF NOT EXISTS logs (uuid TEXT PRIMARY KEY, cache_code TEXT, date TEXT, user TEXT, type INTEGER);") || + !request("CREATE TABLE IF NOT EXISTS caches (code INTEGER PRIMARY KEY, name TEXT, location TEXT, type TEXT, status INTEGER, size TEXT, difficulty INTEGER, terrain INTEGER, country TEXT, region TEXT, owner TEXT);") || + !request("CREATE TABLE IF NOT EXISTS logs (uuid TEXT PRIMARY KEY, cache_code INTEGER, date TEXT, user TEXT, type INTEGER);") || !request("CREATE INDEX idx_user on logs (user, type);")) throw 1; request("COMMIT;"); @@ -119,7 +119,9 @@ bool OCdb::parse_item(const json& j) { update_cache(j); } else if (j.count("change_type") && j["change_type"] == "delete") { Debug(2) << "Deleting cache " << j["object_key"]["code"].get() << ".\n"; - sql = "DELETE FROM caches WHERE code='" + j["object_key"]["code"].get() + "';"; + sql = "DELETE FROM caches WHERE code='"; + sql += cache_code_to_int(j["object_key"]["code"].get()); + sql += "';"; request(sql); } else { Debug(1) << "Incorrect change type: " << j["change_type"] << ".\n"; @@ -142,14 +144,14 @@ bool OCdb::parse_item(const json& j) { } bool OCdb::update_cache(const json& j) { - // (code TEXT PRIMARY KEY, name TEXT, location TEXT, type TEXT, status INTEGER, size TEXT, difficulty INTEGER, terrain INTEGER, country TEXT, region TEXT, owner TEXT) + // (code INTEGER PRIMARY KEY, name TEXT, location TEXT, type TEXT, status INTEGER, size TEXT, difficulty INTEGER, terrain INTEGER, country TEXT, region TEXT, owner TEXT) std::map fields; std::map fields2; int res; if (!j.count("object_key") || !j["object_key"].count("code") || !j.count("data")) return 0; - std::string code = j["object_key"]["code"].get(); + int code = cache_code_to_int(j["object_key"]["code"].get()); if (j["data"].count("names") && j["data"]["names"].count("pl") && !j["data"]["names"]["pl"].is_null()) fields["name"] = j["data"]["names"]["pl"].get(); else if (j["data"].count("names") && j["data"]["names"].count("en") && !j["data"]["names"]["en"].is_null()) @@ -189,7 +191,7 @@ bool OCdb::update_cache(const json& j) { for (auto& i : fields2) sql += i.first + ','; sql.pop_back(); - sql += ") VALUES ('" + code + "',"; + sql += ") VALUES ('" + std::to_string(code) + "',"; for (__attribute__((unused)) auto& i : fields) sql += "?,"; for (__attribute__((unused)) auto& i : fields2) @@ -227,7 +229,7 @@ bool OCdb::update_cache(const json& j) { } bool OCdb::update_log(const json& j) { - // logs (uuid TEXT PRIMARY KEY, cache_code TEXT, date TEXT, user TEXT, type TEXT);")) + // logs (uuid TEXT PRIMARY KEY, cache_code INTEGER, date TEXT, user TEXT, type TEXT);")) std::map fields; std::map fields2; int res; @@ -236,7 +238,7 @@ bool OCdb::update_log(const json& j) { std::string uuid = j["object_key"]["uuid"].get(); if (j["data"].count("cache_code") && !j["data"]["cache_code"].is_null()) - fields["cache_code"] = j["data"]["cache_code"].get(); + fields2["cache_code"] = cache_code_to_int(j["data"]["cache_code"].get()); if (j["data"].count("date") && !j["data"]["date"].is_null()) fields["date"] = j["data"]["date"].get(); if (j["data"].count("user") && j["data"]["user"].count("uuid") && !j["data"]["user"]["uuid"].is_null()) @@ -337,7 +339,7 @@ Caches OCdb::get_user_caches_not_found(const std::string& uuid) const { res = sqlite3_step(stmt); while (res == SQLITE_ROW) { Cache c; - if (sqlite3_column_text(stmt, 0)) c.code = reinterpret_cast(sqlite3_column_text(stmt, 0)); + if (sqlite3_column_text(stmt, 0)) c.code = int_to_cache_code(sqlite3_column_int(stmt, 0)); if (sqlite3_column_text(stmt, 1)) c.pos = Position(reinterpret_cast(sqlite3_column_text(stmt, 1))); if (sqlite3_column_text(stmt, 2)) c.region = reinterpret_cast(sqlite3_column_text(stmt, 2)); c.status = ok; @@ -357,7 +359,7 @@ Caches OCdb::get_user_caches_not_found(const std::string& uuid) const { Caches OCdb::get_user_caches(const std::string& uuid, __attribute__((unused)) int count) const { int res; - //code TEXT PRIMARY KEY, name TEXT, location TEXT, type TEXT, status INTEGER, size TEXT, difficulty INTEGER, terrain INTEGER, country TEXT, region TEXT, owner TEXT) + //code INTEGER PRIMARY KEY, name TEXT, location TEXT, type TEXT, status INTEGER, size TEXT, difficulty INTEGER, terrain INTEGER, country TEXT, region TEXT, owner TEXT) sql = "SELECT code, location, type, size, difficulty, terrain, country, region, owner, status, name FROM caches WHERE EXISTS (SELECT cache_code FROM logs WHERE cache_code = code AND type = "; sql += found; sql += " and user = ?);"; @@ -375,7 +377,7 @@ Caches OCdb::get_user_caches(const std::string& uuid, __attribute__((unused)) in Caches OCdb::get_user_caches_owned(const std::string& uuid) const { int res; - //code TEXT PRIMARY KEY, name TEXT, location TEXT, type TEXT, status TEXT, size TEXT, difficulty INTEGER, terrain INTEGER, country TEXT, region TEXT, owner TEXT) + //code INTEGER PRIMARY KEY, name TEXT, location TEXT, type TEXT, status TEXT, size TEXT, difficulty INTEGER, terrain INTEGER, country TEXT, region TEXT, owner TEXT) sql = "SELECT code, location, type, size, difficulty, terrain, country, region, owner, status, name FROM caches WHERE owner = ?;"; res = sqlite3_prepare_v2(db, sql.c_str(), sql.length() + 1, &stmt, NULL); @@ -395,7 +397,7 @@ Caches OCdb::parse_sql_caches() const { res = sqlite3_step(stmt); while (res == SQLITE_ROW) { Cache c; - if (sqlite3_column_text(stmt, 0)) c.code = reinterpret_cast(sqlite3_column_text(stmt, 0)); + if (sqlite3_column_text(stmt, 0)) c.code = int_to_cache_code(sqlite3_column_int(stmt, 0)); if (sqlite3_column_text(stmt, 1)) c.pos = Position(reinterpret_cast(sqlite3_column_text(stmt, 1))); if (sqlite3_column_text(stmt, 2)) c.type = reinterpret_cast(sqlite3_column_text(stmt, 2)); if (sqlite3_column_text(stmt, 3)) c.size = reinterpret_cast(sqlite3_column_text(stmt, 3)); @@ -479,3 +481,43 @@ std::map OCdb::get_region_stats() { sqlite3_finalize(stmt); return count; } + +std::string OCdb::int_to_cache_code(int n) const { + const int n5 = 36 * 36 * 36 * 36; + const int n4 = 36 * 36 * 36; + const int n3 = 36 * 36; + const int n2 = 36; + + int x; + std::stringstream ss; + ss << cache_code_prefix; + + if (n >= n5) { + x = n/n5; + if (x >= 10) ss << static_cast('A' + x - 10); + else ss << x; + n %= n5; + } + x = n/n4; + if (x >= 10) ss << static_cast('A' + x - 10); + else ss << x; + n %= n4; + x = n/n3; + if (x >= 10) ss << static_cast('A' + x - 10); + else ss << x; + n %= n3; + x = n/n2; + if (x >= 10) ss << static_cast('A' + x - 10); + else ss << x; + n %= n2; + x = n; + if (x >= 10) ss << static_cast('A' + x - 10); + else ss << x; + + return ss.str(); +} + +int OCdb::cache_code_to_int(std::string code) const { + code = code.substr(2); + return std::stoi(code, nullptr, 36); +} diff --git a/ocdb.h b/ocdb.h index b9285a6..673c46a 100644 --- a/ocdb.h +++ b/ocdb.h @@ -19,6 +19,10 @@ private: mutable sqlite3_stmt* stmt; mutable std::string sql; int revision; + + std::string cache_code_prefix = "OP"; + std::string int_to_cache_code(int n) const; + int cache_code_to_int(std::string code) const; bool request(const std::string& req) const; bool init_part(const std::string& json_file); // read db dump