#pragma once #include #include #include #include #include #include struct sqlite3; struct lua_State; namespace mosis { // SQL value types using SqlValue = std::variant>; using SqlRow = std::vector; using SqlResult = std::vector; struct DatabaseLimits { size_t max_database_size = 50 * 1024 * 1024; // 50 MB per database int max_databases_per_app = 5; // Max open databases int max_query_time_ms = 5000; // 5 second query timeout int max_result_rows = 10000; // Max rows returned }; class DatabaseHandle; class DatabaseManager { public: DatabaseManager(const std::string& app_id, const std::string& app_root, const DatabaseLimits& limits = DatabaseLimits{}); ~DatabaseManager(); // Database operations std::shared_ptr Open(const std::string& name, std::string& error); void CloseAll(); // Stats size_t GetOpenDatabaseCount() const; private: std::string m_app_id; std::string m_app_root; DatabaseLimits m_limits; std::unordered_map> m_databases; std::string ResolvePath(const std::string& name); bool ValidateName(const std::string& name, std::string& error); }; class DatabaseHandle { public: DatabaseHandle(sqlite3* db, const std::string& path, const DatabaseLimits& limits); ~DatabaseHandle(); // Execute (INSERT, UPDATE, DELETE, CREATE, etc.) bool Execute(const std::string& sql, const std::vector& params, std::string& error); // Query (SELECT) std::optional Query(const std::string& sql, const std::vector& params, std::string& error); // Get last insert rowid int64_t GetLastInsertRowId() const; // Get affected rows int GetChanges() const; bool IsOpen() const { return m_db != nullptr; } void Close(); private: sqlite3* m_db; std::string m_path; DatabaseLimits m_limits; static int Authorizer(void* user_data, int action, const char* arg1, const char* arg2, const char* arg3, const char* arg4); bool BindParameters(void* stmt, const std::vector& params, std::string& error); }; // Register database.* APIs as globals void RegisterDatabaseAPI(lua_State* L, DatabaseManager* manager); } // namespace mosis