#ifndef BIERGARTEN_PIPELINE_INCLUDES_SERVICES_DATABASE_SQLITE_EXPORT_SERVICE_H_ #define BIERGARTEN_PIPELINE_INCLUDES_SERVICES_DATABASE_SQLITE_EXPORT_SERVICE_H_ /** * @file services/sqlite_export_service.h * @brief SQLite-backed export service for generated brewery data. */ #include #include #include #include #include "data_model/models.h" #include "services/database/export_service.h" #include "services/database/sqlite_export_service_helpers.h" #include "services/datetime/date_time_provider.h" /** * @brief Persists generated brewery records into a fresh SQLite database. */ class SqliteExportService final : public IExportService { public: explicit SqliteExportService(const ApplicationOptions& options); ~SqliteExportService() override; SqliteExportService(const SqliteExportService&) = delete; SqliteExportService& operator=(const SqliteExportService&) = delete; SqliteExportService(SqliteExportService&&) = delete; SqliteExportService& operator=(SqliteExportService&&) = delete; void Initialize() override; uint64_t ProcessRecord(const BreweryRecord& brewery) override; uint64_t ProcessRecord(const UserRecord& user) override; void Finalize() override; private: using SqliteDatabaseHandle = sqlite_export_service_internal::SqliteDatabaseHandle; using SqliteStatementHandle = sqlite_export_service_internal::SqliteStatementHandle; void InitializeSchema() const; void PrepareStatements(); void RollbackAndCloseNoThrow() noexcept; [[nodiscard]] std::filesystem::path BuildDatabasePath() const; [[nodiscard]] static std::string BuildCityKey(const City& location); /** * @brief Returns the row id for @p location, inserting it first if it has * not already been seen during this run. * * Shared by both ProcessRecord() overloads so breweries and users * referencing the same location resolve to the same row. */ [[nodiscard]] sqlite3_int64 ResolveCityId(const City& location); std::unique_ptr date_time_provider_; std::filesystem::path output_path_; std::string run_timestamp_utc_; std::filesystem::path database_path_; SqliteDatabaseHandle db_handle_; SqliteStatementHandle insert_city_stmt_; SqliteStatementHandle insert_brewery_stmt_; SqliteStatementHandle insert_brewery_address_stmt_; SqliteStatementHandle insert_user_stmt_; SqliteStatementHandle insert_user_address_stmt_; bool transaction_open_ = false; std::unordered_map city_cache_; }; #endif // BIERGARTEN_PIPELINE_INCLUDES_SERVICES_DATABASE_SQLITE_EXPORT_SERVICE_H_