#ifndef UGCLOOKUPSQL_H #define UGCLOOKUPSQL_H #include #include #include "IUgcLookup.h" /** * The SQL IUgcLookup runs, the same on MySQL and SQLite. Ids are numbers, so they are written into the query; the * search text is bound (TEXT_BINDS times, always, so the statement's parameters don't change with the search). */ namespace UgcLookupSql { constexpr int TEXT_BINDS = 6; inline std::string IdList(const std::vector& ids) { std::string list; for (const auto id : ids) list += (list.empty() ? "" : ",") + std::to_string(id); return list; } // The columns every entry query selects, for models (ugc AS u) or modular builds (ugc_modular_build AS b) inline std::string Select(bool modular) { return modular ? "SELECT b.ugc_id AS id, b.character_id, c.name AS character_name, COALESCE(c.account_id, 0) AS account_id, a.name AS account_name, " "b.is_optimized, b.process_error, b.ldf_config AS detail FROM ugc_modular_build AS b " "LEFT JOIN charinfo AS c ON c.id = b.character_id LEFT JOIN accounts AS a ON a.id = c.account_id " : "SELECT u.id, u.character_id, c.name AS character_name, u.account_id, a.name AS account_name, " "u.is_optimized, u.process_error, u.filename AS detail FROM ugc AS u " "LEFT JOIN charinfo AS c ON c.id = u.character_id LEFT JOIN accounts AS a ON a.id = u.account_id "; } // WHERE for a search; binds the search's %text% TEXT_BINDS times inline std::string Where(const IUgcLookup::UgcSearch& search, bool modular) { using eField = IUgcLookup::UgcSearch::eField; const auto field = search.field; const bool any = field == eField::ANY; const bool num = search.number.has_value(); const bool txt = !search.text.empty(); const std::string n = num ? std::to_string(*search.number) : "NULL"; const std::string id = modular ? "b.ugc_id" : "u.id"; const std::string character = modular ? "b.character_id" : "u.character_id"; const std::string account = modular ? "c.account_id" : "u.account_id"; const std::string detail = modular ? "b.ldf_config" : "u.filename"; const auto on = [](bool value) { return std::string(value ? "1=1" : "0=1"); }; const std::string placed = "SELECT 1 FROM properties_contents AS pc WHERE pc.ugc_id = " + id; std::string where = "WHERE (0=1"; if (num && (any || field == eField::ID)) { where += " OR " + id + " = " + n + " OR " + character + " = " + n + " OR " + account + " = " + n + " OR EXISTS (" + placed + " AND (pc.id = " + n + " OR pc.property_id = " + n + "))"; } if (num && field == eField::OWNER) where += " OR " + character + " = " + n + " OR " + account + " = " + n; if (num && (any || field == eField::LOT)) { if (modular) where += " OR b.ldf_config LIKE '%:" + n + "+%' OR b.ldf_config LIKE '%:" + n + "'"; else where += " OR EXISTS (" + placed + " AND pc.lot = " + n + ")"; } // The bound text: owner (2), property (1), model (3) where += " OR (" + on(txt && (any || field == eField::OWNER)) + " AND (c.name LIKE ? OR a.name LIKE ?))"; where += " OR (" + on((txt && any) || field == eField::PROPERTY) + " AND EXISTS (SELECT 1 FROM properties_contents AS pc " "JOIN properties AS p ON p.id = pc.property_id WHERE pc.ugc_id = " + id + " AND ((" + on(txt) + " AND p.name LIKE ?) OR p.id = " + n + ")))"; where += " OR (" + on(txt && (any || field == eField::MODEL)) + " AND (" + detail + " LIKE ? OR EXISTS (" + placed + " AND (pc.model_name LIKE ? OR pc.model_description LIKE ?))))"; return where + ") "; } inline std::string Placements(const std::vector& ugcIds) { return "SELECT pc.ugc_id, pc.id, pc.lot, pc.property_id, p.name AS property_name, p.owner_id, c.name AS owner_name, p.zone_id, " "pc.model_name, pc.model_description FROM properties_contents AS pc JOIN properties AS p ON p.id = pc.property_id " "LEFT JOIN charinfo AS c ON c.id = p.owner_id WHERE pc.ugc_id IN (" + IdList(ugcIds) + ") ORDER BY pc.id;"; } inline std::string Mail(const std::vector& subkeys, LOT modelItemLot) { return "SELECT id, receiver_id, receiver_name, attachment_lot, attachment_subkey, attachment_config FROM mail WHERE attachment_count > 0 AND " "(attachment_lot = " + std::to_string(modelItemLot) + (subkeys.empty() ? "" : " OR attachment_subkey IN (" + IdList(subkeys) + ")") + ") ORDER BY id DESC LIMIT 500;"; } } #endif //!UGCLOOKUPSQL_H