react-native-nitro-sqlite 9.8.1 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/RNNitroSQLite.podspec +7 -3
- package/android/CMakeLists.txt +3 -2
- package/android/build.gradle +2 -0
- package/android/sqlite-flags.gradle +47 -0
- package/cpp/NitroSQLiteDatabaseConnections.cpp +306 -0
- package/cpp/NitroSQLiteDatabaseConnections.hpp +86 -0
- package/cpp/{databaseMigration.cpp → NitroSQLiteDatabaseMigration.cpp} +2 -2
- package/cpp/{sqliteExecuteBatch.cpp → NitroSQLiteExecuteBatch.cpp} +4 -4
- package/cpp/{sqliteExecuteBatch.hpp → NitroSQLiteExecuteBatch.hpp} +3 -6
- package/cpp/{importSqlFile.cpp → NitroSQLiteImportSqlFile.cpp} +4 -4
- package/cpp/{importSqlFile.hpp → NitroSQLiteImportSqlFile.hpp} +3 -3
- package/cpp/{macros.hpp → NitroSQLiteMacros.hpp} +3 -3
- package/cpp/NitroSQLiteOperations.cpp +396 -0
- package/cpp/NitroSQLiteOperations.hpp +72 -0
- package/cpp/{types.hpp → NitroSQLiteTypes.hpp} +3 -6
- package/cpp/{utils.hpp → NitroSQLiteUtils.hpp} +2 -2
- package/cpp/hybridObjects/HybridNitroSQLite.cpp +108 -22
- package/cpp/hybridObjects/HybridNitroSQLite.hpp +49 -5
- package/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.cpp +59 -0
- package/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.hpp +33 -0
- package/cpp/hybridObjects/HybridNitroSQLiteQueryResult.hpp +6 -4
- package/ios/OnLoad.mm +38 -2
- package/lib/commonjs/DatabaseQueue.js +52 -16
- package/lib/commonjs/DatabaseQueue.js.map +1 -1
- package/lib/commonjs/NitroSQLiteError.js +6 -7
- package/lib/commonjs/NitroSQLiteError.js.map +1 -1
- package/lib/commonjs/OnLoad.js +1 -1
- package/lib/commonjs/index.js +8 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/operations/execute.js +19 -4
- package/lib/commonjs/operations/execute.js.map +1 -1
- package/lib/commonjs/operations/executeBatch.js +19 -6
- package/lib/commonjs/operations/executeBatch.js.map +1 -1
- package/lib/commonjs/operations/prepare.js +54 -0
- package/lib/commonjs/operations/prepare.js.map +1 -0
- package/lib/commonjs/operations/session.js +106 -30
- package/lib/commonjs/operations/session.js.map +1 -1
- package/lib/commonjs/operations/transaction.js +30 -5
- package/lib/commonjs/operations/transaction.js.map +1 -1
- package/lib/commonjs/specs/NitroSQLitePreparedStatement.nitro.js +6 -0
- package/lib/commonjs/specs/NitroSQLitePreparedStatement.nitro.js.map +1 -0
- package/lib/commonjs/typeORM.js +10 -3
- package/lib/commonjs/typeORM.js.map +1 -1
- package/lib/commonjs/types.js +35 -9
- package/lib/commonjs/types.js.map +1 -1
- package/lib/module/DatabaseQueue.js +52 -16
- package/lib/module/DatabaseQueue.js.map +1 -1
- package/lib/module/NitroSQLiteError.js +6 -7
- package/lib/module/NitroSQLiteError.js.map +1 -1
- package/lib/module/OnLoad.js +1 -1
- package/lib/module/index.js +8 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/operations/execute.js +20 -5
- package/lib/module/operations/execute.js.map +1 -1
- package/lib/module/operations/executeBatch.js +20 -7
- package/lib/module/operations/executeBatch.js.map +1 -1
- package/lib/module/operations/prepare.js +49 -0
- package/lib/module/operations/prepare.js.map +1 -0
- package/lib/module/operations/session.js +107 -31
- package/lib/module/operations/session.js.map +1 -1
- package/lib/module/operations/transaction.js +30 -5
- package/lib/module/operations/transaction.js.map +1 -1
- package/lib/module/specs/NitroSQLitePreparedStatement.nitro.js +4 -0
- package/lib/module/specs/NitroSQLitePreparedStatement.nitro.js.map +1 -0
- package/lib/module/typeORM.js +11 -3
- package/lib/module/typeORM.js.map +1 -1
- package/lib/module/types.js +48 -9
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/commonjs/DatabaseQueue.d.ts +15 -7
- package/lib/typescript/commonjs/DatabaseQueue.d.ts.map +1 -1
- package/lib/typescript/commonjs/NitroSQLiteError.d.ts +6 -7
- package/lib/typescript/commonjs/NitroSQLiteError.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +9 -2
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/operations/execute.d.ts +17 -2
- package/lib/typescript/commonjs/operations/execute.d.ts.map +1 -1
- package/lib/typescript/commonjs/operations/executeBatch.d.ts +15 -2
- package/lib/typescript/commonjs/operations/executeBatch.d.ts.map +1 -1
- package/lib/typescript/commonjs/operations/prepare.d.ts +13 -0
- package/lib/typescript/commonjs/operations/prepare.d.ts.map +1 -0
- package/lib/typescript/commonjs/operations/session.d.ts +8 -0
- package/lib/typescript/commonjs/operations/session.d.ts.map +1 -1
- package/lib/typescript/commonjs/operations/transaction.d.ts +11 -1
- package/lib/typescript/commonjs/operations/transaction.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NitroSQLite.nitro.d.ts +83 -2
- package/lib/typescript/commonjs/specs/NitroSQLite.nitro.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NitroSQLitePreparedStatement.nitro.d.ts +26 -0
- package/lib/typescript/commonjs/specs/NitroSQLitePreparedStatement.nitro.d.ts.map +1 -0
- package/lib/typescript/commonjs/specs/NitroSQLiteQueryResult.nitro.d.ts +9 -15
- package/lib/typescript/commonjs/specs/NitroSQLiteQueryResult.nitro.d.ts.map +1 -1
- package/lib/typescript/commonjs/typeORM.d.ts +14 -3
- package/lib/typescript/commonjs/typeORM.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts +124 -21
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/module/DatabaseQueue.d.ts +15 -7
- package/lib/typescript/module/DatabaseQueue.d.ts.map +1 -1
- package/lib/typescript/module/NitroSQLiteError.d.ts +6 -7
- package/lib/typescript/module/NitroSQLiteError.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +9 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/operations/execute.d.ts +17 -2
- package/lib/typescript/module/operations/execute.d.ts.map +1 -1
- package/lib/typescript/module/operations/executeBatch.d.ts +15 -2
- package/lib/typescript/module/operations/executeBatch.d.ts.map +1 -1
- package/lib/typescript/module/operations/prepare.d.ts +13 -0
- package/lib/typescript/module/operations/prepare.d.ts.map +1 -0
- package/lib/typescript/module/operations/session.d.ts +8 -0
- package/lib/typescript/module/operations/session.d.ts.map +1 -1
- package/lib/typescript/module/operations/transaction.d.ts +11 -1
- package/lib/typescript/module/operations/transaction.d.ts.map +1 -1
- package/lib/typescript/module/specs/NitroSQLite.nitro.d.ts +83 -2
- package/lib/typescript/module/specs/NitroSQLite.nitro.d.ts.map +1 -1
- package/lib/typescript/module/specs/NitroSQLitePreparedStatement.nitro.d.ts +26 -0
- package/lib/typescript/module/specs/NitroSQLitePreparedStatement.nitro.d.ts.map +1 -0
- package/lib/typescript/module/specs/NitroSQLiteQueryResult.nitro.d.ts +9 -15
- package/lib/typescript/module/specs/NitroSQLiteQueryResult.nitro.d.ts.map +1 -1
- package/lib/typescript/module/typeORM.d.ts +14 -3
- package/lib/typescript/module/typeORM.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts +124 -21
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake +1 -0
- package/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.hpp +73 -0
- package/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.cpp +3 -0
- package/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.hpp +8 -2
- package/package.json +4 -2
- package/src/DatabaseQueue.ts +81 -25
- package/src/NitroSQLiteError.ts +6 -7
- package/src/OnLoad.ts +1 -1
- package/src/index.ts +7 -3
- package/src/operations/execute.ts +22 -3
- package/src/operations/executeBatch.ts +20 -5
- package/src/operations/prepare.ts +69 -0
- package/src/operations/session.ts +136 -45
- package/src/operations/transaction.ts +37 -4
- package/src/specs/NitroSQLite.nitro.ts +84 -2
- package/src/specs/NitroSQLitePreparedStatement.nitro.ts +28 -0
- package/src/specs/NitroSQLiteQueryResult.nitro.ts +9 -15
- package/src/typeORM.ts +14 -3
- package/src/types.ts +135 -21
- package/cpp/operations.cpp +0 -358
- package/cpp/operations.hpp +0 -56
- /package/android/{cpp-adapter.cpp → RNNitroSQLiteAdapter.cpp} +0 -0
- /package/cpp/{databaseMigration.hpp → NitroSQLiteDatabaseMigration.hpp} +0 -0
- /package/cpp/{logs.hpp → NitroSQLiteLogs.hpp} +0 -0
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
#include "HybridNitroSQLite.hpp"
|
|
2
|
+
#include "../NitroSQLiteDatabaseMigration.hpp"
|
|
3
|
+
#include "../NitroSQLiteException.hpp"
|
|
4
|
+
#include "../NitroSQLiteExecuteBatch.hpp"
|
|
5
|
+
#include "../NitroSQLiteImportSqlFile.hpp"
|
|
6
|
+
#include "../NitroSQLiteLogs.hpp"
|
|
7
|
+
#include "../NitroSQLiteMacros.hpp"
|
|
8
|
+
#include "../NitroSQLiteOperations.hpp"
|
|
9
|
+
#include "HybridNitroSQLitePreparedStatement.hpp"
|
|
2
10
|
#include "HybridNitroSQLiteQueryResult.hpp"
|
|
3
|
-
#include "NitroSQLiteException.hpp"
|
|
4
|
-
#include "databaseMigration.hpp"
|
|
5
|
-
#include "importSqlFile.hpp"
|
|
6
|
-
#include "logs.hpp"
|
|
7
|
-
#include "macros.hpp"
|
|
8
|
-
#include "operations.hpp"
|
|
9
|
-
#include "sqliteExecuteBatch.hpp"
|
|
10
11
|
#include <exception>
|
|
11
12
|
#include <filesystem>
|
|
12
13
|
#include <iostream>
|
|
13
14
|
#include <map>
|
|
14
15
|
#include <optional>
|
|
15
16
|
#include <string>
|
|
17
|
+
#include <utility>
|
|
16
18
|
#include <variant>
|
|
17
19
|
#include <vector>
|
|
18
20
|
|
|
19
21
|
namespace margelo::nitro::rnnitrosqlite {
|
|
20
22
|
|
|
21
23
|
// Copy any JS-backed ArrayBuffers on the JS thread so they can be safely
|
|
22
|
-
// accessed from the background
|
|
24
|
+
// accessed from the connection's background worker.
|
|
23
25
|
static std::optional<SQLiteQueryParams> copyArrayBufferParamsForBackground(const std::optional<SQLiteQueryParams>& params) {
|
|
24
26
|
if (!params) {
|
|
25
27
|
return std::nullopt;
|
|
@@ -59,7 +61,40 @@ static std::vector<BatchQuery> copyArrayBufferParamsForBackground(const std::vec
|
|
|
59
61
|
return copiedCommands;
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
template <typename Result, typename Operation>
|
|
65
|
+
static std::shared_ptr<Promise<Result>> enqueueConnectionOperation(const SQLiteConnectionPtr& connection, Operation&& operation) {
|
|
66
|
+
auto promise = Promise<Result>::create();
|
|
67
|
+
try {
|
|
68
|
+
connection->enqueueAsync([promise, operation = std::forward<Operation>(operation)]() mutable {
|
|
69
|
+
std::optional<Result> result;
|
|
70
|
+
try {
|
|
71
|
+
result.emplace(operation());
|
|
72
|
+
} catch (...) {
|
|
73
|
+
promise->reject(std::current_exception());
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// Resolving may dispatch to JavaScript and throw after the native promise
|
|
77
|
+
// has settled. Do not try to reject that same promise again.
|
|
78
|
+
try {
|
|
79
|
+
promise->resolve(std::move(*result));
|
|
80
|
+
} catch (...) {
|
|
81
|
+
if (promise->isPending()) {
|
|
82
|
+
promise->reject(std::current_exception());
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
throw;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
} catch (...) {
|
|
89
|
+
promise->reject(std::current_exception());
|
|
90
|
+
}
|
|
91
|
+
return promise;
|
|
92
|
+
}
|
|
93
|
+
|
|
62
94
|
const std::string getDocPath(const std::optional<std::string>& location) {
|
|
95
|
+
if (location && location->find('\0') != std::string::npos) {
|
|
96
|
+
throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened, "Database location contains a NUL byte");
|
|
97
|
+
}
|
|
63
98
|
std::string tempDocPath = std::string(HybridNitroSQLite::docPath);
|
|
64
99
|
if (location) {
|
|
65
100
|
tempDocPath = tempDocPath + "/" + *location;
|
|
@@ -77,45 +112,92 @@ const std::string getOldDocPath(const std::optional<std::string>& location) {
|
|
|
77
112
|
return oldDocPath;
|
|
78
113
|
}
|
|
79
114
|
|
|
80
|
-
const std::string getMigratedDocPath(const std::string& dbName, const std::optional<std::string>& location) {
|
|
115
|
+
const std::string getMigratedDocPath(const std::string& dbName, const std::optional<std::string>& location, bool readOnly = false) {
|
|
81
116
|
const auto currentDocPath = getDocPath(location);
|
|
82
117
|
if (HybridNitroSQLite::migrationDocPath.empty()) {
|
|
83
118
|
return currentDocPath;
|
|
84
119
|
}
|
|
120
|
+
const auto oldDocPath = getOldDocPath(location);
|
|
121
|
+
std::string selectedPath;
|
|
122
|
+
databaseConnections().withConnectionsLocked([&]() {
|
|
123
|
+
const auto oldPath = std::filesystem::path(oldDocPath) / dbName;
|
|
124
|
+
const auto livePath = databaseConnections().findLivePath(oldPath, std::filesystem::path(currentDocPath) / dbName);
|
|
125
|
+
if (livePath) {
|
|
126
|
+
selectedPath = *livePath == oldPath ? oldDocPath : currentDocPath;
|
|
127
|
+
} else if (readOnly) {
|
|
128
|
+
selectedPath = std::filesystem::exists(std::filesystem::path(oldDocPath) / dbName) ? oldDocPath : currentDocPath;
|
|
129
|
+
} else {
|
|
130
|
+
selectedPath = migrateDatabase(dbName, oldDocPath, currentDocPath).string();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
return selectedPath;
|
|
134
|
+
}
|
|
85
135
|
|
|
86
|
-
|
|
136
|
+
void HybridNitroSQLite::open(const std::string& dbName, const std::optional<std::string>& location, std::optional<bool> readOnly) {
|
|
137
|
+
validateDatabaseName(dbName);
|
|
138
|
+
std::lock_guard lock(databaseConnections().lifecycleMutex);
|
|
139
|
+
if (databaseConnections().isOpen(dbName)) {
|
|
140
|
+
throw NitroSQLiteException::DatabaseAlreadyOpen(dbName);
|
|
141
|
+
}
|
|
142
|
+
const auto docPath = getMigratedDocPath(dbName, location, readOnly.value_or(false));
|
|
143
|
+
sqliteOpenDb(dbName, docPath, readOnly.value_or(false));
|
|
87
144
|
}
|
|
88
145
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
146
|
+
std::string HybridNitroSQLite::openConnection(const std::string& dbName, const std::optional<std::string>& location,
|
|
147
|
+
std::optional<bool> readOnly) {
|
|
148
|
+
validateDatabaseName(dbName);
|
|
149
|
+
if (sqlite3_threadsafe() == 0) {
|
|
150
|
+
throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened,
|
|
151
|
+
"Independent connections require a thread-safe SQLite build");
|
|
152
|
+
}
|
|
153
|
+
std::lock_guard lock(databaseConnections().lifecycleMutex);
|
|
154
|
+
const auto docPath = getMigratedDocPath(dbName, location, readOnly.value_or(false));
|
|
155
|
+
return sqliteOpenConnection(dbName, docPath, readOnly.value_or(false));
|
|
92
156
|
}
|
|
93
157
|
|
|
94
158
|
void HybridNitroSQLite::close(const std::string& dbName) {
|
|
95
159
|
sqliteCloseDb(dbName);
|
|
96
160
|
};
|
|
97
161
|
|
|
98
|
-
|
|
162
|
+
bool HybridNitroSQLite::isConnectionOpen(const std::string& connectionId) {
|
|
163
|
+
return databaseConnections().isOpen(connectionId);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
void HybridNitroSQLite::drop(const std::string& dbName, const std::optional<std::string>& location,
|
|
167
|
+
const std::optional<std::string>& connectionId) {
|
|
168
|
+
validateDatabaseName(dbName);
|
|
169
|
+
std::lock_guard lock(databaseConnections().lifecycleMutex);
|
|
99
170
|
const auto currentDocPath = getDocPath(location);
|
|
100
171
|
if (migrationDocPath.empty()) {
|
|
101
|
-
sqliteRemoveDb(dbName, currentDocPath);
|
|
172
|
+
sqliteRemoveDb(dbName, currentDocPath, connectionId);
|
|
102
173
|
return;
|
|
103
174
|
}
|
|
104
175
|
|
|
105
176
|
const auto oldDocPath = getOldDocPath(location);
|
|
177
|
+
const auto preferredPath = databaseConnections().physicalPathForKey(connectionId.value_or(dbName));
|
|
178
|
+
const auto currentPath = std::filesystem::path(currentDocPath) / dbName;
|
|
106
179
|
std::error_code ec;
|
|
107
180
|
const bool oldDatabaseExists = std::filesystem::exists(std::filesystem::path(oldDocPath) / dbName, ec);
|
|
108
181
|
if (ec) {
|
|
109
182
|
LOGW("Failed to inspect database %s in its old location: %s", dbName.c_str(), ec.message().c_str());
|
|
110
183
|
}
|
|
111
184
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
185
|
+
// A stale copy in the old directory must not override the actual target of a live or
|
|
186
|
+
// recently closed independent connection.
|
|
187
|
+
std::error_code equivalentError;
|
|
188
|
+
const bool prefersCurrent = preferredPath && (std::filesystem::equivalent(*preferredPath, currentPath, equivalentError) ||
|
|
189
|
+
canonicalDatabasePath(*preferredPath) == canonicalDatabasePath(currentPath));
|
|
190
|
+
const bool useOldPath = !prefersCurrent && (preferredPath || oldDatabaseExists || ec);
|
|
191
|
+
sqliteRemoveDb(dbName, useOldPath ? oldDocPath : currentDocPath, connectionId, useOldPath ? currentDocPath : oldDocPath);
|
|
115
192
|
};
|
|
116
193
|
|
|
117
194
|
void HybridNitroSQLite::attach(const std::string& mainDbName, const std::string& dbNameToAttach, const std::string& alias,
|
|
118
195
|
const std::optional<std::string>& location) {
|
|
196
|
+
validateDatabaseName(dbNameToAttach);
|
|
197
|
+
std::lock_guard lock(databaseConnections().lifecycleMutex);
|
|
198
|
+
if (databaseConnections().get(mainDbName)->readOnly) {
|
|
199
|
+
throw NitroSQLiteException(NitroSQLiteExceptionType::UnableToAttachToDatabase, "Cannot attach a database to a read-only connection");
|
|
200
|
+
}
|
|
119
201
|
const auto attachedDocPath = getMigratedDocPath(dbNameToAttach, location);
|
|
120
202
|
sqliteAttachDb(mainDbName, attachedDocPath, dbNameToAttach, alias);
|
|
121
203
|
};
|
|
@@ -139,13 +221,17 @@ HybridNitroSQLite::executeAsync(const std::string& dbName, const std::string& qu
|
|
|
139
221
|
return Promise<std::shared_ptr<HybridNitroSQLiteQueryResultSpec>>::rejected(std::current_exception());
|
|
140
222
|
}
|
|
141
223
|
|
|
142
|
-
return
|
|
143
|
-
[connection, query, copiedParams]() -> std::shared_ptr<HybridNitroSQLiteQueryResultSpec> {
|
|
224
|
+
return enqueueConnectionOperation<std::shared_ptr<HybridNitroSQLiteQueryResultSpec>>(
|
|
225
|
+
connection, [connection, query, copiedParams]() -> std::shared_ptr<HybridNitroSQLiteQueryResultSpec> {
|
|
144
226
|
auto result = sqliteExecute(connection, query, copiedParams);
|
|
145
227
|
return result;
|
|
146
228
|
});
|
|
147
229
|
};
|
|
148
230
|
|
|
231
|
+
std::shared_ptr<HybridNitroSQLitePreparedStatementSpec> HybridNitroSQLite::prepare(const std::string& dbName, const std::string& query) {
|
|
232
|
+
return std::make_shared<HybridNitroSQLitePreparedStatement>(sqlitePrepare(dbName, query));
|
|
233
|
+
}
|
|
234
|
+
|
|
149
235
|
BatchQueryResult HybridNitroSQLite::executeBatch(const std::string& dbName, const std::vector<BatchQueryCommand>& batchParams) {
|
|
150
236
|
const auto commands = batchParamsToCommands(batchParams);
|
|
151
237
|
|
|
@@ -166,7 +252,7 @@ std::shared_ptr<Promise<BatchQueryResult>> HybridNitroSQLite::executeBatchAsync(
|
|
|
166
252
|
return Promise<BatchQueryResult>::rejected(std::current_exception());
|
|
167
253
|
}
|
|
168
254
|
|
|
169
|
-
return
|
|
255
|
+
return enqueueConnectionOperation<BatchQueryResult>(connection, [connection, copiedCommands]() -> BatchQueryResult {
|
|
170
256
|
auto result = sqliteExecuteBatch(connection, copiedCommands);
|
|
171
257
|
return BatchQueryResult(result.rowsAffected);
|
|
172
258
|
});
|
|
@@ -184,7 +270,7 @@ std::shared_ptr<Promise<FileLoadResult>> HybridNitroSQLite::loadFileAsync(const
|
|
|
184
270
|
} catch (...) {
|
|
185
271
|
return Promise<FileLoadResult>::rejected(std::current_exception());
|
|
186
272
|
}
|
|
187
|
-
return
|
|
273
|
+
return enqueueConnectionOperation<FileLoadResult>(connection, [connection, location]() -> FileLoadResult {
|
|
188
274
|
const auto result = importSqlFile(connection, location);
|
|
189
275
|
return FileLoadResult(result.commands, result.rowsAffected);
|
|
190
276
|
});
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include "../NitroSQLiteTypes.hpp"
|
|
4
|
+
#include "HybridNitroSQLitePreparedStatementSpec.hpp"
|
|
3
5
|
#include "HybridNitroSQLiteQueryResultSpec.hpp"
|
|
4
6
|
#include "HybridNitroSQLiteSpec.hpp"
|
|
5
|
-
#include "types.hpp"
|
|
6
|
-
|
|
7
|
-
using namespace margelo::rnnitrosqlite;
|
|
8
7
|
|
|
9
8
|
namespace margelo::nitro::rnnitrosqlite {
|
|
10
9
|
|
|
10
|
+
/** Native database operations exposed to JavaScript through the Nitro hybrid object. */
|
|
11
11
|
class HybridNitroSQLite : public HybridNitroSQLiteSpec {
|
|
12
12
|
public:
|
|
13
13
|
HybridNitroSQLite() : HybridObject(TAG) {}
|
|
@@ -21,28 +21,72 @@ public:
|
|
|
21
21
|
|
|
22
22
|
public:
|
|
23
23
|
// Methods
|
|
24
|
-
|
|
24
|
+
/** Open the default connection, requiring an existing file in read-only mode. */
|
|
25
|
+
void open(const std::string& dbName, const std::optional<std::string>& location, std::optional<bool> readOnly) override;
|
|
26
|
+
|
|
27
|
+
/** Open a separate native handle and return an opaque ID for later calls. */
|
|
28
|
+
std::string openConnection(const std::string& dbName, const std::optional<std::string>& location, std::optional<bool> readOnly) override;
|
|
25
29
|
|
|
30
|
+
/** Close the named native database handle. */
|
|
26
31
|
void close(const std::string& dbName) override;
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
/** Check whether a connection name or ID still identifies an open handle. */
|
|
34
|
+
bool isConnectionOpen(const std::string& connectionId) override;
|
|
29
35
|
|
|
36
|
+
/** Delete a database, closing the specified connection when it is open. */
|
|
37
|
+
void drop(const std::string& dbName, const std::optional<std::string>& location, const std::optional<std::string>& connectionId) override;
|
|
38
|
+
|
|
39
|
+
/** Attach a database file to an open database.
|
|
40
|
+
* @param mainDbName Name of the open main database.
|
|
41
|
+
* @param dbNameToAttach File name of the database to attach.
|
|
42
|
+
* @param alias SQL schema name for the attached database.
|
|
43
|
+
* @param location Optional directory relative to the platform database root.
|
|
44
|
+
*/
|
|
30
45
|
void attach(const std::string& mainDbName, const std::string& dbNameToAttach, const std::string& alias,
|
|
31
46
|
const std::optional<std::string>& location) override;
|
|
32
47
|
|
|
48
|
+
/** Detach the database identified by @p alias from @p mainDbName. */
|
|
33
49
|
void detach(const std::string& mainDbName, const std::string& alias) override;
|
|
34
50
|
|
|
51
|
+
/** Execute one SQL statement on the calling thread.
|
|
52
|
+
* @param dbName Name of an open database.
|
|
53
|
+
* @param query SQL statement with optional positional placeholders.
|
|
54
|
+
* @param params Optional values bound to the placeholders.
|
|
55
|
+
* @return Native rows, affected row count, insert ID, and metadata.
|
|
56
|
+
*/
|
|
35
57
|
std::shared_ptr<HybridNitroSQLiteQueryResultSpec> execute(const std::string& dbName, const std::string& query,
|
|
36
58
|
const std::optional<SQLiteQueryParams>& params) override;
|
|
37
59
|
|
|
60
|
+
/** Execute one SQL statement on a background thread.
|
|
61
|
+
* @return A promise of the native query result.
|
|
62
|
+
*/
|
|
38
63
|
std::shared_ptr<Promise<std::shared_ptr<HybridNitroSQLiteQueryResultSpec>>>
|
|
39
64
|
executeAsync(const std::string& dbName, const std::string& query, const std::optional<SQLiteQueryParams>& params) override;
|
|
40
65
|
|
|
66
|
+
/** Prepare one SQL statement for repeated execution on an open connection. */
|
|
67
|
+
std::shared_ptr<HybridNitroSQLitePreparedStatementSpec> prepare(const std::string& dbName, const std::string& query) override;
|
|
68
|
+
|
|
69
|
+
/** Run a nonempty batch in one exclusive transaction on the calling thread.
|
|
70
|
+
* A failed command rolls back the batch.
|
|
71
|
+
* @return Total affected row count.
|
|
72
|
+
*/
|
|
41
73
|
BatchQueryResult executeBatch(const std::string& dbName, const std::vector<BatchQueryCommand>& commands) override;
|
|
74
|
+
/** Run a nonempty batch in one exclusive transaction on a background thread.
|
|
75
|
+
* @return A promise of the total affected row count.
|
|
76
|
+
*/
|
|
42
77
|
std::shared_ptr<Promise<BatchQueryResult>> executeBatchAsync(const std::string& dbName,
|
|
43
78
|
const std::vector<BatchQueryCommand>& commands) override;
|
|
44
79
|
|
|
80
|
+
/** Import a SQL file in one exclusive transaction on the calling thread.
|
|
81
|
+
* Each nonempty line is interpreted as one statement.
|
|
82
|
+
* @param location Path to the SQL file.
|
|
83
|
+
* @return Number of executed commands and affected rows.
|
|
84
|
+
*/
|
|
45
85
|
FileLoadResult loadFile(const std::string& dbName, const std::string& location) override;
|
|
86
|
+
/** Import a SQL file on a background thread.
|
|
87
|
+
* @param location Path to the SQL file.
|
|
88
|
+
* @return A promise of the command and affected row counts.
|
|
89
|
+
*/
|
|
46
90
|
std::shared_ptr<Promise<FileLoadResult>> loadFileAsync(const std::string& dbName, const std::string& location) override;
|
|
47
91
|
};
|
|
48
92
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#include "HybridNitroSQLitePreparedStatement.hpp"
|
|
2
|
+
#include "HybridNitroSQLiteQueryResult.hpp"
|
|
3
|
+
#include <NitroModules/ArrayBuffer.hpp>
|
|
4
|
+
|
|
5
|
+
namespace margelo::nitro::rnnitrosqlite {
|
|
6
|
+
|
|
7
|
+
namespace {
|
|
8
|
+
|
|
9
|
+
std::optional<SQLiteQueryParams> copyArrayBufferParamsForBackground(const std::optional<SQLiteQueryParams>& params) {
|
|
10
|
+
if (!params) {
|
|
11
|
+
return std::nullopt;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
SQLiteQueryParams copiedParams;
|
|
15
|
+
copiedParams.reserve(params->size());
|
|
16
|
+
|
|
17
|
+
for (const auto& value : *params) {
|
|
18
|
+
if (std::holds_alternative<std::shared_ptr<ArrayBuffer>>(value)) {
|
|
19
|
+
copiedParams.push_back(ArrayBuffer::copy(std::get<std::shared_ptr<ArrayBuffer>>(value)));
|
|
20
|
+
} else {
|
|
21
|
+
copiedParams.push_back(value);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return copiedParams;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
} // namespace
|
|
29
|
+
|
|
30
|
+
HybridNitroSQLitePreparedStatement::HybridNitroSQLitePreparedStatement(std::shared_ptr<SQLitePreparedStatement> statement)
|
|
31
|
+
: HybridObject(TAG), _statement(std::move(statement)) {}
|
|
32
|
+
|
|
33
|
+
std::shared_ptr<HybridNitroSQLiteQueryResultSpec>
|
|
34
|
+
HybridNitroSQLitePreparedStatement::execute(const std::optional<SQLiteQueryParams>& params) {
|
|
35
|
+
return _statement->execute(params);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
std::shared_ptr<Promise<std::shared_ptr<HybridNitroSQLiteQueryResultSpec>>>
|
|
39
|
+
HybridNitroSQLitePreparedStatement::executeAsync(const std::optional<SQLiteQueryParams>& params) {
|
|
40
|
+
const auto copiedParams = copyArrayBufferParamsForBackground(params);
|
|
41
|
+
const auto statement = _statement;
|
|
42
|
+
|
|
43
|
+
return Promise<std::shared_ptr<HybridNitroSQLiteQueryResultSpec>>::async(
|
|
44
|
+
[statement, copiedParams]() -> std::shared_ptr<HybridNitroSQLiteQueryResultSpec> { return statement->execute(copiedParams); });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void HybridNitroSQLitePreparedStatement::finalize() {
|
|
48
|
+
_statement->finalize();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
bool HybridNitroSQLitePreparedStatement::getIsFinalized() {
|
|
52
|
+
return _statement->isFinalized();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
size_t HybridNitroSQLitePreparedStatement::getExternalMemorySize() noexcept {
|
|
56
|
+
return sizeof(*this) + _statement->getExternalMemorySize();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
} // namespace margelo::nitro::rnnitrosqlite
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "../NitroSQLiteOperations.hpp"
|
|
4
|
+
#include "../NitroSQLiteTypes.hpp"
|
|
5
|
+
#include "HybridNitroSQLitePreparedStatementSpec.hpp"
|
|
6
|
+
#include <memory>
|
|
7
|
+
|
|
8
|
+
namespace margelo::nitro::rnnitrosqlite {
|
|
9
|
+
|
|
10
|
+
/** Nitro hybrid object for a reusable native SQLite statement. */
|
|
11
|
+
class HybridNitroSQLitePreparedStatement : public HybridNitroSQLitePreparedStatementSpec {
|
|
12
|
+
public:
|
|
13
|
+
/** Wrap a prepared statement for calls from JavaScript. */
|
|
14
|
+
explicit HybridNitroSQLitePreparedStatement(std::shared_ptr<SQLitePreparedStatement> statement);
|
|
15
|
+
|
|
16
|
+
/** Execute with new bindings on the calling thread. */
|
|
17
|
+
std::shared_ptr<HybridNitroSQLiteQueryResultSpec> execute(const std::optional<SQLiteQueryParams>& params) override;
|
|
18
|
+
/** Execute with new bindings on a background thread. */
|
|
19
|
+
std::shared_ptr<Promise<std::shared_ptr<HybridNitroSQLiteQueryResultSpec>>>
|
|
20
|
+
executeAsync(const std::optional<SQLiteQueryParams>& params) override;
|
|
21
|
+
/** Release the native statement. */
|
|
22
|
+
void finalize() override;
|
|
23
|
+
/** Check whether the native statement has been released. */
|
|
24
|
+
bool getIsFinalized() override;
|
|
25
|
+
|
|
26
|
+
/** Report native memory used by this hybrid object. */
|
|
27
|
+
size_t getExternalMemorySize() noexcept override;
|
|
28
|
+
|
|
29
|
+
private:
|
|
30
|
+
std::shared_ptr<SQLitePreparedStatement> _statement;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
} // namespace margelo::nitro::rnnitrosqlite
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include "../NitroSQLiteTypes.hpp"
|
|
3
4
|
#include "HybridNitroSQLiteQueryResultSpec.hpp"
|
|
4
|
-
#include "types.hpp"
|
|
5
5
|
#include <map>
|
|
6
6
|
|
|
7
|
-
using namespace margelo::rnnitrosqlite;
|
|
8
|
-
|
|
9
7
|
namespace margelo::nitro::rnnitrosqlite {
|
|
10
8
|
|
|
9
|
+
/** Native result object returned by a single SQL execution. */
|
|
11
10
|
class HybridNitroSQLiteQueryResult : public HybridNitroSQLiteQueryResultSpec {
|
|
12
11
|
public:
|
|
13
12
|
HybridNitroSQLiteQueryResult() : HybridObject(TAG) {}
|
|
@@ -22,10 +21,13 @@ private:
|
|
|
22
21
|
std::optional<SQLiteQueryTableMetadata> _metadata;
|
|
23
22
|
|
|
24
23
|
public:
|
|
25
|
-
|
|
24
|
+
/** Return the connection's last insert row ID, which may be from an earlier statement. */
|
|
26
25
|
std::optional<double> getInsertId() override;
|
|
26
|
+
/** Return SQLite's latest row change count, which may be stale for a read-only query. */
|
|
27
27
|
double getRowsAffected() override;
|
|
28
|
+
/** Return result rows keyed by column name. */
|
|
28
29
|
SQLiteQueryResults getResults() override;
|
|
30
|
+
/** Return column metadata when available. */
|
|
29
31
|
std::optional<SQLiteQueryTableMetadata> getMetadata() override;
|
|
30
32
|
|
|
31
33
|
/**
|
package/ios/OnLoad.mm
CHANGED
|
@@ -1,7 +1,39 @@
|
|
|
1
1
|
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <TargetConditionals.h>
|
|
2
3
|
#import "RNNitroSQLite-Swift-Cxx-Umbrella.hpp"
|
|
3
4
|
#import "HybridNitroSQLite.hpp"
|
|
4
5
|
|
|
6
|
+
#if TARGET_OS_OSX
|
|
7
|
+
static NSString *macOSDatabaseDirectory(void) {
|
|
8
|
+
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
9
|
+
NSError *error = nil;
|
|
10
|
+
NSURL *applicationSupportURL = [fileManager URLForDirectory:NSApplicationSupportDirectory
|
|
11
|
+
inDomain:NSUserDomainMask
|
|
12
|
+
appropriateForURL:nil
|
|
13
|
+
create:YES
|
|
14
|
+
error:&error];
|
|
15
|
+
if (applicationSupportURL == nil) {
|
|
16
|
+
@throw [NSException exceptionWithName:@"SQLiteInitializationException"
|
|
17
|
+
reason:[NSString stringWithFormat:@"Could not find the Application Support directory: %@", error]
|
|
18
|
+
userInfo:nil];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
|
|
22
|
+
if (bundleIdentifier == nil) {
|
|
23
|
+
bundleIdentifier = [[NSProcessInfo processInfo] processName];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
NSURL *databaseURL = [applicationSupportURL URLByAppendingPathComponent:bundleIdentifier isDirectory:YES];
|
|
27
|
+
if (![fileManager createDirectoryAtURL:databaseURL withIntermediateDirectories:YES attributes:nil error:&error]) {
|
|
28
|
+
@throw [NSException exceptionWithName:@"SQLiteInitializationException"
|
|
29
|
+
reason:[NSString stringWithFormat:@"Could not create the database directory: %@", error]
|
|
30
|
+
userInfo:nil];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return [databaseURL path];
|
|
34
|
+
}
|
|
35
|
+
#endif
|
|
36
|
+
|
|
5
37
|
@interface OnLoad : NSObject
|
|
6
38
|
@end
|
|
7
39
|
|
|
@@ -11,7 +43,7 @@ using namespace margelo::nitro;
|
|
|
11
43
|
using namespace margelo::nitro::rnnitrosqlite;
|
|
12
44
|
|
|
13
45
|
+ (void)load {
|
|
14
|
-
// Get appGroupID value from Info.plist using key "
|
|
46
|
+
// Get appGroupID value from Info.plist using key "RNNitroSQLite_AppGroup".
|
|
15
47
|
NSString *appGroupID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_AppGroup"];
|
|
16
48
|
NSString *documentPath;
|
|
17
49
|
|
|
@@ -21,7 +53,7 @@ using namespace margelo::nitro::rnnitrosqlite;
|
|
|
21
53
|
NSURL *storeUrl = [fileManager containerURLForSecurityApplicationGroupIdentifier:appGroupID];
|
|
22
54
|
|
|
23
55
|
if (storeUrl == nil) {
|
|
24
|
-
NSLog(@"Invalid
|
|
56
|
+
NSLog(@"Invalid App Group ID provided (%@). Check the value of \"RNNitroSQLite_AppGroup\" in your Info.plist file", appGroupID);
|
|
25
57
|
@throw [NSException exceptionWithName:@"SQLiteInitializationException"
|
|
26
58
|
reason:@"Error while initializing SQLite database (AppGroup)"
|
|
27
59
|
userInfo:nil];
|
|
@@ -30,6 +62,9 @@ using namespace margelo::nitro::rnnitrosqlite;
|
|
|
30
62
|
|
|
31
63
|
documentPath = [storeUrl path];
|
|
32
64
|
} else {
|
|
65
|
+
#if TARGET_OS_OSX
|
|
66
|
+
documentPath = macOSDatabaseDirectory();
|
|
67
|
+
#else
|
|
33
68
|
NSString *databaseLocation = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_DatabaseLocation"];
|
|
34
69
|
|
|
35
70
|
if ([databaseLocation isEqualToString:@"ApplicationSupport"]) {
|
|
@@ -56,6 +91,7 @@ using namespace margelo::nitro::rnnitrosqlite;
|
|
|
56
91
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true);
|
|
57
92
|
documentPath = [paths objectAtIndex:0];
|
|
58
93
|
}
|
|
94
|
+
#endif
|
|
59
95
|
}
|
|
60
96
|
|
|
61
97
|
HybridNitroSQLite::docPath = [documentPath UTF8String];
|
|
@@ -8,24 +8,31 @@ exports.getDatabaseQueue = getDatabaseQueue;
|
|
|
8
8
|
exports.isDatabaseOpen = isDatabaseOpen;
|
|
9
9
|
exports.openDatabaseQueue = openDatabaseQueue;
|
|
10
10
|
exports.queueOperationAsync = queueOperationAsync;
|
|
11
|
+
exports.queueStatementAsync = queueStatementAsync;
|
|
11
12
|
exports.startOperationSync = startOperationSync;
|
|
12
13
|
exports.throwIfDatabaseIsNotOpen = throwIfDatabaseIsNotOpen;
|
|
13
14
|
var _NitroSQLiteError = _interopRequireDefault(require("./NitroSQLiteError.js"));
|
|
14
15
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
|
+
/** Identity of a managed connection's operation queue. Application code should
|
|
17
|
+
* omit the optional queue key on package helpers; connections choose it for you.
|
|
18
|
+
*/
|
|
19
|
+
|
|
15
20
|
const databaseQueues = new Map();
|
|
16
21
|
function openDatabaseQueue(dbName) {
|
|
17
22
|
if (isDatabaseOpen(dbName)) {
|
|
18
|
-
throw new _NitroSQLiteError.default(`Database ${dbName} is already open. There is already a connection to the database.`);
|
|
23
|
+
throw new _NitroSQLiteError.default(`Database ${String(dbName)} is already open. There is already a connection to the database.`);
|
|
19
24
|
}
|
|
20
25
|
databaseQueues.set(dbName, {
|
|
21
26
|
queue: [],
|
|
22
|
-
inProgress: false
|
|
27
|
+
inProgress: false,
|
|
28
|
+
activeStatements: 0,
|
|
29
|
+
draining: false
|
|
23
30
|
});
|
|
24
31
|
}
|
|
25
32
|
function closeDatabaseQueue(dbName) {
|
|
26
33
|
const databaseQueue = getDatabaseQueue(dbName);
|
|
27
34
|
if (databaseQueue.inProgress || databaseQueue.queue.length > 0) {
|
|
28
|
-
throw new _NitroSQLiteError.default(`Cannot close database ${dbName}. The database is busy with another operation.`);
|
|
35
|
+
throw new _NitroSQLiteError.default(`Cannot close database ${String(dbName)}. The database is busy with another operation.`);
|
|
29
36
|
}
|
|
30
37
|
databaseQueues.delete(dbName);
|
|
31
38
|
}
|
|
@@ -33,7 +40,7 @@ function isDatabaseOpen(dbName) {
|
|
|
33
40
|
return databaseQueues.has(dbName);
|
|
34
41
|
}
|
|
35
42
|
function throwIfDatabaseIsNotOpen(dbName) {
|
|
36
|
-
if (!isDatabaseOpen(dbName)) throw new _NitroSQLiteError.default(`Database ${dbName} is not open. There is no connection to the database.`);
|
|
43
|
+
if (!isDatabaseOpen(dbName)) throw new _NitroSQLiteError.default(`Database ${String(dbName)} is not open. There is no connection to the database.`);
|
|
37
44
|
}
|
|
38
45
|
function getDatabaseQueue(dbName) {
|
|
39
46
|
throwIfDatabaseIsNotOpen(dbName);
|
|
@@ -41,6 +48,12 @@ function getDatabaseQueue(dbName) {
|
|
|
41
48
|
return queue;
|
|
42
49
|
}
|
|
43
50
|
function queueOperationAsync(dbName, callback) {
|
|
51
|
+
return enqueueOperation(dbName, 'exclusive', callback);
|
|
52
|
+
}
|
|
53
|
+
function queueStatementAsync(dbName, callback) {
|
|
54
|
+
return enqueueOperation(dbName, 'statement', callback);
|
|
55
|
+
}
|
|
56
|
+
function enqueueOperation(dbName, kind, callback) {
|
|
44
57
|
const databaseQueue = getDatabaseQueue(dbName);
|
|
45
58
|
return new Promise((resolve, reject) => {
|
|
46
59
|
async function start() {
|
|
@@ -50,34 +63,56 @@ function queueOperationAsync(dbName, callback) {
|
|
|
50
63
|
} catch (error) {
|
|
51
64
|
reject(error);
|
|
52
65
|
} finally {
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
if (kind === 'statement') {
|
|
67
|
+
databaseQueue.activeStatements--;
|
|
68
|
+
if (databaseQueue.activeStatements === 0) {
|
|
69
|
+
databaseQueue.inProgress = false;
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
databaseQueue.inProgress = false;
|
|
73
|
+
}
|
|
74
|
+
startNextOperations(databaseQueue);
|
|
55
75
|
}
|
|
56
76
|
}
|
|
57
77
|
const operation = {
|
|
78
|
+
kind,
|
|
58
79
|
start
|
|
59
80
|
};
|
|
60
81
|
databaseQueue.queue.push(operation);
|
|
61
|
-
|
|
82
|
+
startNextOperations(databaseQueue);
|
|
62
83
|
});
|
|
63
84
|
}
|
|
64
|
-
function
|
|
65
|
-
|
|
66
|
-
if (queue.inProgress || queue.queue.length === 0) {
|
|
85
|
+
function startNextOperations(queue) {
|
|
86
|
+
if (queue.draining || queue.inProgress && queue.activeStatements === 0) {
|
|
67
87
|
return;
|
|
68
88
|
}
|
|
69
|
-
queue.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
89
|
+
queue.draining = true;
|
|
90
|
+
try {
|
|
91
|
+
while (queue.queue.length > 0) {
|
|
92
|
+
const exclusiveIndex = queue.queue.findIndex(operation => operation.kind === 'exclusive');
|
|
93
|
+
const statementCount = exclusiveIndex === -1 ? queue.queue.length : exclusiveIndex;
|
|
94
|
+
if (statementCount > 0) {
|
|
95
|
+
const statements = queue.queue.splice(0, statementCount);
|
|
96
|
+
queue.inProgress = true;
|
|
97
|
+
queue.activeStatements += statements.length;
|
|
98
|
+
for (const statement of statements) statement.start();
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (queue.activeStatements > 0) return;
|
|
102
|
+
queue.inProgress = true;
|
|
103
|
+
queue.queue.shift().start();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
} finally {
|
|
107
|
+
queue.draining = false;
|
|
108
|
+
}
|
|
74
109
|
}
|
|
75
110
|
function startOperationSync(dbName, callback) {
|
|
76
111
|
const databaseQueue = getDatabaseQueue(dbName);
|
|
77
112
|
|
|
78
113
|
// Database is busy - cannot execute synchronously
|
|
79
114
|
if (databaseQueue.inProgress || databaseQueue.queue.length > 0) {
|
|
80
|
-
throw new _NitroSQLiteError.default(`Cannot run synchronous operation on database. Database ${dbName} is busy with another operation.`);
|
|
115
|
+
throw new _NitroSQLiteError.default(`Cannot run synchronous operation on database. Database ${String(dbName)} is busy with another operation.`);
|
|
81
116
|
}
|
|
82
117
|
|
|
83
118
|
// Execute synchronously
|
|
@@ -86,6 +121,7 @@ function startOperationSync(dbName, callback) {
|
|
|
86
121
|
return callback();
|
|
87
122
|
} finally {
|
|
88
123
|
databaseQueue.inProgress = false;
|
|
124
|
+
startNextOperations(databaseQueue);
|
|
89
125
|
}
|
|
90
126
|
}
|
|
91
127
|
//# sourceMappingURL=DatabaseQueue.js.map
|