1313#include " JSIHelper.h"
1414#include " ThreadPool.h"
1515#include " sqlfileloader.h"
16+ #include " sqlbatchexecutor.h"
1617#include < vector>
1718#include < string>
1819
@@ -185,7 +186,7 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker
185186
186187 // Converting results into a JSI Response
187188 auto jsiResult = createSequelQueryExecutionResult (rt, status, &results);
188- return jsiResult;
189+ return move ( jsiResult) ;
189190 });
190191
191192 // Execute a batch of SQL queries in a transaction
@@ -201,80 +202,84 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker
201202 return createError (rt, " [react-native-quick-sqlite][execSQLBatch] - Incorrect parameter count" );
202203 }
203204
205+ const jsi::Value ¶ms = args[1 ];
206+ if (params.isNull () || params.isUndefined ())
207+ {
208+ return createError (rt, " [react-native-quick-sqlite][execSQLBatch] - An array of SQL commands or parameters is needed" );
209+ }
204210 const string dbName = args[0 ].asString (rt).utf8 (rt);
211+ const jsi::Array &batchParams = params.asObject (rt).asArray (rt);
212+ vector<QuickQueryArguments> commands;
213+ jsiBatchParametersToQuickArguments (rt, batchParams, &commands);
214+
215+ auto batchResult = executeBatch (dbName, &commands);
216+ if (batchResult.type == SequelResultOk)
217+ {
218+ auto res = jsi::Object (rt);
219+ res.setProperty (rt, " status" , jsi::Value (0 ));
220+ res.setProperty (rt, " rowsAffected" , jsi::Value (batchResult.affectedRows ));
221+ return move (res);
222+ } else
223+ {
224+ return createError (rt, batchResult.message );
225+ }
226+ });
227+
228+ auto execSQLBatchAsync = jsi::Function::createFromHostFunction (
229+ rt,
230+ jsi::PropNameID::forAscii (rt, " sequel_execSQLBatchAsync" ),
231+ 3 ,
232+ [pool](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
233+ {
234+ if (sizeof (args) < 3 )
235+ {
236+ return createError (rt, " [react-native-quick-sqlite][execSQLBatch] - Incorrect parameter count" );
237+ }
238+
205239 const jsi::Value ¶ms = args[1 ];
206240 if (params.isNull () || params.isUndefined ())
207241 {
208242 return createError (rt, " [react-native-quick-sqlite][execSQLBatch] - An array of SQL commands or parameters is needed" );
209243 }
210244
211- int rowsAffected = 0 ;
245+
246+ const string dbName = args[0 ].asString (rt).utf8 (rt);
212247 const jsi::Array &batchParams = params.asObject (rt).asArray (rt);
213- try
248+ auto callback = make_shared<jsi::Value>((args[2 ].asObject (rt)));
249+
250+ vector<QuickQueryArguments> commands;
251+ jsiBatchParametersToQuickArguments (rt, batchParams, &commands);
252+
253+ auto task =
254+ [&rt, dbName, commands = make_shared<vector<QuickQueryArguments>>(commands), callback]()
214255 {
215- sequel_execute (rt, dbName, " BEGIN TRANSACTION" , jsi::Value::undefined ());
216- for (int i = 0 ; i < batchParams.length (rt); i++)
256+ try
217257 {
218- const jsi::Array &command = batchParams.getValueAtIndex (rt, i).asObject (rt).asArray (rt);
219- if (command.length (rt) == 0 )
220- {
221- sequel_execute (rt, dbName, " ROLLBACK" , jsi::Value::undefined ());
222- return createError (rt, " [react-native-quick-sqlite][execSQLBatch] - No SQL Commands found on batch index " + std::to_string (i));
223- }
224- const string query = command.getValueAtIndex (rt, 0 ).asString (rt).utf8 (rt);
225- const jsi::Value &commandParams = command.length (rt) > 1 ? command.getValueAtIndex (rt, 1 ) : jsi::Value::undefined ();
226- if (!commandParams.isUndefined () && commandParams.asObject (rt).isArray (rt) && commandParams.asObject (rt).asArray (rt).length (rt) > 0 && commandParams.asObject (rt).asArray (rt).getValueAtIndex (rt, 0 ).isObject ())
227- {
228- // This arguments are an array of arrays, like a batch update of a single sql command.
229- const jsi::Array &batchUpdateParams = commandParams.asObject (rt).asArray (rt);
230- for (int x = 0 ; x < batchUpdateParams.length (rt); x++)
231- {
232- const jsi::Value &p = batchUpdateParams.getValueAtIndex (rt, x);
233- SequelResult result = sequel_execute (rt, dbName, query, p);
234- if (result.type == SequelResultError)
235- {
236- sequel_execute (rt, dbName, " ROLLBACK" , jsi::Value::undefined ());
237- return createError (rt, result.message .c_str ());
238- }
239- else
240- {
241- if (result.value .getObject (rt).hasProperty (rt, jsi::PropNameID::forAscii (rt, " rowsAffected" )))
242- {
243- rowsAffected += result.value .getObject (rt).getProperty (rt, jsi::PropNameID::forAscii (rt, " rowsAffected" )).asNumber ();
244- }
245- }
246- }
247- }
248- else
258+ // Inside the new worker thread, we can now call sqlite operations
259+ auto batchResult = executeBatch (dbName, commands.get ());
260+ invoker->invokeAsync ([&rt, batchResult = move (batchResult), callback]
249261 {
250- SequelResult result = sequel_execute (rt, dbName, query, commandParams);
251- if (result.type == SequelResultError)
262+ if (batchResult.type == SequelResultOk)
252263 {
253- sequel_execute (rt, dbName, " ROLLBACK" , jsi::Value::undefined ());
254-
255- return createError (rt, result.message .c_str ());
256- }
257- else
264+ auto res = jsi::Object (rt);
265+ res.setProperty (rt, " status" , jsi::Value (0 ));
266+ res.setProperty (rt, " rowsAffected" , jsi::Value (batchResult.affectedRows ));
267+ callback->asObject (rt).asFunction (rt).call (rt, move (res));
268+ return move (res);
269+ } else
258270 {
259- if (result.value .getObject (rt).hasProperty (rt, jsi::PropNameID::forAscii (rt, " rowsAffected" )))
260- {
261- rowsAffected += result.value .getObject (rt).getProperty (rt, jsi::PropNameID::forAscii (rt, " rowsAffected" )).asNumber ();
262- }
271+ callback->asObject (rt).asFunction (rt).call (rt, createError (rt, batchResult.message ));
263272 }
264- }
273+ });
265274 }
266- sequel_execute (rt, dbName, " COMMIT" , jsi::Value::undefined ());
267- }
268- catch (...)
269- {
270- sequel_execute (rt, dbName, " ROLLBACK" , jsi::Value::undefined ());
271- return createError (rt, " [react-native-quick-sqlite][execSQLBatch] - Unexpected error" );
272- }
273-
274- auto res = jsi::Object (rt);
275- res.setProperty (rt, " status" , jsi::Value (0 ));
276- res.setProperty (rt, " rowsAffected" , jsi::Value (rowsAffected));
277- return move (res);
275+ catch (std::exception &exc)
276+ {
277+ invoker->invokeAsync ([&rt, callback, &exc]
278+ { callback->asObject (rt).asFunction (rt).call (rt, createError (rt, exc.what ())); });
279+ }
280+ };
281+ pool->queueWork (task);
282+ return {};
278283 });
279284
280285 // Load SQL File from disk
@@ -406,6 +411,7 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker
406411 module .setProperty (rt, " executeSql" , move (execSQL));
407412 module .setProperty (rt, " asyncExecuteSql" , move (asyncExecSQL));
408413 module .setProperty (rt, " executeSqlBatch" , move (execSQLBatch));
414+ module .setProperty (rt, " asyncExecuteSqlBatch" , move (execSQLBatchAsync));
409415 module .setProperty (rt, " loadSqlFile" , move (loadSQLFile));
410416 module .setProperty (rt, " asyncLoadSqlFile" , move (loadSQLFileAsync));
411417
0 commit comments