From 58ebc85bee32c1a1b632fbb43e72e4d015d7f537 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 5 Feb 2026 12:26:19 +0100 Subject: [PATCH 1/5] fix: c++ hybrid objects not constructed properly --- package/cpp/operations.cpp | 9 +++-- package/cpp/operations.hpp | 3 +- package/cpp/specs/HybridNitroSQLite.cpp | 8 ++--- .../specs/HybridNitroSQLiteQueryResult.cpp | 28 +++------------ .../specs/HybridNitroSQLiteQueryResult.hpp | 34 +++++++++++++++++-- package/cpp/sqliteExecuteBatch.cpp | 2 +- package/cpp/types.hpp | 11 +----- 7 files changed, 48 insertions(+), 47 deletions(-) diff --git a/package/cpp/operations.cpp b/package/cpp/operations.cpp index bc339ca3..62453524 100644 --- a/package/cpp/operations.cpp +++ b/package/cpp/operations.cpp @@ -11,6 +11,7 @@ #include #include #include +#include "specs/HybridNitroSQLiteQueryResult.hpp" using namespace facebook; using namespace margelo::nitro; @@ -121,7 +122,7 @@ void bindStatement(sqlite3_stmt* statement, const SQLiteQueryParams& values) { } } -SQLiteExecuteQueryResult sqliteExecute(const std::string& dbName, const std::string& query, +std::shared_ptr sqliteExecute(const std::string& dbName, const std::string& query, const std::optional& params) { if (dbMap.count(dbName) == 0) { throw NitroSQLiteException::DatabaseNotOpen(dbName); @@ -229,10 +230,7 @@ SQLiteExecuteQueryResult sqliteExecute(const std::string& dbName, const std::str int rowsAffected = sqlite3_changes(db); long long latestInsertRowId = sqlite3_last_insert_rowid(db); - return {.rowsAffected = rowsAffected, - .insertId = static_cast(latestInsertRowId), - .results = std::move(results), - .metadata = std::move(metadata)}; + return std::make_shared(results, static_cast(latestInsertRowId), rowsAffected, metadata); } SQLiteOperationResult sqliteExecuteLiteral(const std::string& dbName, const std::string& query) { @@ -288,3 +286,4 @@ SQLiteOperationResult sqliteExecuteLiteral(const std::string& dbName, const std: } } // namespace margelo::rnnitrosqlite + diff --git a/package/cpp/operations.hpp b/package/cpp/operations.hpp index dd086932..a50ce4cf 100644 --- a/package/cpp/operations.hpp +++ b/package/cpp/operations.hpp @@ -1,6 +1,7 @@ #pragma once #include "types.hpp" +#include "specs/HybridNitroSQLiteQueryResult.hpp" namespace margelo::rnnitrosqlite { @@ -15,7 +16,7 @@ void sqliteAttachDb(const std::string& mainDBName, const std::string& docPath, c void sqliteDetachDb(const std::string& mainDBName, const std::string& alias); -SQLiteExecuteQueryResult sqliteExecute(const std::string& dbName, const std::string& query, const std::optional& params); +std::shared_ptr sqliteExecute(const std::string& dbName, const std::string& query, const std::optional& params); SQLiteOperationResult sqliteExecuteLiteral(const std::string& dbName, const std::string& query); diff --git a/package/cpp/specs/HybridNitroSQLite.cpp b/package/cpp/specs/HybridNitroSQLite.cpp index b54b3f0b..b59a3c30 100644 --- a/package/cpp/specs/HybridNitroSQLite.cpp +++ b/package/cpp/specs/HybridNitroSQLite.cpp @@ -10,6 +10,7 @@ #include #include #include +#include "HybridNitroSQLiteQueryResult.hpp" namespace margelo::nitro::rnnitrosqlite { @@ -50,12 +51,9 @@ void HybridNitroSQLite::detach(const std::string& mainDbName, const std::string& sqliteDetachDb(mainDbName, alias); }; -using ExecuteQueryResult = std::shared_ptr; - -ExecuteQueryResult HybridNitroSQLite::execute(const std::string& dbName, const std::string& query, +std::shared_ptr HybridNitroSQLite::execute(const std::string& dbName, const std::string& query, const std::optional& params) { - SQLiteExecuteQueryResult result = sqliteExecute(dbName, query, params); - return std::make_shared(std::move(result)); + return sqliteExecute(dbName, query, params); }; std::shared_ptr>> diff --git a/package/cpp/specs/HybridNitroSQLiteQueryResult.cpp b/package/cpp/specs/HybridNitroSQLiteQueryResult.cpp index 5ccf734a..762ca9b1 100644 --- a/package/cpp/specs/HybridNitroSQLiteQueryResult.cpp +++ b/package/cpp/specs/HybridNitroSQLiteQueryResult.cpp @@ -9,41 +9,23 @@ namespace margelo::nitro::rnnitrosqlite { std::optional HybridNitroSQLiteQueryResult::getInsertId() { - return _result.insertId; + return _insertId; } double HybridNitroSQLiteQueryResult::getRowsAffected() { - return _result.rowsAffected; + return _rowsAffected; } SQLiteQueryResults HybridNitroSQLiteQueryResult::getResults() { - return _result.results; + return _results; }; std::optional HybridNitroSQLiteQueryResult::getRows() { - if (_result.results.empty()) { - return std::nullopt; - } - - auto rows = _result.results; - - // Create the item function that returns a Promise - auto itemFunction = [rows](double idx) -> std::shared_ptr>> { - return Promise>::async([rows, idx]() -> std::optional { - const auto index = static_cast(idx); - if (index >= rows.size()) { - return std::nullopt; - } - return rows[index]; - }); - }; - - const auto length = static_cast(rows.size()); - return NitroSQLiteQueryResultRows(std::move(rows), length, itemFunction); + return _rows; } std::optional HybridNitroSQLiteQueryResult::getMetadata() { - return _result.metadata; + return _metadata; } } // namespace margelo::nitro::rnnitrosqlite diff --git a/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp b/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp index bad545d4..2ab2f33b 100644 --- a/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp +++ b/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp @@ -11,10 +11,40 @@ namespace margelo::nitro::rnnitrosqlite { class HybridNitroSQLiteQueryResult : public HybridNitroSQLiteQueryResultSpec { public: HybridNitroSQLiteQueryResult() : HybridObject(TAG) {} - HybridNitroSQLiteQueryResult(SQLiteExecuteQueryResult&& result) : HybridObject(TAG), _result(std::move(result)) {} + HybridNitroSQLiteQueryResult(SQLiteQueryResults results, std::optional insertId, double rowsAffected, std::optional metadata) { + HybridNitroSQLiteQueryResult(); + + _results = results; + _insertId = insertId; + _metadata = metadata; + + if (!_results.empty()) { + auto rows = _results; + + // Create the item function that returns a Promise + auto itemFunction = [rows](double idx) -> std::shared_ptr>> { + return Promise>::async([rows, idx]() -> std::optional { + const auto index = static_cast(idx); + if (index >= rows.size()) { + return std::nullopt; + } + return rows[index]; + }); + }; + + const auto length = static_cast(rows.size()); + _rows = NitroSQLiteQueryResultRows(std::move(rows), length, itemFunction); + } + + + } private: - SQLiteExecuteQueryResult _result; + std::optional _insertId; + double _rowsAffected; + SQLiteQueryResults _results; + std::optional _rows; + std::optional_metadata; public: // Properties diff --git a/package/cpp/sqliteExecuteBatch.cpp b/package/cpp/sqliteExecuteBatch.cpp index 7e06770f..4aca8b5f 100644 --- a/package/cpp/sqliteExecuteBatch.cpp +++ b/package/cpp/sqliteExecuteBatch.cpp @@ -49,7 +49,7 @@ SQLiteOperationResult sqliteExecuteBatch(const std::string& dbName, const std::v auto metadata = std::optional(std::nullopt); try { auto result = sqliteExecute(dbName, command.sql, command.params); - rowsAffected += result.rowsAffected; + rowsAffected += result->getRowsAffected(); } catch (NitroSQLiteException& e) { sqliteExecuteLiteral(dbName, "ROLLBACK"); throw e; diff --git a/package/cpp/types.hpp b/package/cpp/types.hpp index 48d1e5f6..eefa83a0 100644 --- a/package/cpp/types.hpp +++ b/package/cpp/types.hpp @@ -18,16 +18,7 @@ using SQLiteQueryTableMetadata = std::unordered_map metadata; + int commands = 0; }; // constexpr function that maps SQLiteColumnType to string literals From 843db89dde74467eb2ca73e14edf780a85b18e28 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 5 Feb 2026 12:26:54 +0100 Subject: [PATCH 2/5] fix: remove `buildJsQueryResult` and simplify types --- package/src/operations/execute.ts | 22 ++-------------------- package/src/types.ts | 12 +----------- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/package/src/operations/execute.ts b/package/src/operations/execute.ts index c0ef34b1..071bdd33 100644 --- a/package/src/operations/execute.ts +++ b/package/src/operations/execute.ts @@ -1,5 +1,4 @@ import { HybridNitroSQLite } from '../nitro' -import type { NitroSQLiteQueryResult } from '../specs/NitroSQLiteQueryResult.nitro' import type { QueryResult, QueryResultRow, SQLiteQueryParams } from '../types' import NitroSQLiteError from '../NitroSQLiteError' @@ -10,7 +9,7 @@ export function execute( ): QueryResult { try { const result = HybridNitroSQLite.execute(dbName, query, params) - return buildJsQueryResult(result) + return result as QueryResult } catch (error) { throw NitroSQLiteError.fromError(error) } @@ -23,25 +22,8 @@ export async function executeAsync( ): Promise> { try { const result = await HybridNitroSQLite.executeAsync(dbName, query, params) - return buildJsQueryResult(result) + return result as QueryResult } catch (error) { throw NitroSQLiteError.fromError(error) } } - -function buildJsQueryResult( - result: NitroSQLiteQueryResult, -): QueryResult { - const data = result.results as Row[] - - return { - ...result, - insertId: result.insertId, - rowsAffected: result.rowsAffected, - rows: { - _array: data, - length: data.length, - item: (idx: number) => data[idx], - }, - } as QueryResult -} diff --git a/package/src/types.ts b/package/src/types.ts index 09e652eb..3ceba314 100644 --- a/package/src/types.ts +++ b/package/src/types.ts @@ -1,5 +1,4 @@ import type { - NitroSQLiteQueryColumnMetadata, NitroSQLiteQueryResult, NitroSQLiteQueryResultRows, } from './specs/NitroSQLiteQueryResult.nitro' @@ -42,17 +41,8 @@ export type QueryResultRow = Record export type QueryResult = NitroSQLiteQueryResult & { - readonly rowsAffected: number - readonly insertId?: number - - /** Query results */ - readonly results: Row[] - /** Query results in a row format for TypeORM compatibility */ - readonly rows?: NitroSQLiteQueryResultRows - - /** Table metadata */ - readonly metadata?: Record + rows?: NitroSQLiteQueryResultRows } export type ExecuteQuery = ( From 89e753b31c786d37c7cd80f76b4fb2f921cc99b8 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 5 Feb 2026 12:27:06 +0100 Subject: [PATCH 3/5] chore: update Claude permissions --- .claude/settings.local.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..633cb5bb --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,8 @@ +{ + "permissions": { + "allow": [ + "Bash(find:*)", + "Bash(grep:*)" + ] + } +} From 8ce124a5f0ca170eb2b8c668d3806650d1441f76 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 5 Feb 2026 12:56:23 +0100 Subject: [PATCH 4/5] fix: properly construct `HybridNitroSQLiteQueryResult` --- .../specs/HybridNitroSQLiteQueryResult.hpp | 56 +++++++++++-------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp b/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp index 2ab2f33b..1122dd18 100644 --- a/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp +++ b/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp @@ -11,32 +11,40 @@ namespace margelo::nitro::rnnitrosqlite { class HybridNitroSQLiteQueryResult : public HybridNitroSQLiteQueryResultSpec { public: HybridNitroSQLiteQueryResult() : HybridObject(TAG) {} - HybridNitroSQLiteQueryResult(SQLiteQueryResults results, std::optional insertId, double rowsAffected, std::optional metadata) { - HybridNitroSQLiteQueryResult(); - - _results = results; - _insertId = insertId; - _metadata = metadata; - - if (!_results.empty()) { - auto rows = _results; - - // Create the item function that returns a Promise - auto itemFunction = [rows](double idx) -> std::shared_ptr>> { - return Promise>::async([rows, idx]() -> std::optional { - const auto index = static_cast(idx); - if (index >= rows.size()) { - return std::nullopt; - } - return rows[index]; - }); + HybridNitroSQLiteQueryResult(SQLiteQueryResults results, + std::optional insertId, + double rowsAffected, + std::optional metadata) + : HybridObject(TAG), + _insertId(insertId), + _rowsAffected(rowsAffected), + _results(std::move(results)), + _metadata(metadata) { + if (_results.empty()) { + // Empty rows: empty vector, length 0, item callback always returns null + auto emptyItem = [](double /* idx */) -> std::shared_ptr>> { + return Promise>::async( + []() -> std::optional { return std::nullopt; }); }; - - const auto length = static_cast(rows.size()); - _rows = NitroSQLiteQueryResultRows(std::move(rows), length, itemFunction); + _rows = NitroSQLiteQueryResultRows(SQLiteQueryResults{}, 0.0, std::move(emptyItem)); + return; } - - + + auto rows = _results; + auto itemFunction = + [rows](double idx) -> std::shared_ptr>> { + return Promise>::async( + [rows, idx]() -> std::optional { + const auto index = static_cast(idx); + if (index >= rows.size()) { + return std::nullopt; + } + return rows[index]; + }); + }; + + const auto length = static_cast(rows.size()); + _rows = NitroSQLiteQueryResultRows(std::move(rows), length, std::move(itemFunction)); } private: From 078f30d7931aacc3d3860ae02fb9f0d055c2e2bb Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 5 Feb 2026 12:58:54 +0100 Subject: [PATCH 5/5] chore: lint cpp --- package/cpp/NitroSQLiteException.hpp | 3 +- package/cpp/operations.cpp | 5 ++- package/cpp/operations.hpp | 5 +-- package/cpp/specs/HybridNitroSQLite.cpp | 3 +- .../specs/HybridNitroSQLiteQueryResult.hpp | 35 +++++++------------ 5 files changed, 20 insertions(+), 31 deletions(-) diff --git a/package/cpp/NitroSQLiteException.hpp b/package/cpp/NitroSQLiteException.hpp index 4a8469bd..e63f5d70 100644 --- a/package/cpp/NitroSQLiteException.hpp +++ b/package/cpp/NitroSQLiteException.hpp @@ -2,12 +2,11 @@ #include #include -#include #include +#include const std::string NITRO_SQLITE_EXCEPTION_PREFIX = "[NativeNitroSQLiteException]"; - enum NitroSQLiteExceptionType { UnknownError, DatabaseCannotBeOpened, diff --git a/package/cpp/operations.cpp b/package/cpp/operations.cpp index 62453524..af361dd5 100644 --- a/package/cpp/operations.cpp +++ b/package/cpp/operations.cpp @@ -1,6 +1,7 @@ #include "operations.hpp" #include "NitroSQLiteException.hpp" #include "logs.hpp" +#include "specs/HybridNitroSQLiteQueryResult.hpp" #include "utils.hpp" #include #include @@ -11,7 +12,6 @@ #include #include #include -#include "specs/HybridNitroSQLiteQueryResult.hpp" using namespace facebook; using namespace margelo::nitro; @@ -123,7 +123,7 @@ void bindStatement(sqlite3_stmt* statement, const SQLiteQueryParams& values) { } std::shared_ptr sqliteExecute(const std::string& dbName, const std::string& query, - const std::optional& params) { + const std::optional& params) { if (dbMap.count(dbName) == 0) { throw NitroSQLiteException::DatabaseNotOpen(dbName); } @@ -286,4 +286,3 @@ SQLiteOperationResult sqliteExecuteLiteral(const std::string& dbName, const std: } } // namespace margelo::rnnitrosqlite - diff --git a/package/cpp/operations.hpp b/package/cpp/operations.hpp index a50ce4cf..36addeaf 100644 --- a/package/cpp/operations.hpp +++ b/package/cpp/operations.hpp @@ -1,7 +1,7 @@ #pragma once -#include "types.hpp" #include "specs/HybridNitroSQLiteQueryResult.hpp" +#include "types.hpp" namespace margelo::rnnitrosqlite { @@ -16,7 +16,8 @@ void sqliteAttachDb(const std::string& mainDBName, const std::string& docPath, c void sqliteDetachDb(const std::string& mainDBName, const std::string& alias); -std::shared_ptr sqliteExecute(const std::string& dbName, const std::string& query, const std::optional& params); +std::shared_ptr sqliteExecute(const std::string& dbName, const std::string& query, + const std::optional& params); SQLiteOperationResult sqliteExecuteLiteral(const std::string& dbName, const std::string& query); diff --git a/package/cpp/specs/HybridNitroSQLite.cpp b/package/cpp/specs/HybridNitroSQLite.cpp index b59a3c30..ceb0e554 100644 --- a/package/cpp/specs/HybridNitroSQLite.cpp +++ b/package/cpp/specs/HybridNitroSQLite.cpp @@ -10,7 +10,6 @@ #include #include #include -#include "HybridNitroSQLiteQueryResult.hpp" namespace margelo::nitro::rnnitrosqlite { @@ -52,7 +51,7 @@ void HybridNitroSQLite::detach(const std::string& mainDbName, const std::string& }; std::shared_ptr HybridNitroSQLite::execute(const std::string& dbName, const std::string& query, - const std::optional& params) { + const std::optional& params) { return sqliteExecute(dbName, query, params); }; diff --git a/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp b/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp index 1122dd18..a06a99dd 100644 --- a/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp +++ b/package/cpp/specs/HybridNitroSQLiteQueryResult.hpp @@ -11,37 +11,28 @@ namespace margelo::nitro::rnnitrosqlite { class HybridNitroSQLiteQueryResult : public HybridNitroSQLiteQueryResultSpec { public: HybridNitroSQLiteQueryResult() : HybridObject(TAG) {} - HybridNitroSQLiteQueryResult(SQLiteQueryResults results, - std::optional insertId, - double rowsAffected, + HybridNitroSQLiteQueryResult(SQLiteQueryResults results, std::optional insertId, double rowsAffected, std::optional metadata) - : HybridObject(TAG), - _insertId(insertId), - _rowsAffected(rowsAffected), - _results(std::move(results)), - _metadata(metadata) { + : HybridObject(TAG), _insertId(insertId), _rowsAffected(rowsAffected), _results(std::move(results)), _metadata(metadata) { if (_results.empty()) { // Empty rows: empty vector, length 0, item callback always returns null auto emptyItem = [](double /* idx */) -> std::shared_ptr>> { - return Promise>::async( - []() -> std::optional { return std::nullopt; }); + return Promise>::async([]() -> std::optional { return std::nullopt; }); }; _rows = NitroSQLiteQueryResultRows(SQLiteQueryResults{}, 0.0, std::move(emptyItem)); return; } auto rows = _results; - auto itemFunction = - [rows](double idx) -> std::shared_ptr>> { - return Promise>::async( - [rows, idx]() -> std::optional { - const auto index = static_cast(idx); - if (index >= rows.size()) { - return std::nullopt; - } - return rows[index]; - }); - }; + auto itemFunction = [rows](double idx) -> std::shared_ptr>> { + return Promise>::async([rows, idx]() -> std::optional { + const auto index = static_cast(idx); + if (index >= rows.size()) { + return std::nullopt; + } + return rows[index]; + }); + }; const auto length = static_cast(rows.size()); _rows = NitroSQLiteQueryResultRows(std::move(rows), length, std::move(itemFunction)); @@ -52,7 +43,7 @@ class HybridNitroSQLiteQueryResult : public HybridNitroSQLiteQueryResultSpec { double _rowsAffected; SQLiteQueryResults _results; std::optional _rows; - std::optional_metadata; + std::optional _metadata; public: // Properties