Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make quick-sqlite 2x quicker? #30

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions cpp/JSIHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,45 @@ jsi::Value createSequelQueryExecutionResult(jsi::Runtime &rt, SQLiteOPResult sta

return move(res);
}

jsi::Value createSequelQueryExecutionResult2(jsi::Runtime &rt, SQLiteOPResult status, jsi::Array &results, vector<QuickColumnMetadata> *metadata)
{
if(status.type == SQLiteError) {
throw std::invalid_argument(status.errorMessage);
}

jsi::Object res = jsi::Object(rt);

res.setProperty(rt, "rowsAffected", jsi::Value(status.rowsAffected));
if (status.rowsAffected > 0 && status.insertId != 0)
{
res.setProperty(rt, "insertId", jsi::Value(status.insertId));
}

// Converting row results into objects
size_t rowCount = results.size(rt);
jsi::Object rows = jsi::Object(rt);
if (rowCount > 0)
{
rows.setProperty(rt, "_array", move(results));
res.setProperty(rt, "rows", move(rows));
}

if(metadata != NULL)
{
size_t column_count = metadata->size();
auto column_array = jsi::Array(rt, column_count);
for (int i = 0; i < column_count; i++) {
auto column = metadata->at(i);
jsi::Object column_object = jsi::Object(rt);
column_object.setProperty(rt, "columnName", jsi::String::createFromUtf8(rt, column.colunmName.c_str()));
column_object.setProperty(rt, "columnDeclaredType", jsi::String::createFromUtf8(rt, column.columnDeclaredType.c_str()));
column_object.setProperty(rt, "columnIndex", jsi::Value(column.columnIndex));
column_array.setValueAtIndex(rt, i, move(column_object));
}
res.setProperty(rt, "metadata", move(column_array));
}
rows.setProperty(rt, "length", jsi::Value((int)rowCount));

return move(res);
}
1 change: 1 addition & 0 deletions cpp/JSIHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,6 @@ QuickValue createInt64QuickValue(long long value);
QuickValue createDoubleQuickValue(double value);
QuickValue createArrayBufferQuickValue(uint8_t *arrayBufferValue, size_t arrayBufferSize);
jsi::Value createSequelQueryExecutionResult(jsi::Runtime &rt, SQLiteOPResult status, vector<map<string, QuickValue>> *results, vector<QuickColumnMetadata> *metadata);
jsi::Value createSequelQueryExecutionResult2(jsi::Runtime &rt, SQLiteOPResult status, jsi::Array &results, vector<QuickColumnMetadata> *metadata);

#endif /* JSIHelper_h */
114 changes: 114 additions & 0 deletions cpp/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,51 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker
}
});


auto execute2 = HOSTFN("execute2", 4)
{
const string dbName = args[0].asString(rt).utf8(rt);
const string query = args[1].asString(rt).utf8(rt);
vector<QuickValue> params;
bool returnArrays = false;
if(count > 2) {
const jsi::Value &originalParams = args[2];
jsiQueryArgumentsToSequelParam(rt, originalParams, &params);
}

if (count == 4) {
returnArrays = args[3].asBool();
}

vector<jsi::Object> results;
vector<QuickColumnMetadata> metadata;

// Converting results into a JSI Response
try {
auto status = sqliteExecute2(rt, dbName, query, &params, returnArrays, &results, &metadata);

if(status.type == SQLiteError) {
// throw std::runtime_error(status.errorMessage);
throw jsi::JSError(rt, status.errorMessage);
// return {};
}

jsi::Array ar = jsi::Array(rt, results.size());

int i = 0;
for (auto const& result : results) {
ar.setValueAtIndex(rt, i, move(result));
i++;
}

auto jsiResult = createSequelQueryExecutionResult2(rt, status, ar, &metadata);

return jsiResult;
} catch(std::exception &e) {
throw jsi::JSError(rt, e.what());
}
});

auto executeAsync = HOSTFN("executeAsync", 3)
{
if (count < 3)
Expand Down Expand Up @@ -263,6 +308,73 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker
return promise;
});


auto executeAsync2 = HOSTFN("executeAsync2", 4)
{
if (count < 4)
{
throw jsi::JSError(rt, "[react-native-quick-sqlite][executeAsync2] Incorrect arguments for executeAsync2");
}

const string dbName = args[0].asString(rt).utf8(rt);
const string query = args[1].asString(rt).utf8(rt);
const jsi::Value &originalParams = args[2];
const bool returnArrays = args[3].asBool();

// Converting query parameters inside the javascript caller thread
vector<QuickValue> params;
jsiQueryArgumentsToSequelParam(rt, originalParams, &params);

auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
auto reject = std::make_shared<jsi::Value>(rt, args[1]);

auto task =
[&rt, dbName, query, params = make_shared<vector<QuickValue>>(params), returnArrays, resolve, reject]()
{
try
{
invoker->invokeAsync([&rt, dbName, query, params, returnArrays, resolve, reject]
{
vector<jsi::Object> results;
vector<QuickColumnMetadata> metadata;
auto status = sqliteExecute2(rt, dbName, query, params.get(), returnArrays, &results, &metadata);
if(status.type == SQLiteOk) {
jsi::Array ar = jsi::Array(rt, results.size());

int i = 0;
for (auto const& result : results) {
ar.setValueAtIndex(rt, i, move(result));
i++;
}

auto jsiResult = createSequelQueryExecutionResult2(rt, status, ar, &metadata);
resolve->asObject(rt).asFunction(rt).call(rt, move(jsiResult));
} else {
auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
auto error = errorCtr.callAsConstructor(rt, jsi::String::createFromUtf8(rt, status.errorMessage));
reject->asObject(rt).asFunction(rt).call(rt, error);
}
});

}
catch (std::exception &exc)
{
invoker->invokeAsync([&rt, &exc] {
jsi::JSError(rt, exc.what());
});
}
};

pool->queueWork(task);

return {};
}));

return promise;
});

// Execute a batch of SQL queries in a transaction
// Parameters can be: [[sql: string, arguments: any[] | arguments: any[][] ]]
auto executeBatch = HOSTFN("executeBatch", 2)
Expand Down Expand Up @@ -438,7 +550,9 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker
module.setProperty(rt, "detach", move(detach));
module.setProperty(rt, "delete", move(remove));
module.setProperty(rt, "execute", move(execute));
module.setProperty(rt, "execute2", move(execute2));
module.setProperty(rt, "executeAsync", move(executeAsync));
module.setProperty(rt, "executeAsync2", move(executeAsync2));
module.setProperty(rt, "executeBatch", move(executeBatch));
module.setProperty(rt, "executeBatchAsync", move(executeBatchAsync));
module.setProperty(rt, "loadFile", move(loadFile));
Expand Down
13 changes: 7 additions & 6 deletions cpp/sqlbatchexecutor.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
/**
* SQL Batch execution implementation using default sqliteBridge implementation
*/
*/
#include "JSIHelper.h"
#include "sqliteBridge.h"

using namespace std;
using namespace facebook;

struct QuickQueryArguments {
struct QuickQueryArguments
{
string sql;
shared_ptr<vector<QuickValue>> params;
};

/**
* Local Helper method to translate JSI objects QuickQueryArguments datastructure
* Local Helper method to translate JSI objects QuickQueryArguments datastructure
* MUST be called in the JavaScript Thread
*/
*/
void jsiBatchParametersToQuickArguments(jsi::Runtime &rt, jsi::Array const &batchParams, vector<QuickQueryArguments> *commands);

/**
* Execute a batch of commands in a exclusive transaction
*/
* Execute a batch of commands in a exclusive transaction
*/
SequelBatchOperationResult sqliteExecuteBatch(std::string dbName, vector<QuickQueryArguments> *commands);
Loading