diff --git a/packages/sqflite/sqflite_aurora/aurora/CMakeLists.txt b/packages/sqflite/sqflite_aurora/aurora/CMakeLists.txt index a4cdaf0..ca1f6e2 100644 --- a/packages/sqflite/sqflite_aurora/aurora/CMakeLists.txt +++ b/packages/sqflite/sqflite_aurora/aurora/CMakeLists.txt @@ -19,10 +19,11 @@ pkg_check_modules(FlutterEmbedder REQUIRED IMPORTED_TARGET flutter-embedder) pkg_check_modules(SQLite REQUIRED IMPORTED_TARGET sqlite3) add_library(${PLUGIN_NAME} SHARED - lib/asynq.cpp + lib/async_queue.cpp lib/database.cpp lib/logger.cpp - lib/sqflite_aurora_plugin.cpp) + lib/sqflite_aurora_plugin.cpp + lib/utils.cpp) set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::FlutterEmbedder PkgConfig::SQLite) diff --git a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/asynq.h b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/async_queue.h similarity index 81% rename from packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/asynq.h rename to packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/async_queue.h index 7c801d9..1b46375 100644 --- a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/asynq.h +++ b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/async_queue.h @@ -8,14 +8,10 @@ #include #include #include -#include #include +#include -#ifdef PLUGIN_IMPL -#define PLUGIN_EXPORT __attribute__((visibility("default"))) -#else -#define PLUGIN_EXPORT -#endif +#include class PLUGIN_EXPORT AsyncQueue final { @@ -26,7 +22,7 @@ public: AsyncQueue(); ~AsyncQueue(); - void Push(const Task &task); + void push(const Task &task); private: void run(); diff --git a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/constants.h b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/constants.h index ba3f905..39c7a03 100644 --- a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/constants.h +++ b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/constants.h @@ -7,55 +7,55 @@ #include -const std::string METHOD_GET_PLATFORM_VERSION = "getPlatformVersion"; -const std::string METHOD_GET_DATABASES_PATH = "getDatabasesPath"; -const std::string METHOD_DEBUG = "debug"; -const std::string METHOD_OPTIONS = "options"; -const std::string METHOD_OPEN_DATABASE = "openDatabase"; -const std::string METHOD_CLOSE_DATABASE = "closeDatabase"; -const std::string METHOD_INSERT = "insert"; -const std::string METHOD_EXECUTE = "execute"; -const std::string METHOD_QUERY = "query"; -const std::string METHOD_QUERY_CURSOR_NEXT = "queryCursorNext"; -const std::string METHOD_UPDATE = "update"; -const std::string METHOD_BATCH = "batch"; -const std::string METHOD_DELETE_DATABASE = "deleteDatabase"; -const std::string METHOD_DATABASE_EXISTS = "databaseExists"; +const inline std::string METHOD_GET_PLATFORM_VERSION = "getPlatformVersion"; +const inline std::string METHOD_GET_DATABASES_PATH = "getDatabasesPath"; +const inline std::string METHOD_DEBUG = "debug"; +const inline std::string METHOD_OPTIONS = "options"; +const inline std::string METHOD_OPEN_DATABASE = "openDatabase"; +const inline std::string METHOD_CLOSE_DATABASE = "closeDatabase"; +const inline std::string METHOD_INSERT = "insert"; +const inline std::string METHOD_EXECUTE = "execute"; +const inline std::string METHOD_QUERY = "query"; +const inline std::string METHOD_QUERY_CURSOR_NEXT = "queryCursorNext"; +const inline std::string METHOD_UPDATE = "update"; +const inline std::string METHOD_BATCH = "batch"; +const inline std::string METHOD_DELETE_DATABASE = "deleteDatabase"; +const inline std::string METHOD_DATABASE_EXISTS = "databaseExists"; -const std::string ARG_ID = "id"; -const std::string ARG_PATH = "path"; -const std::string ARG_READ_ONLY = "readOnly"; -const std::string ARG_SINGLE_INSTANCE = "singleInstance"; -const std::string ARG_LOG_LEVEL = "logLevel"; -const std::string ARG_TRANSACTION_ID = "transactionId"; -const std::string ARG_IN_TRANSACTION = "inTransaction"; -const std::string ARG_RECOVERED = "recovered"; -const std::string ARG_RECOVERED_IN_TRANSACTION = "recoveredInTransaction"; -const std::string ARG_SQL = "sql"; -const std::string ARG_SQL_ARGUMENTS = "arguments"; -const std::string ARG_NO_RESULT = "noResult"; -const std::string ARG_CONTINUE_ON_ERROR = "continueOnError"; -const std::string ARG_COLUMNS = "columns"; -const std::string ARG_ROWS = "rows"; -const std::string ARG_DATABASES = "databases"; -const std::string ARG_COMMAND = "cmd"; -const std::string ARG_OPERATIONS = "operations"; -const std::string ARG_METHOD = "method"; -const std::string ARG_RESULT = "result"; -const std::string ARG_ERROR = "error"; -const std::string ARG_ERROR_CODE = "code"; -const std::string ARG_ERROR_MESSAGE = "message"; -const std::string ARG_ERROR_DATA = "data"; -const std::string ARG_CURSOR_PAGE_SIZE = "cursorPageSize"; -const std::string ARG_CURSOR_ID = "cursorId"; -const std::string ARG_CANCEL = "cancel"; +const inline std::string ARG_ID = "id"; +const inline std::string ARG_PATH = "path"; +const inline std::string ARG_READ_ONLY = "readOnly"; +const inline std::string ARG_SINGLE_INSTANCE = "singleInstance"; +const inline std::string ARG_LOG_LEVEL = "logLevel"; +const inline std::string ARG_TRANSACTION_ID = "transactionId"; +const inline std::string ARG_IN_TRANSACTION = "inTransaction"; +const inline std::string ARG_RECOVERED = "recovered"; +const inline std::string ARG_RECOVERED_IN_TRANSACTION = "recoveredInTransaction"; +const inline std::string ARG_SQL = "sql"; +const inline std::string ARG_SQL_ARGUMENTS = "arguments"; +const inline std::string ARG_NO_RESULT = "noResult"; +const inline std::string ARG_CONTINUE_ON_ERROR = "continueOnError"; +const inline std::string ARG_COLUMNS = "columns"; +const inline std::string ARG_ROWS = "rows"; +const inline std::string ARG_DATABASES = "databases"; +const inline std::string ARG_COMMAND = "cmd"; +const inline std::string ARG_OPERATIONS = "operations"; +const inline std::string ARG_METHOD = "method"; +const inline std::string ARG_RESULT = "result"; +const inline std::string ARG_ERROR = "error"; +const inline std::string ARG_ERROR_CODE = "code"; +const inline std::string ARG_ERROR_MESSAGE = "message"; +const inline std::string ARG_ERROR_DATA = "data"; +const inline std::string ARG_CURSOR_PAGE_SIZE = "cursorPageSize"; +const inline std::string ARG_CURSOR_ID = "cursorId"; +const inline std::string ARG_CANCEL = "cancel"; -const std::string ERROR_SQFLITE = "sqlite_error"; -const std::string ERROR_OPEN = "open_failed"; -const std::string ERROR_CLOSE = "close_failed"; -const std::string ERROR_CLOSED = "database_closed"; -const std::string ERROR_BAD_PARAM = "bad_param"; -const std::string ERROR_BAD_ARGS = "bad_arguments"; -const std::string ERROR_INTERNAL = "internal"; +const inline std::string ERROR_SQFLITE = "sqlite_error"; +const inline std::string ERROR_OPEN = "open_failed"; +const inline std::string ERROR_CLOSE = "close_failed"; +const inline std::string ERROR_CLOSED = "database_closed"; +const inline std::string ERROR_BAD_PARAM = "bad_param"; +const inline std::string ERROR_BAD_ARGS = "bad_arguments"; +const inline std::string ERROR_INTERNAL = "internal"; #endif /* FLUTTER_PLUGIN_SQFLITE_CONSTANTS_H */ diff --git a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/database.h b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/database.h index a067a7a..76bd1ac 100644 --- a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/database.h +++ b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/database.h @@ -8,21 +8,16 @@ #include #include +#include #include +#include #include -#include #include #include #include #include -#ifdef PLUGIN_IMPL -#define PLUGIN_EXPORT __attribute__((visibility("default"))) -#else -#define PLUGIN_EXPORT -#endif - class PLUGIN_EXPORT Database final { public: @@ -46,70 +41,64 @@ public: }; public: - Database(int id, const std::string &path, bool singleton, const Logger &logger); + Database(int id, const std::string &path, bool singleInstance, const Logger &logger); ~Database(); public: - std::optional Open(); - std::optional OpenReadOnly(); - std::optional Close(); - std::optional Execute(const std::string &sql, const Encodable::List &args); - std::optional QueryCursorNext(int cursorID, bool cancel, Encodable::Map &result); - std::optional Query(const std::string &sql, - const Encodable::List &args, - Encodable::Map &result); - std::optional QueryWithPageSize(const std::string &sql, - const Encodable::List &args, - int64_t pageSize, - Encodable::Map &result); - std::optional Insert(const std::string &sql, - const Encodable::List &args, - int &insertID); - std::optional Update(const std::string &sql, - const Encodable::List &args, - int &updated); - std::optional Batch(const std::vector &operations, - bool continueOnError, - Encodable::List &results); - - void EnterInTransaction(); - void LeaveTransaction(); - int CurrentTransactionID(); + utils::error open(); + utils::error openReadOnly(); + utils::error close(); + utils::error execute(const std::string &sql, const Encodable::List &args); + utils::error queryCursorNext(int cursorID, bool cancel, Encodable::Map &result); + utils::error query(const std::string &sql, const Encodable::List &args, Encodable::Map &result); + utils::error queryWithPageSize(const std::string &sql, + const Encodable::List &args, + int64_t pageSize, + Encodable::Map &result); + utils::error insert(const std::string &sql, const Encodable::List &args, int &insertID); + utils::error update(const std::string &sql, const Encodable::List &args, int &updated); + utils::error batch(const std::vector &operations, + bool continueOnError, + Encodable::List &results); + + void enterInTransaction(); + void leaveTransaction(); + int currentTransactionID(); typedef std::function SqlCommandCallback; - void ProcessSqlCommand(int transactionID, const SqlCommandCallback &callback); + void processSqlCommand(int transactionID, const SqlCommandCallback &callback); public: - bool IsOpen() const; - bool IsSingleInstance() const; - bool IsInTransaction() const; - bool IsInMemory() const; - bool IsReadOnly() const; + bool isOpen() const; + bool isSingleInstance() const; + bool isInTransaction() const; + bool isInMemory() const; + bool isReadOnly() const; - const std::string &Path() const; - int64_t ID() const; - Logger::Level LogLevel() const; + const std::string &path() const; + int64_t id() const; + Logger::Level logLevel() const; private: std::string currentErrorMessage(); - std::optional createParentDir(); - std::optional bindStmtArgs(sqlite3_stmt *stmt, const Encodable::List &args); + utils::error createParentDir(); + utils::error bindStmtArgs(sqlite3_stmt *stmt, const Encodable::List &args); void closeCursor(const Cursor &cursor); - std::optional resultFromCursor(const Cursor &cursor, Encodable::Map &result); + utils::error resultFromCursor(const Cursor &cursor, Encodable::Map &result); private: - int64_t id; - std::string path; - bool isSingleInstance; - bool isReadOnly; - Logger logger; - int transactionID; - int currentTransactionID; - std::queue pendingSqlCallbacks; - int64_t cursorID; - std::unordered_map cursors; - sqlite3 *db; + int64_t m_id; + std::string m_path; + bool m_isSingleInstance; + bool m_isReadOnly; + Logger m_logger; + int m_transactionID; + int m_currentTransactionID; + std::queue m_pendingSqlCallbacks; + int64_t m_cursorID; + std::unordered_map m_cursors; + sqlite3 *m_db; }; #endif /* FLUTTER_PLUGIN_SQFLITE_DATABASE_H */ diff --git a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/globals.h b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/globals.h new file mode 100644 index 0000000..45d7824 --- /dev/null +++ b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/globals.h @@ -0,0 +1,10 @@ +#ifndef FLUTTER_PLUGIN_SQFLITE_GLOBALS_H +#define FLUTTER_PLUGIN_SQFLITE_GLOBALS_H + +#ifdef PLUGIN_IMPL +#define PLUGIN_EXPORT __attribute__((visibility("default"))) +#else +#define PLUGIN_EXPORT +#endif + +#endif /* FLUTTER_PLUGIN_SQFLITE_GLOBALS_H */ diff --git a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/logger.h b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/logger.h index aefcd7a..3d16fc5 100644 --- a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/logger.h +++ b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/logger.h @@ -6,14 +6,9 @@ #define FLUTTER_PLUGIN_SQFLITE_LOGGER_H #include +#include #include -#ifdef PLUGIN_IMPL -#define PLUGIN_EXPORT __attribute__((visibility("default"))) -#else -#define PLUGIN_EXPORT -#endif - class PLUGIN_EXPORT Logger final { public: @@ -26,19 +21,19 @@ public: public: Logger(Level level, const std::string &tag); - Level LogLevel() const; - void SetLogLevel(Level level); + Level logLevel() const; + void setLogLevel(Level level); - std::string Tag() const; - void SetTag(const std::string &tag); + std::string tag() const; + void setTag(const std::string &tag); std::ostream &verb(); std::ostream &sql(); private: - Level level; - std::string tag; - std::ostream devnull; + Level m_level; + std::string m_tag; + std::ostream m_devnull; }; #endif /* FLUTTER_PLUGIN_SQFLITE_LOGGER_H */ diff --git a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/sqflite_aurora_plugin.h b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/sqflite_aurora_plugin.h index 2390334..7620948 100644 --- a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/sqflite_aurora_plugin.h +++ b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/sqflite_aurora_plugin.h @@ -7,19 +7,14 @@ #include -#include +#include #include +#include #include #include #include -#ifdef PLUGIN_IMPL -#define PLUGIN_EXPORT __attribute__((visibility("default"))) -#else -#define PLUGIN_EXPORT -#endif - class PLUGIN_EXPORT SqfliteAuroraPlugin final : public PluginInterface { public: @@ -49,23 +44,23 @@ private: void databaseRemove(std::shared_ptr db); void databaseAdd(std::shared_ptr db); - void success(const MethodCall &call, const Encodable &result = nullptr); - void error(const MethodCall &call, - const std::string &error, - const std::string &message, - const std::string &desc = "", - const Encodable &details = nullptr); + void sendSuccess(const MethodCall &call, const Encodable &result = nullptr); + void sendError(const MethodCall &call, + const std::string &error, + const std::string &message, + const std::string &desc = "", + const Encodable &details = nullptr); Encodable::Map makeOpenResult(int64_t dbID, bool recovered, bool recoveredInTransaction); private: - std::mutex mutex; - std::unordered_map> singletonDatabases; - std::unordered_map> databases; - int64_t dbID = 0; - Logger logger; - bool queryAsMapList = false; - AsyncQueue asynq; + std::mutex m_mutex; + std::unordered_map> m_singleInstanceDatabases; + std::unordered_map> m_databases; + int64_t m_dbID = 0; + Logger m_logger; + bool m_queryAsMapList = false; + AsyncQueue m_asyncQueue; }; #endif /* FLUTTER_PLUGIN_SQFLITE_H */ diff --git a/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/utils.h b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/utils.h new file mode 100644 index 0000000..810de0e --- /dev/null +++ b/packages/sqflite/sqflite_aurora/aurora/include/sqflite_aurora/utils.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023. Open Mobile Platform LLC. + * License: Proprietary. + */ +#ifndef FLUTTER_PLUGIN_SQFLITE_UTILS_H +#define FLUTTER_PLUGIN_SQFLITE_UTILS_H + +#include +#include + +namespace utils { + +class error final +{ +public: + explicit error(std::string message); + error() = default; + + explicit operator bool() const; + const std::string &message() const; + + static error none(); + +private: + std::optional m_message; +}; + +} /* namespace utils */ + +#endif /* FLUTTER_PLUGIN_SQFLITE_UTILS_H */ diff --git a/packages/sqflite/sqflite_aurora/aurora/lib/asynq.cpp b/packages/sqflite/sqflite_aurora/aurora/lib/async_queue.cpp similarity index 90% rename from packages/sqflite/sqflite_aurora/aurora/lib/asynq.cpp rename to packages/sqflite/sqflite_aurora/aurora/lib/async_queue.cpp index 7731ce9..d9171c9 100644 --- a/packages/sqflite/sqflite_aurora/aurora/lib/asynq.cpp +++ b/packages/sqflite/sqflite_aurora/aurora/lib/async_queue.cpp @@ -2,7 +2,7 @@ * Copyright (c) 2023. Open Mobile Platform LLC. * License: Proprietary. */ -#include +#include AsyncQueue::AsyncQueue() : m_running(false) @@ -15,7 +15,7 @@ AsyncQueue::~AsyncQueue() m_thread.join(); } -void AsyncQueue::Push(const Task &task) +void AsyncQueue::push(const Task &task) { if (!m_running) { m_running = true; @@ -38,8 +38,8 @@ void AsyncQueue::run() const auto task = m_tasks.front(); m_tasks.pop(); - lock.unlock(); + lock.unlock(); task(); } } diff --git a/packages/sqflite/sqflite_aurora/aurora/lib/database.cpp b/packages/sqflite/sqflite_aurora/aurora/lib/database.cpp index 8d95a65..15d6123 100644 --- a/packages/sqflite/sqflite_aurora/aurora/lib/database.cpp +++ b/packages/sqflite/sqflite_aurora/aurora/lib/database.cpp @@ -10,11 +10,13 @@ namespace { -void addError(Encodable::List &results, const std::string &error) +void addError(Encodable::List &results, const utils::error &error) { - results.emplace_back(Encodable::Map{ - {"error", Encodable::Map{{"message", error}}}, - }); + if (error) { + results.emplace_back(Encodable::Map{ + {"error", Encodable::Map{{"message", error.message()}}}, + }); + } } template @@ -25,72 +27,72 @@ void addResult(Encodable::List &results, const T &result) } /* namespace */ -Database::Database(int id, const std::string &path, bool singleton, const Logger &logger) - : id(id) - , path(path) - , isSingleInstance(singleton) - , logger(logger.LogLevel(), logger.Tag() + "-db-" + std::to_string(id)) - , transactionID(0) - , currentTransactionID(TransactionID::None) - , cursorID(0) - , db(nullptr) +Database::Database(int id, const std::string &path, bool singleInstance, const Logger &logger) + : m_id(id) + , m_path(path) + , m_isSingleInstance(singleInstance) + , m_logger(logger.logLevel(), logger.tag() + "-db-" + std::to_string(id)) + , m_transactionID(0) + , m_currentTransactionID(TransactionID::None) + , m_cursorID(0) + , m_db(nullptr) {} Database::~Database() { - Close(); + close(); } -std::optional Database::Open() +utils::error Database::open() { - const auto error = this->createParentDir(); + const auto error = createParentDir(); if (error) return error; - int result_code = sqlite3_open_v2(this->path.c_str(), - &this->db, + int result_code = sqlite3_open_v2(m_path.c_str(), + &m_db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); if (result_code != SQLITE_OK) - return this->currentErrorMessage(); + return utils::error(currentErrorMessage()); - this->isReadOnly = false; - return std::nullopt; + m_isReadOnly = false; + return utils::error::none(); } -std::optional Database::OpenReadOnly() +utils::error Database::openReadOnly() { - const auto error = this->createParentDir(); + const auto error = createParentDir(); if (error) return error; - int result_code = sqlite3_open_v2(this->path.c_str(), &this->db, SQLITE_OPEN_READONLY, nullptr); + int result_code = sqlite3_open_v2(m_path.c_str(), &m_db, SQLITE_OPEN_READONLY, nullptr); if (result_code != SQLITE_OK) - return this->currentErrorMessage(); + return utils::error(currentErrorMessage()); - this->isReadOnly = true; - return std::nullopt; + m_isReadOnly = true; + return utils::error::none(); } -std::optional Database::Close() +utils::error Database::close() { - if (sqlite3_close_v2(this->db) != SQLITE_OK) - return this->currentErrorMessage(); + if (sqlite3_close_v2(m_db) != SQLITE_OK) + return utils::error(currentErrorMessage()); - this->db = nullptr; - this->pendingSqlCallbacks = {}; + m_db = nullptr; + m_pendingSqlCallbacks = {}; - return std::nullopt; + return utils::error::none(); } -std::optional Database::Execute(const std::string &sql, const Encodable::List &args) +utils::error Database::execute(const std::string &sql, const Encodable::List &args) { sqlite3_stmt *stmt = nullptr; - if (sqlite3_prepare_v2(this->db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) - return this->currentErrorMessage(); + if (sqlite3_prepare_v2(m_db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) + return utils::error(currentErrorMessage()); - const auto error = this->bindStmtArgs(stmt, args); + const auto error = bindStmtArgs(stmt, args); if (error) { sqlite3_finalize(stmt); @@ -107,23 +109,23 @@ std::optional Database::Execute(const std::string &sql, const Encod break; sqlite3_finalize(stmt); - return this->currentErrorMessage(); + return utils::error(currentErrorMessage()); } sqlite3_finalize(stmt); - return std::nullopt; + return utils::error::none(); } -std::optional Database::Query(const std::string &sql, +utils::error Database::query(const std::string &sql, const Encodable::List &args, Encodable::Map &result) { sqlite3_stmt *stmt = nullptr; - if (sqlite3_prepare_v2(this->db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) - return this->currentErrorMessage(); + if (sqlite3_prepare_v2(m_db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) + return utils::error(currentErrorMessage()); - const auto error = this->bindStmtArgs(stmt, args); + const auto error = bindStmtArgs(stmt, args); if (error) { sqlite3_finalize(stmt); @@ -184,206 +186,206 @@ std::optional Database::Query(const std::string &sql, break; sqlite3_finalize(stmt); - return this->currentErrorMessage(); + return utils::error(currentErrorMessage()); } result = Encodable::Map{{"columns", columns}, {"rows", rows}}; sqlite3_finalize(stmt); - return std::nullopt; + return utils::error::none(); } -std::optional Database::QueryWithPageSize(const std::string &sql, +utils::error Database::queryWithPageSize(const std::string &sql, const Encodable::List &args, int64_t pageSize, Encodable::Map &result) { sqlite3_stmt *stmt = nullptr; - if (sqlite3_prepare_v2(this->db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) - return this->currentErrorMessage(); + if (sqlite3_prepare_v2(m_db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) + return utils::error(currentErrorMessage()); - const auto error = this->bindStmtArgs(stmt, args); + const auto error = bindStmtArgs(stmt, args); if (error) return error; - this->cursorID += 1; - this->cursors[cursorID] = Cursor{this->cursorID, stmt, pageSize}; + m_cursorID += 1; + m_cursors[m_cursorID] = Cursor{m_cursorID, stmt, pageSize}; - return resultFromCursor(this->cursors[cursorID], result); + return resultFromCursor(m_cursors[m_cursorID], result); } -std::optional Database::QueryCursorNext(int cursorID, +utils::error Database::queryCursorNext(int cursorID, bool cancel, Encodable::Map &result) { - this->logger.verb() << "querying cursor next (ID=" << cursorID << "; CANCEL=" << cancel << ")" - << std::endl; + m_logger.verb() << "querying cursor next (ID=" << cursorID << "; CANCEL=" << cancel << ")" + << std::endl; - if (!this->cursors.count(cursorID)) - return "cursor not found"; + if (!m_cursors.count(cursorID)) + return utils::error("cursor not found"); - const Cursor &cursor = this->cursors[cursorID]; + const Cursor &cursor = m_cursors[cursorID]; if (cancel) { - this->closeCursor(cursor); - return std::nullopt; + closeCursor(cursor); + return utils::error::none(); } - return this->resultFromCursor(cursor, result); + return resultFromCursor(cursor, result); } -std::optional Database::Insert(const std::string &sql, +utils::error Database::insert(const std::string &sql, const Encodable::List &args, int &insertID) { - if (this->isReadOnly) - return "database is readonly"; + if (m_isReadOnly) + return utils::error("database is readonly"); - const auto error = this->Execute(sql, args); + const auto error = execute(sql, args); if (error) return error; - const int updated = sqlite3_changes(this->db); + const int updated = sqlite3_changes(m_db); - this->logger.sql() << "rows updated: " << updated << std::endl; + m_logger.sql() << "rows updated: " << updated << std::endl; if (updated == 0) { insertID = 0; - return std::nullopt; + return utils::error::none(); } - insertID = sqlite3_last_insert_rowid(this->db); - this->logger.sql() << "last inserted row id: " << insertID << std::endl; + insertID = sqlite3_last_insert_rowid(m_db); + m_logger.sql() << "last inserted row id: " << insertID << std::endl; - return std::nullopt; + return utils::error::none(); } -std::optional Database::Update(const std::string &sql, +utils::error Database::update(const std::string &sql, const Encodable::List &args, int &updated) { - if (this->isReadOnly) - return "database is readonly"; + if (m_isReadOnly) + return utils::error("database is readonly"); - const auto error = this->Execute(sql, args); + const auto error = execute(sql, args); if (error) return error; - updated = sqlite3_changes(this->db); - this->logger.sql() << "rows updated: " << updated << std::endl; + updated = sqlite3_changes(m_db); + m_logger.sql() << "rows updated: " << updated << std::endl; - return std::nullopt; + return utils::error::none(); } -void Database::ProcessSqlCommand(int transactionID, const SqlCommandCallback &callback) +void Database::processSqlCommand(int transactionID, const SqlCommandCallback &callback) { - if (this->currentTransactionID == TransactionID::None) { + if (m_currentTransactionID == TransactionID::None) { callback(); return; } - if (transactionID == this->currentTransactionID || transactionID == TransactionID::Force) { + if (transactionID == m_currentTransactionID || transactionID == TransactionID::Force) { callback(); - if (this->currentTransactionID == TransactionID::None) { - while (!this->pendingSqlCallbacks.empty() && this->IsOpen()) { - const auto &pendingCallback = this->pendingSqlCallbacks.front(); + if (m_currentTransactionID == TransactionID::None) { + while (!m_pendingSqlCallbacks.empty() && isOpen()) { + const auto &pendingCallback = m_pendingSqlCallbacks.front(); pendingCallback(); - this->pendingSqlCallbacks.pop(); + m_pendingSqlCallbacks.pop(); } } return; } - this->pendingSqlCallbacks.push(callback); + m_pendingSqlCallbacks.push(callback); } -void Database::EnterInTransaction() +void Database::enterInTransaction() { - this->transactionID += 1; - this->currentTransactionID = this->transactionID; + m_transactionID += 1; + m_currentTransactionID = m_transactionID; } -void Database::LeaveTransaction() +void Database::leaveTransaction() { - this->currentTransactionID = TransactionID::None; + m_currentTransactionID = TransactionID::None; } -int Database::CurrentTransactionID() +int Database::currentTransactionID() { - return this->currentTransactionID; + return m_currentTransactionID; } -bool Database::IsOpen() const +bool Database::isOpen() const { - return this->db != nullptr; + return m_db != nullptr; } -const std::string &Database::Path() const +const std::string &Database::path() const { - return this->path; + return m_path; } -bool Database::IsSingleInstance() const +bool Database::isSingleInstance() const { - return this->isSingleInstance; + return m_isSingleInstance; } -bool Database::IsReadOnly() const +bool Database::isReadOnly() const { - return this->isReadOnly; + return m_isReadOnly; } -bool Database::IsInTransaction() const +bool Database::isInTransaction() const { - return this->currentTransactionID != TransactionID::None; + return m_currentTransactionID != TransactionID::None; } -int64_t Database::ID() const +int64_t Database::id() const { - return this->id; + return m_id; } -Logger::Level Database::LogLevel() const +Logger::Level Database::logLevel() const { - return this->logger.LogLevel(); + return m_logger.logLevel(); } -bool Database::IsInMemory() const +bool Database::isInMemory() const { - return this->path.empty() || this->path == ":memory:"; + return m_path.empty() || m_path == ":memory:"; } std::string Database::currentErrorMessage() { - const auto message = sqlite3_errmsg(this->db); - const auto code = sqlite3_extended_errcode(this->db); + const auto message = sqlite3_errmsg(m_db); + const auto code = sqlite3_extended_errcode(m_db); return std::string(message) + " (" + std::to_string(code) + ")"; } -std::optional Database::createParentDir() +utils::error Database::createParentDir() { - if (this->IsInMemory()) - return std::nullopt; + if (isInMemory()) + return utils::error::none(); - const auto parentDir = std::filesystem::path(this->path).parent_path(); + const auto parentDir = std::filesystem::path(m_path).parent_path(); if (std::filesystem::exists(parentDir)) - return std::nullopt; + return utils::error::none(); if (std::filesystem::create_directories(parentDir)) - return std::nullopt; + return utils::error::none(); - return "couldn't create parent directory"; + return utils::error("couldn't create parent directory"); } -std::optional Database::bindStmtArgs(sqlite3_stmt *stmt, const Encodable::List &args) +utils::error Database::bindStmtArgs(sqlite3_stmt *stmt, const Encodable::List &args) { int result = SQLITE_OK; @@ -451,12 +453,12 @@ std::optional Database::bindStmtArgs(sqlite3_stmt *stmt, const Enco for (const auto &entry : arg.GetList()) { if (!entry.IsInt()) - return "only list of bytes is supported for statement parameter"; + return utils::error("only list of bytes is supported for statement parameter"); const auto value = entry.GetInt(); if (value < 0 || value > 255) - return "only list of bytes is supported for statement parameter"; + return utils::error("only list of bytes is supported for statement parameter"); container.push_back(static_cast(value)); } @@ -467,25 +469,25 @@ std::optional Database::bindStmtArgs(sqlite3_stmt *stmt, const Enco container.size(), SQLITE_TRANSIENT); } else { - return "statement parameter has invalid type"; + return utils::error("statement parameter has invalid type"); } if (result != SQLITE_OK) - return this->currentErrorMessage(); + return utils::error(currentErrorMessage()); } - this->logger.sql() << sqlite3_expanded_sql(stmt) << std::endl; - return std::nullopt; + m_logger.sql() << sqlite3_expanded_sql(stmt) << std::endl; + return utils::error::none(); } void Database::closeCursor(const Cursor &cursor) { - logger.verb() << "closing cursor (ID=" << cursor.id << ")" << std::endl; + m_logger.verb() << "closing cursor (ID=" << cursor.id << ")" << std::endl; sqlite3_finalize(cursor.stmt); - this->cursors.erase(cursor.id); + m_cursors.erase(cursor.id); } -std::optional Database::resultFromCursor(const Cursor &cursor, Encodable::Map &result) +utils::error Database::resultFromCursor(const Cursor &cursor, Encodable::Map &result) { Encodable::List columns; @@ -540,12 +542,12 @@ std::optional Database::resultFromCursor(const Cursor &cursor, Enco } if (status == SQLITE_DONE) { - this->closeCursor(cursor); + closeCursor(cursor); break; } - this->closeCursor(cursor); - return this->currentErrorMessage(); + closeCursor(cursor); + return utils::error(currentErrorMessage()); } result = Encodable::Map{{"columns", columns}, {"rows", rows}}; @@ -553,10 +555,10 @@ std::optional Database::resultFromCursor(const Cursor &cursor, Enco if (status != SQLITE_DONE) result.insert({ARG_CURSOR_ID, cursor.id}); - return std::nullopt; + return utils::error::none(); } -std::optional Database::Batch(const std::vector &operations, +utils::error Database::batch(const std::vector &operations, bool continueOnError, Encodable::List &results) { @@ -565,13 +567,13 @@ std::optional Database::Batch(const std::vector &operati if (method == METHOD_INSERT) { int insertID = 0; - const auto error = this->Insert(operation.sql, operation.arguments, insertID); + const auto error = insert(operation.sql, operation.arguments, insertID); if (error) { if (!continueOnError) return error; - addError(results, *error); + addError(results, error); continue; } @@ -584,13 +586,13 @@ std::optional Database::Batch(const std::vector &operati } if (method == METHOD_EXECUTE) { - const auto error = this->Execute(operation.sql, operation.arguments); + const auto error = execute(operation.sql, operation.arguments); if (error) { if (!continueOnError) return error; - addError(results, *error); + addError(results, error); continue; } @@ -600,13 +602,13 @@ std::optional Database::Batch(const std::vector &operati if (method == METHOD_QUERY) { Encodable::Map result; - const auto error = this->Query(operation.sql, operation.arguments, result); + const auto error = query(operation.sql, operation.arguments, result); if (error) { if (!continueOnError) return error; - addError(results, *error); + addError(results, error); continue; } @@ -616,13 +618,13 @@ std::optional Database::Batch(const std::vector &operati if (method == METHOD_UPDATE) { int updated = 0; - const auto error = this->Update(operation.sql, operation.arguments, updated); + const auto error = update(operation.sql, operation.arguments, updated); if (error) { if (!continueOnError) return error; - addError(results, *error); + addError(results, error); continue; } @@ -631,5 +633,5 @@ std::optional Database::Batch(const std::vector &operati } } - return std::nullopt; + return utils::error::none(); } diff --git a/packages/sqflite/sqflite_aurora/aurora/lib/logger.cpp b/packages/sqflite/sqflite_aurora/aurora/lib/logger.cpp index ef13340..7355880 100644 --- a/packages/sqflite/sqflite_aurora/aurora/lib/logger.cpp +++ b/packages/sqflite/sqflite_aurora/aurora/lib/logger.cpp @@ -6,43 +6,43 @@ #include Logger::Logger(Level level, const std::string &tag) - : level(level) - , tag(tag) - , devnull(0) + : m_level(level) + , m_tag(tag) + , m_devnull(0) {} -Logger::Level Logger::LogLevel() const +Logger::Level Logger::logLevel() const { - return this->level; + return m_level; } -void Logger::SetLogLevel(Level level) +void Logger::setLogLevel(Level level) { - this->level = level; + m_level = level; } -std::string Logger::Tag() const +std::string Logger::tag() const { - return this->tag; + return m_tag; } -void Logger::SetTag(const std::string &tag) +void Logger::setTag(const std::string &tag) { - this->tag = tag; + m_tag = tag; } std::ostream &Logger::verb() { - if (this->level >= Level::Verbose) - return loginfo << (this->tag.empty() ? "" : "[" + this->tag + "] "); + if (m_level >= Level::Verbose) + return loginfo << (m_tag.empty() ? "" : "[" + m_tag + "] "); - return this->devnull; + return m_devnull; } std::ostream &Logger::sql() { - if (this->level >= Level::Sql) - return loginfo << (this->tag.empty() ? "" : "[" + this->tag + "] "); + if (m_level >= Level::Sql) + return loginfo << (m_tag.empty() ? "" : "[" + m_tag + "] "); - return this->devnull; + return m_devnull; } diff --git a/packages/sqflite/sqflite_aurora/aurora/lib/sqflite_aurora_plugin.cpp b/packages/sqflite/sqflite_aurora/aurora/lib/sqflite_aurora_plugin.cpp index ed6a83b..c60d17c 100644 --- a/packages/sqflite/sqflite_aurora/aurora/lib/sqflite_aurora_plugin.cpp +++ b/packages/sqflite/sqflite_aurora/aurora/lib/sqflite_aurora_plugin.cpp @@ -13,7 +13,7 @@ namespace { -int64_t GetTransactionID(const Encodable &args) +int64_t getTransactionID(const Encodable &args) { if (!args.HasKey(ARG_TRANSACTION_ID)) return static_cast(Database::TransactionID::None); @@ -27,7 +27,7 @@ int64_t GetTransactionID(const Encodable &args) return args[ARG_TRANSACTION_ID].GetInt(); } -Encodable::List GetSqlArguments(const Encodable &args) +Encodable::List getSqlArguments(const Encodable &args) { if (!args.HasKey(ARG_SQL_ARGUMENTS)) return Encodable::List{}; @@ -44,15 +44,15 @@ Encodable::List GetSqlArguments(const Encodable &args) } /* namespace */ SqfliteAuroraPlugin::SqfliteAuroraPlugin() - : dbID(0) - , logger(Logger::Level::None, "sqflite") + : m_dbID(0) + , m_logger(Logger::Level::None, "sqflite") {} void SqfliteAuroraPlugin::RegisterWithRegistrar(PluginRegistrar ®istrar) { registrar.RegisterMethodChannel("com.tekartik.sqflite", MethodCodecType::Standard, - [this](const MethodCall &call) { this->onMethodCall(call); }); + [this](const MethodCall &call) { onMethodCall(call); }); } void SqfliteAuroraPlugin::onMethodCall(const MethodCall &call) @@ -60,76 +60,76 @@ void SqfliteAuroraPlugin::onMethodCall(const MethodCall &call) const auto &method = call.GetMethod(); if (method == METHOD_GET_PLATFORM_VERSION) { - this->onPlatformVersionCall(call); + onPlatformVersionCall(call); return; } if (method == METHOD_OPEN_DATABASE) { - this->onOpenDatabaseCall(call); + onOpenDatabaseCall(call); return; } if (method == METHOD_CLOSE_DATABASE) { - this->onCloseDatabaseCall(call); + onCloseDatabaseCall(call); return; } if (method == METHOD_DELETE_DATABASE) { - this->onDeleteDatabaseCall(call); + onDeleteDatabaseCall(call); return; } if (method == METHOD_DATABASE_EXISTS) { - this->onDatabaseExistsCall(call); + onDatabaseExistsCall(call); return; } if (method == METHOD_GET_DATABASES_PATH) { - this->onGetDatabasesPathCall(call); + onGetDatabasesPathCall(call); return; } if (method == METHOD_OPTIONS) { - this->onOptionsCall(call); + onOptionsCall(call); return; } if (method == METHOD_DEBUG) { - this->onDebugCall(call); + onDebugCall(call); return; } if (method == METHOD_EXECUTE) { - this->onExecuteCall(call); + onExecuteCall(call); return; } if (method == METHOD_QUERY) { - this->onQueryCall(call); + onQueryCall(call); return; } if (method == METHOD_QUERY_CURSOR_NEXT) { - this->onQueryCursorNextCall(call); + onQueryCursorNextCall(call); return; } if (method == METHOD_UPDATE) { - this->onUpdateCall(call); + onUpdateCall(call); return; } if (method == METHOD_INSERT) { - this->onInsertCall(call); + onInsertCall(call); return; } if (method == METHOD_BATCH) { - this->onBatchCall(call); + onBatchCall(call); return; } - this->success(call); + sendSuccess(call); } void SqfliteAuroraPlugin::onPlatformVersionCall(const MethodCall &call) @@ -141,122 +141,114 @@ void SqfliteAuroraPlugin::onPlatformVersionCall(const MethodCall &call) if (line.rfind("VERSION_ID=") != 0) continue; - this->success(call, "Aurora " + line.substr(11)); + sendSuccess(call, "Aurora " + line.substr(11)); return; } - this->success(call, "Aurora"); + sendSuccess(call, "Aurora"); } void SqfliteAuroraPlugin::onOpenDatabaseCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - - const auto dbPath = args[ARG_PATH].GetString(); - const auto readOnly = args.HasKey(ARG_READ_ONLY) ? args[ARG_READ_ONLY].GetBoolean() : false; + const auto dbPath = call.GetArgument(ARG_PATH); + const auto readOnly = call.GetArgument(ARG_READ_ONLY, false); const auto inMemory = dbPath.empty() || dbPath == ":memory:"; - const auto singleton = args[ARG_SINGLE_INSTANCE].GetBoolean() && !inMemory; + const auto isSingleInstance = call.GetArgument(ARG_SINGLE_INSTANCE) + && !inMemory; - if (singleton) { - const auto db = this->databaseByPath(dbPath); + if (isSingleInstance) { + const auto db = databaseByPath(dbPath); if (db) { - if (db->IsOpen()) { - this->logger.verb() << "re-opened single instance database" - << (db->IsInTransaction() ? "(in transaction) " : "") - << db->ID() << " " << db->Path() << std::endl; + if (db->isOpen()) { + m_logger.verb() << "re-opened single instance database" + << (db->isInTransaction() ? "(in transaction) " : "") << db->id() + << " " << db->path() << std::endl; - this->success(call, makeOpenResult(db->ID(), true, db->IsInTransaction())); + sendSuccess(call, makeOpenResult(db->id(), true, db->isInTransaction())); return; } - this->logger.verb() << "single instance database " << db->Path() << " not opened" - << std::endl; + m_logger.verb() << "single instance database " << db->path() << " not opened" + << std::endl; } } - const auto db = std::make_shared(++dbID, dbPath, singleton, logger); + const auto db = std::make_shared(++m_dbID, dbPath, isSingleInstance, m_logger); - this->asynq.Push([this, db, readOnly, call] { - this->logger.sql() << "open database " + db->Path() + " (ID=" << db->ID() << ")" - << std::endl; + m_asyncQueue.push([this, db, readOnly, call] { + m_logger.sql() << "open database " + db->path() + " (ID=" << db->id() << ")" << std::endl; - const auto error = readOnly ? db->OpenReadOnly() : db->Open(); + const auto error = readOnly ? db->openReadOnly() : db->open(); if (error) { - this->error(call, ERROR_OPEN, db->Path(), *error); + sendError(call, ERROR_OPEN, db->path(), error.message()); return; } - this->databaseAdd(db); - this->success(call, makeOpenResult(db->ID(), false, false)); + databaseAdd(db); + sendSuccess(call, makeOpenResult(db->id(), false, false)); }); } void SqfliteAuroraPlugin::onCloseDatabaseCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - const auto dbID = args[ARG_ID].GetInt(); - + const auto dbID = call.GetArgument(ARG_ID); const auto db = databaseByID(dbID); - this->asynq.Push([this, db, dbID, call] { + m_asyncQueue.push([this, db, dbID, call] { if (!db) { - this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); + sendError(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); return; } - this->logger.sql() << "closing database with ID=" << db->ID() << std::endl; + m_logger.sql() << "closing database with ID=" << db->id() << std::endl; - const auto error = db->Close(); + const auto error = db->close(); if (error) { - this->error(call, ERROR_CLOSE, db->Path(), *error); + sendError(call, ERROR_CLOSE, db->path(), error.message()); return; } - this->databaseRemove(db); - this->success(call); + databaseRemove(db); + sendSuccess(call); }); } void SqfliteAuroraPlugin::onDeleteDatabaseCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - const auto dbPath = args[ARG_PATH].GetString(); - + const auto dbPath = call.GetArgument(ARG_PATH); const auto db = databaseByPath(dbPath); - this->asynq.Push([this, db, dbPath, call] { + m_asyncQueue.push([this, db, dbPath, call] { if (db) { - if (db->IsOpen()) { - this->logger.verb() - << "close database " << db->Path() << " (ID=" << db->ID() << ")" << std::endl; + if (db->isOpen()) { + m_logger.verb() << "close database " << db->path() << " (ID=" << db->id() << ")" + << std::endl; - const auto error = db->Close(); + const auto error = db->close(); if (error) { - this->error(call, ERROR_CLOSE, db->Path(), *error); + sendError(call, ERROR_CLOSE, db->path(), error.message()); return; } } - this->databaseRemove(db); + databaseRemove(db); } if (std::filesystem::exists(dbPath)) { - this->logger.verb() << "delete not opened database " << dbPath << std::endl; + m_logger.verb() << "delete not opened database " << dbPath << std::endl; std::filesystem::remove(dbPath); } - this->success(call); + sendSuccess(call); }); } void SqfliteAuroraPlugin::onDatabaseExistsCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - const auto dbPath = args[ARG_PATH].GetString(); - - this->success(call, std::filesystem::exists(dbPath)); + const auto dbPath = call.GetArgument(ARG_PATH); + sendSuccess(call, std::filesystem::exists(dbPath)); } void SqfliteAuroraPlugin::onGetDatabasesPathCall(const MethodCall &call) @@ -264,48 +256,46 @@ void SqfliteAuroraPlugin::onGetDatabasesPathCall(const MethodCall &call) const auto home = std::getenv("HOME"); if (home == nullptr) { - this->error(call, ERROR_INTERNAL, "environment variable $HOME not found"); + sendError(call, ERROR_INTERNAL, "environment variable $HOME not found"); return; } const auto [orgname, appname] = Application::GetID(); const auto directory = std::filesystem::path(home) / ".local/share" / orgname / appname; - this->success(call, directory.generic_string()); + sendSuccess(call, directory.generic_string()); } void SqfliteAuroraPlugin::onOptionsCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - const auto level = args[ARG_LOG_LEVEL].GetInt(); + const auto level = call.GetArgument(ARG_LOG_LEVEL); + m_logger.setLogLevel(static_cast(level)); - this->logger.SetLogLevel(static_cast(level)); - this->success(call); + sendSuccess(call); } void SqfliteAuroraPlugin::onDebugCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - const auto cmd = args[ARG_COMMAND].GetString(); + const auto cmd = call.GetArgument(ARG_COMMAND); - std::lock_guard lock(this->mutex); + std::lock_guard lock(m_mutex); Encodable::Map result; if (cmd == "get") { - if (this->logger.LogLevel() > Logger::Level::None) - result.emplace(ARG_LOG_LEVEL, static_cast(this->logger.LogLevel())); + if (m_logger.logLevel() > Logger::Level::None) + result.emplace(ARG_LOG_LEVEL, static_cast(m_logger.logLevel())); - if (!this->databases.empty()) { + if (!m_databases.empty()) { Encodable::Map databases; - for (const auto &[id, db] : this->databases) { + for (const auto &[id, db] : m_databases) { Encodable::Map info; - info.emplace(ARG_PATH, db->Path()); - info.emplace(ARG_SINGLE_INSTANCE, db->IsSingleInstance()); + info.emplace(ARG_PATH, db->path()); + info.emplace(ARG_SINGLE_INSTANCE, db->isSingleInstance()); - if (db->LogLevel() > Logger::Level::None) - info.emplace(ARG_LOG_LEVEL, static_cast(db->LogLevel())); + if (db->logLevel() > Logger::Level::None) + info.emplace(ARG_LOG_LEVEL, static_cast(db->logLevel())); databases.emplace(std::to_string(id), info); } @@ -314,211 +304,197 @@ void SqfliteAuroraPlugin::onDebugCall(const MethodCall &call) } } - this->success(call, result); + sendSuccess(call, result); } void SqfliteAuroraPlugin::onExecuteCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - - const auto dbID = args[ARG_ID].GetInt(); - const auto sql = args[ARG_SQL].GetString(); - const auto sqlArgs = GetSqlArguments(args); - const auto inTransactionChange = args.HasKey(ARG_IN_TRANSACTION) - ? args[ARG_IN_TRANSACTION].GetBoolean() - : false; - const auto transactionID = GetTransactionID(args); + const auto dbID = call.GetArgument(ARG_ID); + const auto sql = call.GetArgument(ARG_SQL); + const auto inTransactionChange = call.GetArgument(ARG_IN_TRANSACTION, false); + + const auto sqlArgs = getSqlArguments(call.GetArguments()); + const auto transactionID = getTransactionID(call.GetArguments()); const auto enteringTransaction = inTransactionChange == true && transactionID == Database::TransactionID::None; const auto db = databaseByID(dbID); if (!db) { - this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); + sendError(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); return; } - this->asynq.Push( - [this, db, sql, sqlArgs, inTransactionChange, enteringTransaction, transactionID, call] { - db->ProcessSqlCommand( - transactionID, - [this, db, sql, sqlArgs, inTransactionChange, enteringTransaction, call] { - if (enteringTransaction) - db->EnterInTransaction(); - - const auto error = db->Execute(sql, sqlArgs); - - if (error) { - db->LeaveTransaction(); - this->error(call, ERROR_INTERNAL, *error); - return; - } - - if (enteringTransaction) { - this->success(call, - Encodable::Map{ - {ARG_TRANSACTION_ID, db->CurrentTransactionID()}, - }); - return; - } - - if (inTransactionChange == false) - db->LeaveTransaction(); - - this->success(call); - }); + m_asyncQueue.push([this, + db, + sql, + sqlArgs, + inTransactionChange, + enteringTransaction, + transactionID, + call] { + db->processSqlCommand(transactionID, [this, db, sql, sqlArgs, inTransactionChange, enteringTransaction, call] { + if (enteringTransaction) + db->enterInTransaction(); + + const auto error = db->execute(sql, sqlArgs); + + if (error) { + db->leaveTransaction(); + sendError(call, ERROR_INTERNAL, error.message()); + return; + } + + if (enteringTransaction) { + sendSuccess(call, Encodable::Map{{ARG_TRANSACTION_ID, db->currentTransactionID()}}); + return; + } + + if (inTransactionChange == false) + db->leaveTransaction(); + + sendSuccess(call); }); + }); } void SqfliteAuroraPlugin::onQueryCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - - const auto dbID = args[ARG_ID].GetInt(); - const auto sql = args[ARG_SQL].GetString(); - const auto sqlArgs = GetSqlArguments(args); - const auto transactionID = GetTransactionID(args); - const auto pageSize = args.HasKey(ARG_CURSOR_PAGE_SIZE) ? args[ARG_CURSOR_PAGE_SIZE].GetInt() - : -1; + const auto dbID = call.GetArgument(ARG_ID); + const auto sql = call.GetArgument(ARG_SQL); + const auto pageSize = call.GetArgument(ARG_CURSOR_PAGE_SIZE, -1); + + const auto sqlArgs = getSqlArguments(call.GetArguments()); + const auto transactionID = getTransactionID(call.GetArguments()); const auto db = databaseByID(dbID); if (!db) { - this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); + sendError(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); return; } - this->asynq.Push([this, db, sql, sqlArgs, transactionID, pageSize, call] { - db->ProcessSqlCommand(transactionID, [this, db, sql, sqlArgs, pageSize, call] { + m_asyncQueue.push([this, db, sql, sqlArgs, transactionID, pageSize, call] { + db->processSqlCommand(transactionID, [this, db, sql, sqlArgs, pageSize, call] { Encodable::Map result; - std::optional error; + utils::error error; if (pageSize <= 0) - error = db->Query(sql, sqlArgs, result); + error = db->query(sql, sqlArgs, result); else - error = db->QueryWithPageSize(sql, sqlArgs, pageSize, result); + error = db->queryWithPageSize(sql, sqlArgs, pageSize, result); if (error) { - this->error(call, ERROR_INTERNAL, *error); + sendError(call, ERROR_INTERNAL, error.message()); return; } - this->success(call, result); + sendSuccess(call, result); }); }); } void SqfliteAuroraPlugin::onQueryCursorNextCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - - const auto dbID = args[ARG_ID].GetInt(); - const auto cursorID = args[ARG_CURSOR_ID].GetInt(); - const auto closeCursor = args.HasKey(ARG_CANCEL) ? args[ARG_CANCEL].GetBoolean() : false; - const auto transactionID = GetTransactionID(args); + const auto dbID = call.GetArgument(ARG_ID); + const auto cursorID = call.GetArgument(ARG_CURSOR_ID); + const auto closeCursor = call.GetArgument(ARG_CANCEL, false); + const auto transactionID = getTransactionID(call.GetArguments()); const auto db = databaseByID(dbID); if (!db) { - this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); + sendError(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); return; } - this->asynq.Push([this, db, cursorID, closeCursor, transactionID, call] { - db->ProcessSqlCommand(transactionID, [this, db, cursorID, closeCursor, call] { + m_asyncQueue.push([this, db, cursorID, closeCursor, transactionID, call] { + db->processSqlCommand(transactionID, [this, db, cursorID, closeCursor, call] { Encodable::Map result; - const auto error = db->QueryCursorNext(cursorID, closeCursor, result); + const auto error = db->queryCursorNext(cursorID, closeCursor, result); if (error) { - this->error(call, ERROR_INTERNAL, *error); + sendError(call, ERROR_INTERNAL, error.message()); return; } - this->success(call, result); + sendSuccess(call, result); }); }); } void SqfliteAuroraPlugin::onUpdateCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - - const auto dbID = args[ARG_ID].GetInt(); - const auto sql = args[ARG_SQL].GetString(); - const auto sqlArgs = GetSqlArguments(args); - const auto transactionID = GetTransactionID(args); + const auto dbID = call.GetArgument(ARG_ID); + const auto sql = call.GetArgument(ARG_SQL); + const auto sqlArgs = getSqlArguments(call.GetArguments()); + const auto transactionID = getTransactionID(call.GetArguments()); const auto db = databaseByID(dbID); if (!db) { - this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); + sendError(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); return; } - this->asynq.Push([this, db, sql, sqlArgs, transactionID, call] { - db->ProcessSqlCommand(transactionID, [this, db, sql, sqlArgs, call] { + m_asyncQueue.push([this, db, sql, sqlArgs, transactionID, call] { + db->processSqlCommand(transactionID, [this, db, sql, sqlArgs, call] { int updated = 0; - const auto error = db->Update(sql, sqlArgs, updated); + const auto error = db->update(sql, sqlArgs, updated); if (error) { - this->error(call, ERROR_INTERNAL, *error); + sendError(call, ERROR_INTERNAL, error.message()); return; } - this->success(call, updated); + sendSuccess(call, updated); }); }); } void SqfliteAuroraPlugin::onInsertCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - - const auto dbID = args[ARG_ID].GetInt(); - const auto sql = args[ARG_SQL].GetString(); - const auto sqlArgs = GetSqlArguments(args); - const auto transactionID = GetTransactionID(args); + const auto dbID = call.GetArgument(ARG_ID); + const auto sql = call.GetArgument(ARG_SQL); + const auto sqlArgs = getSqlArguments(call.GetArguments()); + const auto transactionID = getTransactionID(call.GetArguments()); const auto db = databaseByID(dbID); if (!db) { - this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); + sendError(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); return; } - this->asynq.Push([this, db, sql, sqlArgs, transactionID, call] { - db->ProcessSqlCommand(transactionID, [this, db, sql, sqlArgs, call] { + m_asyncQueue.push([this, db, sql, sqlArgs, transactionID, call] { + db->processSqlCommand(transactionID, [this, db, sql, sqlArgs, call] { int insertID = 0; - const auto error = db->Insert(sql, sqlArgs, insertID); + const auto error = db->insert(sql, sqlArgs, insertID); if (error) { - this->error(call, ERROR_INTERNAL, *error); + sendError(call, ERROR_INTERNAL, error.message()); return; } if (insertID == 0) - this->success(call); + sendSuccess(call); else - this->success(call, insertID); + sendSuccess(call, insertID); }); }); } void SqfliteAuroraPlugin::onBatchCall(const MethodCall &call) { - const auto &args = call.GetArguments(); - - const auto dbID = args[ARG_ID].GetInt(); - const auto &operations = args[ARG_OPERATIONS].GetList(); - const auto noResult = args.HasKey(ARG_NO_RESULT) ? args[ARG_NO_RESULT].GetBoolean() : false; - const auto continueOnError = args.HasKey(ARG_CONTINUE_ON_ERROR) - ? args[ARG_CONTINUE_ON_ERROR].GetBoolean() - : false; - const auto transactionID = GetTransactionID(args); + const auto dbID = call.GetArgument(ARG_ID); + const auto &operations = call.GetArgument(ARG_OPERATIONS); + const auto noResult = call.GetArgument(ARG_NO_RESULT, false); + const auto continueOnError = call.GetArgument(ARG_CONTINUE_ON_ERROR, false); + const auto transactionID = getTransactionID(call.GetArguments()); const auto db = databaseByID(dbID); if (!db) { - this->error(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); + sendError(call, ERROR_CLOSED, "database closed", "ID=" + std::to_string(dbID) + ")"); return; } @@ -527,80 +503,80 @@ void SqfliteAuroraPlugin::onBatchCall(const MethodCall &call) for (const auto &operation : operations) { const auto method = operation[ARG_METHOD].GetString(); const auto sql = operation[ARG_SQL].GetString(); - const auto sqlArgs = GetSqlArguments(operation); + const auto sqlArgs = getSqlArguments(operation); dbOperations.emplace_back(Database::Operation{method, sql, sqlArgs}); } - this->asynq.Push([this, db, dbOperations, transactionID, continueOnError, noResult, call] { + m_asyncQueue.push([this, db, dbOperations, transactionID, continueOnError, noResult, call] { const auto command = [this, db, dbOperations, continueOnError, noResult, call] { Encodable::List results; - const auto error = db->Batch(dbOperations, continueOnError, results); + const auto error = db->batch(dbOperations, continueOnError, results); if (error) { - this->error(call, ERROR_INTERNAL, *error); + sendError(call, ERROR_INTERNAL, error.message()); return; } if (noResult) - this->success(call); + sendSuccess(call); else - this->success(call, results); + sendSuccess(call, results); }; - db->ProcessSqlCommand(transactionID, command); + db->processSqlCommand(transactionID, command); }); } std::shared_ptr SqfliteAuroraPlugin::databaseByPath(const std::string &path) { - std::lock_guard lock(this->mutex); + std::lock_guard lock(m_mutex); - if (!this->singletonDatabases.count(path)) + if (!m_singleInstanceDatabases.count(path)) return nullptr; - return this->singletonDatabases.at(path); + return m_singleInstanceDatabases.at(path); } std::shared_ptr SqfliteAuroraPlugin::databaseByID(int64_t id) { - std::lock_guard lock(this->mutex); + std::lock_guard lock(m_mutex); - if (!this->databases.count(id)) + if (!m_databases.count(id)) return nullptr; - return this->databases.at(id); + return m_databases.at(id); } void SqfliteAuroraPlugin::databaseRemove(std::shared_ptr db) { - std::lock_guard lock(this->mutex); + std::lock_guard lock(m_mutex); - if (db->IsSingleInstance()) - this->singletonDatabases.erase(db->Path()); + if (db->isSingleInstance()) + m_singleInstanceDatabases.erase(db->path()); - this->databases.erase(db->ID()); + m_databases.erase(db->id()); } void SqfliteAuroraPlugin::databaseAdd(std::shared_ptr db) { - std::lock_guard lock(this->mutex); + std::lock_guard lock(m_mutex); - if (db->IsSingleInstance()) - this->singletonDatabases.emplace(db->Path(), db); + if (db->isSingleInstance()) + m_singleInstanceDatabases.emplace(db->path(), db); - this->databases.emplace(db->ID(), db); + m_databases.emplace(db->id(), db); } -void SqfliteAuroraPlugin::success(const MethodCall &call, const Encodable &result) +void SqfliteAuroraPlugin::sendSuccess(const MethodCall &call, const Encodable &result) { call.SendSuccessResponse(result); } -void SqfliteAuroraPlugin::error(const MethodCall &call, - const std::string &error, - const std::string &message, - const std::string &desc, - const Encodable &details) +void SqfliteAuroraPlugin::sendError(const MethodCall &call, + const std::string &error, + const std::string &message, + const std::string &desc, + const Encodable &details) { call.SendErrorResponse(ERROR_SQFLITE, error + ": " + message + (desc.empty() ? "" : " (" + desc + ")"), diff --git a/packages/sqflite/sqflite_aurora/aurora/lib/utils.cpp b/packages/sqflite/sqflite_aurora/aurora/lib/utils.cpp new file mode 100644 index 0000000..d825ac4 --- /dev/null +++ b/packages/sqflite/sqflite_aurora/aurora/lib/utils.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023. Open Mobile Platform LLC. + * License: Proprietary. + */ +#include + +namespace utils { + +error::error(std::string message) + : m_message(std::move(message)) +{} + +utils::error error::none() +{ + return {}; +} + +error::operator bool() const +{ + return m_message.has_value(); +} + +const std::string &error::message() const +{ + return m_message.value(); +} + +} /* namespace utils */