diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp @@ -493,6 +493,69 @@ Logger::log("Encryption completed successfully."); } +auto &SQLiteQueryExecutor::getStorage() { + static auto storage = make_storage( + SQLiteQueryExecutor::sqliteFilePath, + make_index("messages_idx_thread_time", &Message::thread, &Message::time), + make_index("media_idx_container", &Media::container), + make_table( + "drafts", + make_column("key", &Draft::key, unique(), primary_key()), + make_column("text", &Draft::text)), + make_table( + "messages", + make_column("id", &Message::id, unique(), primary_key()), + make_column("local_id", &Message::local_id), + make_column("thread", &Message::thread), + make_column("user", &Message::user), + make_column("type", &Message::type), + make_column("future_type", &Message::future_type), + make_column("content", &Message::content), + make_column("time", &Message::time)), + make_table( + "olm_persist_account", + make_column("id", &OlmPersistAccount::id, unique(), primary_key()), + make_column("account_data", &OlmPersistAccount::account_data)), + make_table( + "olm_persist_sessions", + make_column( + "target_user_id", + &OlmPersistSession::target_user_id, + unique(), + primary_key()), + make_column("session_data", &OlmPersistSession::session_data)), + make_table( + "media", + make_column("id", &Media::id, unique(), primary_key()), + make_column("container", &Media::container), + make_column("thread", &Media::thread), + make_column("uri", &Media::uri), + make_column("type", &Media::type), + make_column("extras", &Media::extras)), + make_table( + "threads", + make_column("id", &Thread::id, unique(), primary_key()), + make_column("type", &Thread::type), + make_column("name", &Thread::name), + make_column("description", &Thread::description), + make_column("color", &Thread::color), + make_column("creation_time", &Thread::creation_time), + make_column("parent_thread_id", &Thread::parent_thread_id), + make_column("containing_thread_id", &Thread::containing_thread_id), + make_column("community", &Thread::community), + make_column("members", &Thread::members), + make_column("roles", &Thread::roles), + make_column("current_user", &Thread::current_user), + make_column("source_message_id", &Thread::source_message_id), + make_column("replies_count", &Thread::replies_count)), + make_table( + "metadata", + make_column("name", &Metadata::name, unique(), primary_key()), + make_column("data", &Metadata::data))); + storage.on_open = on_database_open; + return storage; +} + typedef bool ShouldBeInTransaction; typedef std::pair, ShouldBeInTransaction> SQLiteMigration; @@ -537,6 +600,30 @@ version_msg << "db version: " << current_user_version << std::endl; Logger::log(version_msg.str()); + if (current_user_version == 0) { + SQLiteQueryExecutor::getStorage().sync_schema(); + + Logger::log("Creating new database, syncing structure with ORM storage."); + + auto latest_version = migrations.back().first; + + std::stringstream update_version; + update_version << "PRAGMA user_version=" << latest_version << ";"; + auto update_version_str = update_version.str(); + + char *error; + sqlite3_exec(db, update_version_str.c_str(), nullptr, nullptr, &error); + + if (error) { + std::ostringstream errorStream; + errorStream << "Error saving database version: " << error; + throw std::system_error( + errno, std::generic_category(), errorStream.str()); + } + + return; + } + for (const auto &[idx, migration] : migrations) { if (idx <= current_user_version) { continue; @@ -581,69 +668,6 @@ SQLiteQueryExecutor::encryptionKey = encryptionKey; } -auto &SQLiteQueryExecutor::getStorage() { - static auto storage = make_storage( - SQLiteQueryExecutor::sqliteFilePath, - make_index("messages_idx_thread_time", &Message::thread, &Message::time), - make_index("media_idx_container", &Media::container), - make_table( - "drafts", - make_column("key", &Draft::key, unique(), primary_key()), - make_column("text", &Draft::text)), - make_table( - "messages", - make_column("id", &Message::id, unique(), primary_key()), - make_column("local_id", &Message::local_id), - make_column("thread", &Message::thread), - make_column("user", &Message::user), - make_column("type", &Message::type), - make_column("future_type", &Message::future_type), - make_column("content", &Message::content), - make_column("time", &Message::time)), - make_table( - "olm_persist_account", - make_column("id", &OlmPersistAccount::id, unique(), primary_key()), - make_column("account_data", &OlmPersistAccount::account_data)), - make_table( - "olm_persist_sessions", - make_column( - "target_user_id", - &OlmPersistSession::target_user_id, - unique(), - primary_key()), - make_column("session_data", &OlmPersistSession::session_data)), - make_table( - "media", - make_column("id", &Media::id, unique(), primary_key()), - make_column("container", &Media::container), - make_column("thread", &Media::thread), - make_column("uri", &Media::uri), - make_column("type", &Media::type), - make_column("extras", &Media::extras)), - make_table( - "threads", - make_column("id", &Thread::id, unique(), primary_key()), - make_column("type", &Thread::type), - make_column("name", &Thread::name), - make_column("description", &Thread::description), - make_column("color", &Thread::color), - make_column("creation_time", &Thread::creation_time), - make_column("parent_thread_id", &Thread::parent_thread_id), - make_column("containing_thread_id", &Thread::containing_thread_id), - make_column("community", &Thread::community), - make_column("members", &Thread::members), - make_column("roles", &Thread::roles), - make_column("current_user", &Thread::current_user), - make_column("source_message_id", &Thread::source_message_id), - make_column("replies_count", &Thread::replies_count)), - make_table( - "metadata", - make_column("name", &Metadata::name, unique(), primary_key()), - make_column("data", &Metadata::data))); - storage.on_open = on_database_open; - return storage; -} - void SQLiteQueryExecutor::initialize(std::string &databasePath) { std::call_once(SQLiteQueryExecutor::initialized, [&databasePath]() { SQLiteQueryExecutor::sqliteFilePath = databasePath;