diff options
Diffstat (limited to 'src/database/database.cpp')
-rw-r--r-- | src/database/database.cpp | 223 |
1 files changed, 118 insertions, 105 deletions
diff --git a/src/database/database.cpp b/src/database/database.cpp index f7d309b..92f7682 100644 --- a/src/database/database.cpp +++ b/src/database/database.cpp @@ -2,171 +2,185 @@ #ifdef USE_DATABASE #include <database/database.hpp> -#include <logger/logger.hpp> -#include <irc/iid.hpp> #include <uuid/uuid.h> #include <utils/get_first_non_empty.hpp> #include <utils/time.hpp> -using namespace std::string_literals; +#include <sqlite3.h> -std::unique_ptr<db::BibouDB> Database::db; +sqlite3* Database::db; +Database::MucLogLineTable Database::muc_log_lines("MucLogLine_"); +Database::GlobalOptionsTable Database::global_options("GlobalOptions_"); +Database::IrcServerOptionsTable Database::irc_server_options("IrcServerOptions_"); +Database::IrcChannelOptionsTable Database::irc_channel_options("IrcChannelOptions_"); -void Database::open(const std::string& filename, const std::string& db_type) +void Database::open(const std::string& filename) { - try + // Try to open the specified database. + // Close and replace the previous database pointer if it succeeded. If it did + // not, just leave things untouched + sqlite3* new_db; + auto res = sqlite3_open_v2(filename.data(), &new_db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + if (res != SQLITE_OK) { - auto new_db = std::make_unique<db::BibouDB>(db_type, - "database="s + filename); - if (new_db->needsUpgrade()) - new_db->upgrade(); - Database::db.reset(new_db.release()); - } catch (const litesql::DatabaseError& e) { - log_error("Failed to open database ", filename, ". ", e.what()); - throw; + log_error("Failed to open database file ", filename, ": ", sqlite3_errmsg(Database::db)); + throw std::runtime_error(""); } + Database::close(); + Database::db = new_db; + Database::muc_log_lines.create(Database::db); + Database::muc_log_lines.upgrade(Database::db); + Database::global_options.create(Database::db); + Database::global_options.upgrade(Database::db); + Database::irc_server_options.create(Database::db); + Database::irc_server_options.upgrade(Database::db); + Database::irc_channel_options.create(Database::db); + Database::irc_channel_options.upgrade(Database::db); } -void Database::set_verbose(const bool val) -{ - Database::db->verbose = val; -} -db::GlobalOptions Database::get_global_options(const std::string& owner) +Database::GlobalOptions Database::get_global_options(const std::string& owner) { - try { - auto options = litesql::select<db::GlobalOptions>(*Database::db, - db::GlobalOptions::Owner == owner).one(); - return options; - } catch (const litesql::NotFound& e) { - db::GlobalOptions options(*Database::db); - options.owner = owner; - return options; - } + auto request = Database::global_options.select(); + request.where() << Owner{} << "=" << owner; + + Database::GlobalOptions options{Database::global_options.get_name()}; + auto result = request.execute(Database::db); + if (result.size() == 1) + options = result.front(); + else + options.col<Owner>() = owner; + return options; } -db::IrcServerOptions Database::get_irc_server_options(const std::string& owner, - const std::string& server) +Database::IrcServerOptions Database::get_irc_server_options(const std::string& owner, const std::string& server) { - try { - auto options = litesql::select<db::IrcServerOptions>(*Database::db, - db::IrcServerOptions::Owner == owner && - db::IrcServerOptions::Server == server).one(); - return options; - } catch (const litesql::NotFound& e) { - db::IrcServerOptions options(*Database::db); - options.owner = owner; - options.server = server; - // options.update(); - return options; - } + auto request = Database::irc_server_options.select(); + request.where() << Owner{} << "=" << owner << " and " << Server{} << "=" << server; + + Database::IrcServerOptions options{Database::irc_server_options.get_name()}; + auto result = request.execute(Database::db); + if (result.size() == 1) + options = result.front(); + else + { + options.col<Owner>() = owner; + options.col<Server>() = server; + } + return options; } -db::IrcChannelOptions Database::get_irc_channel_options(const std::string& owner, - const std::string& server, - const std::string& channel) +Database::IrcChannelOptions Database::get_irc_channel_options(const std::string& owner, const std::string& server, const std::string& channel) { - try { - auto options = litesql::select<db::IrcChannelOptions>(*Database::db, - db::IrcChannelOptions::Owner == owner && - db::IrcChannelOptions::Server == server && - db::IrcChannelOptions::Channel == channel).one(); - return options; - } catch (const litesql::NotFound& e) { - db::IrcChannelOptions options(*Database::db); - options.owner = owner; - options.server = server; - options.channel = channel; - return options; - } + auto request = Database::irc_channel_options.select(); + request.where() << Owner{} << "=" << owner <<\ + " and " << Server{} << "=" << server <<\ + " and " << Channel{} << "=" << channel; + Database::IrcChannelOptions options{Database::irc_channel_options.get_name()}; + auto result = request.execute(Database::db); + if (result.size() == 1) + options = result.front(); + else + { + options.col<Owner>() = owner; + options.col<Server>() = server; + options.col<Channel>() = channel; + } + return options; } -db::IrcChannelOptions Database::get_irc_channel_options_with_server_default(const std::string& owner, - const std::string& server, - const std::string& channel) +Database::IrcChannelOptions Database::get_irc_channel_options_with_server_default(const std::string& owner, const std::string& server, + const std::string& channel) { auto coptions = Database::get_irc_channel_options(owner, server, channel); auto soptions = Database::get_irc_server_options(owner, server); - coptions.encodingIn = get_first_non_empty(coptions.encodingIn.value(), - soptions.encodingIn.value()); - coptions.encodingOut = get_first_non_empty(coptions.encodingOut.value(), - soptions.encodingOut.value()); + coptions.col<EncodingIn>() = get_first_non_empty(coptions.col<EncodingIn>(), + soptions.col<EncodingIn>()); + coptions.col<EncodingOut>() = get_first_non_empty(coptions.col<EncodingOut>(), + soptions.col<EncodingOut>()); - coptions.maxHistoryLength = get_first_non_empty(coptions.maxHistoryLength.value(), - soptions.maxHistoryLength.value()); + coptions.col<MaxHistoryLength>() = get_first_non_empty(coptions.col<MaxHistoryLength>(), + soptions.col<MaxHistoryLength>()); return coptions; } -db::IrcChannelOptions Database::get_irc_channel_options_with_server_and_global_default(const std::string& owner, - const std::string& server, - const std::string& channel) +Database::IrcChannelOptions Database::get_irc_channel_options_with_server_and_global_default(const std::string& owner, const std::string& server, const std::string& channel) { auto coptions = Database::get_irc_channel_options(owner, server, channel); auto soptions = Database::get_irc_server_options(owner, server); auto goptions = Database::get_global_options(owner); - coptions.encodingIn = get_first_non_empty(coptions.encodingIn.value(), - soptions.encodingIn.value()); - coptions.encodingOut = get_first_non_empty(coptions.encodingOut.value(), - soptions.encodingOut.value()); + coptions.col<EncodingIn>() = get_first_non_empty(coptions.col<EncodingIn>(), + soptions.col<EncodingIn>()); - coptions.maxHistoryLength = get_first_non_empty(coptions.maxHistoryLength.value(), - soptions.maxHistoryLength.value(), - goptions.maxHistoryLength.value()); + coptions.col<EncodingOut>() = get_first_non_empty(coptions.col<EncodingOut>(), + soptions.col<EncodingOut>()); + + coptions.col<MaxHistoryLength>() = get_first_non_empty(coptions.col<MaxHistoryLength>(), + soptions.col<MaxHistoryLength>(), + goptions.col<MaxHistoryLength>()); return coptions; } -void Database::store_muc_message(const std::string& owner, const Iid& iid, - Database::time_point date, - const std::string& body, - const std::string& nick) +std::string Database::store_muc_message(const std::string& owner, const std::string& chan_name, + const std::string& server_name, Database::time_point date, + const std::string& body, const std::string& nick) { - db::MucLogLine line(*Database::db); + auto line = Database::muc_log_lines.row(); + + auto uuid = Database::gen_uuid(); - line.uuid = Database::gen_uuid(); - line.owner = owner; - line.ircChanName = iid.get_local(); - line.ircServerName = iid.get_server(); - line.date = date.time_since_epoch().count() / 1'000'000'000; - line.body = body; - line.nick = nick; + line.col<Uuid>() = uuid; + line.col<Owner>() = owner; + line.col<IrcChanName>() = chan_name; + line.col<IrcServerName>() = server_name; + line.col<Date>() = std::chrono::duration_cast<std::chrono::seconds>(date.time_since_epoch()).count(); + line.col<Body>() = body; + line.col<Nick>() = nick; - line.update(); + line.save(Database::db); + + return uuid; } -std::vector<db::MucLogLine> Database::get_muc_logs(const std::string& owner, const std::string& chan_name, const std::string& server, +std::vector<Database::MucLogLine> Database::get_muc_logs(const std::string& owner, const std::string& chan_name, const std::string& server, int limit, const std::string& start, const std::string& end) { - auto request = litesql::select<db::MucLogLine>(*Database::db, - db::MucLogLine::Owner == owner && - db::MucLogLine::IrcChanName == chan_name && - db::MucLogLine::IrcServerName == server); - request.orderBy(db::MucLogLine::Id, false); + auto request = Database::muc_log_lines.select(); + request.where() << Database::Owner{} << "=" << owner << \ + " and " << Database::IrcChanName{} << "=" << chan_name << \ + " and " << Database::IrcServerName{} << "=" << server; - if (limit >= 0) - request.limit(limit); if (!start.empty()) { const auto start_time = utils::parse_datetime(start); if (start_time != -1) - request.where(db::MucLogLine::Date >= start_time); + request << " and " << Database::Date{} << ">=" << start_time; } if (!end.empty()) { const auto end_time = utils::parse_datetime(end); if (end_time != -1) - request.where(db::MucLogLine::Date <= end_time); + request << " and " << Database::Date{} << "<=" << end_time; } - const auto& res = request.all(); - return {res.crbegin(), res.crend()}; + + request.order_by() << Id{} << " DESC "; + + if (limit >= 0) + request.limit() << limit; + + auto result = request.execute(Database::db); + + return {result.crbegin(), result.crend()}; } void Database::close() { - Database::db.reset(nullptr); + sqlite3_close_v2(Database::db); + Database::db = nullptr; } std::string Database::gen_uuid() @@ -178,5 +192,4 @@ std::string Database::gen_uuid() return uuid_str; } - -#endif +#endif
\ No newline at end of file |