Skip to content
Merged
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
4 changes: 4 additions & 0 deletions android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ add_library(
../cpp/react-native-quick-sqlite.h
../cpp/sqlite3.h
../cpp/sqlite3.c
../cpp/JSIHelper.h
../cpp/JSIHelper.cpp
../cpp/ThreadPool.h
../cpp/ThreadPool.cpp
cpp-adapter.cpp
)

Expand Down
211 changes: 164 additions & 47 deletions cpp/JSIHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,70 +10,187 @@
using namespace std;
using namespace facebook;

vector<any> jsiArrayToVector(jsi::Runtime &rt, jsi::Array values)
SequelValue createNullSequelValue() {
return SequelValue {
.dataType = NULL_VALUE
};
}

SequelValue createBooleanSequelValue(bool value) {
return SequelValue {
.dataType = BOOLEAN,
.booleanValue = int(value)
};
}

SequelValue createTextSequelValue(string value) {
return SequelValue {
.dataType = TEXT,
.textValue = value
};
}

SequelValue createIntegerSequelValue(int value) {
return SequelValue {
.dataType = INTEGER,
.doubleOrIntValue = static_cast<double>(value)
};
}

SequelValue createIntegerSequelValue(double value) {
return SequelValue {
.dataType = INTEGER,
.doubleOrIntValue = value
};
}

SequelValue createInt64SequelValue(long long value) {
return SequelValue {
.dataType = INT64,
.int64Value = value
};
}

SequelValue createDoubleSequelValue(double value) {
return SequelValue {
.dataType = DOUBLE,
.doubleOrIntValue = value
};
}

SequelValue createArrayBufferSequelValue(uint8_t *arrayBufferValue, size_t arrayBufferSize) {
return SequelValue {
.dataType = ARRAY_BUFFER,
.arrayBufferValue = shared_ptr<uint8_t>{arrayBufferValue},
.arrayBufferSize = arrayBufferSize
};
}

void jsiQueryArgumentsToSequelParam(jsi::Runtime &rt, jsi::Value const &params, vector<SequelValue> *target)
{
// int jsiParamsLength = params.length(rt);
// vector<string> res;
// for (int ii = 0; ii < jsiParamsLength; ii++)
// {
// res.push_back(params.getValueAtIndex(rt, ii).asString(rt).utf8(rt));
// }
// return res;
vector<any> res;

if (params.isNull() || params.isUndefined())
{
return;
}

jsi::Array values = params.asObject(rt).asArray(rt);

for (int ii = 0; ii < values.length(rt); ii++)
{

jsi::Value value = values.getValueAtIndex(rt, ii);
if (value.isNull())
if (value.isNull() || value.isUndefined())
{
res.push_back(nullptr);
// sqlite3_bind_null(statement, ii + 1);
target->push_back(createNullSequelValue());
}
else if (value.isBool())
{
res.push_back(value.getBool());
// int intVal = int(value.getBool());
// sqlite3_bind_int(statement, ii + 1, intVal);
int intVal = int(value.getBool());
target->push_back(createBooleanSequelValue(value.getBool()));
}
else if (value.isNumber())
{
res.push_back(value.asNumber());
// double doubleVal = value.asNumber();
// int intVal = (int)doubleVal;
// long long longVal = (long)doubleVal;
// if (intVal == doubleVal)
// {
// sqlite3_bind_int(statement, ii + 1, intVal);
// }
// else if (longVal == doubleVal)
// {
// sqlite3_bind_int64(statement, ii + 1, longVal);
// }
// else
// {
// sqlite3_bind_double(statement, ii + 1, doubleVal);
// }
double doubleVal = value.asNumber();
int intVal = (int)doubleVal;
long long longVal = (long)doubleVal;
if (intVal == doubleVal)
{
target->push_back(createIntegerSequelValue(intVal));
}
else if (longVal == doubleVal)
{
target->push_back(createInt64SequelValue(longVal));
}
else
{
target->push_back(createDoubleSequelValue(doubleVal));
}
}
else if (value.isString())
{
res.push_back(value.asString(rt).utf8(rt));
// string strVal = value.asString(rt).utf8(rt);
//
// sqlite3_bind_text(statement, ii + 1, strVal.c_str(), strVal.length(), SQLITE_TRANSIENT);
string strVal = value.asString(rt).utf8(rt);
target->push_back(createTextSequelValue(strVal));
}
else if (value.isObject())
{
// auto obj = value.asObject(rt);
// if (obj.isArrayBuffer(rt))
// {
// auto buf = obj.getArrayBuffer(rt);
// // The statement is executed before returning control to JSI, so we don't need to copy the data to extend its lifetime.
// sqlite3_bind_blob(statement, ii + 1, buf.data(rt), buf.size(rt), SQLITE_STATIC);
// }
auto obj = value.asObject(rt);
if (obj.isArrayBuffer(rt))
{
auto buf = obj.getArrayBuffer(rt);
target->push_back(createArrayBufferSequelValue(buf.data(rt), buf.size(rt)));
}
}
else {
target->push_back(createNullSequelValue());
}
}



return res;
}

jsi::Value createSequelQueryExecutionResult(jsi::Runtime &rt, SequelOperationStatus status, vector<map<string,SequelValue>> *results)
{
jsi::Object res = jsi::Object(rt);
if(status.type == SequelResultOk)
{
//res.setProperty(rt, "rows", move(rows));
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();
jsi::Object rows = jsi::Object(rt);
if(rowCount > 0)
{
auto array = jsi::Array(rt, rowCount);
for(int i = 0; i<rowCount; i++)
{
jsi::Object rowObject = jsi::Object(rt);
auto row = results->at(i);
for (auto const& entry : row)
{
std::string columnName = entry.first;
SequelValue value = entry.second;
if (value.dataType == TEXT)
{
rowObject.setProperty(rt, columnName.c_str(), jsi::String::createFromUtf8(rt, value.textValue.c_str()));
}
else if (value.dataType == INTEGER)
{
rowObject.setProperty(rt, columnName.c_str(), jsi::Value(value.doubleOrIntValue));
}
else if (value.dataType == DOUBLE)
{
rowObject.setProperty(rt, columnName.c_str(), jsi::Value(value.doubleOrIntValue));
}
else if (value.dataType == ARRAY_BUFFER)
{
jsi::Function array_buffer_ctor = rt.global().getPropertyAsFunction(rt, "ArrayBuffer");
jsi::Object o = array_buffer_ctor.callAsConstructor(rt, (int)value.arrayBufferSize).getObject(rt);
jsi::ArrayBuffer buf = o.getArrayBuffer(rt);
// It's a shame we have to copy here: see https://github.com/facebook/hermes/pull/419 and https://github.com/facebook/hermes/issues/564.
memcpy(buf.data(rt), value.arrayBufferValue.get(), value.arrayBufferSize);
rowObject.setProperty(rt, columnName.c_str(), o);
}
else
{
rowObject.setProperty(rt, columnName.c_str(), jsi::Value(nullptr));
}
}
array.setValueAtIndex(rt, i, move(rowObject));
}
rows.setProperty(rt, "_array", move(array));
res.setProperty(rt, "rows", move(rows));
}
rows.setProperty(rt, "status", jsi::Value(0));
rows.setProperty(rt, "length", jsi::Value((int)rowCount));
}
else
{
res.setProperty(rt, "status", jsi::Value(1));
res.setProperty(rt, "message", jsi::String::createFromUtf8(rt, status.errorMessage.c_str()));
}

return move(res);
}
20 changes: 18 additions & 2 deletions cpp/JSIHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,27 @@
#include <stdio.h>
#include <jsi/jsilib.h>
#include <jsi/jsi.h>
#include <any>
#include <vector>
#include <map>
#include "SequelResult.h"

using namespace std;
using namespace facebook;

vector<any> jsiArrayToVector(jsi::Runtime &rt, jsi::Array values);
/**
* Fill the target vector with parsed parameters
* */
void jsiQueryArgumentsToSequelParam(jsi::Runtime &rt, jsi::Value const &args, vector<SequelValue> *target);

SequelValue createNullSequelValue();
SequelValue createBooleanSequelValue(bool value);
SequelValue createTextSequelValue(string value);
SequelValue createIntegerSequelValue(int value);
SequelValue createIntegerSequelValue(double value);
SequelValue createInt64SequelValue(long long value);
SequelValue createDoubleSequelValue(double value);
SequelValue createArrayBufferSequelValue(uint8_t *arrayBufferValue, size_t arrayBufferSize);
jsi::Value createSequelQueryExecutionResult(jsi::Runtime &rt, SequelOperationStatus status, vector<map<string,SequelValue>> *results);


#endif /* JSIHelper_h */
45 changes: 39 additions & 6 deletions cpp/SequelResult.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,41 @@
#include <jsi/jsilib.h>
#include <jsi/jsi.h>
#include <string>
#include <any>

using namespace std;
using namespace facebook;

enum SequelDataType {
NULL_VALUE,
TEXT,
INTEGER,
INT64,
DOUBLE,
BOOLEAN,
ARRAY_BUFFER,
};

/**
* TypeSafe dynamic parameter value to bind on sqlite statements
*/
struct SequelValue {
SequelDataType dataType;
int booleanValue;
double doubleOrIntValue;
long long int64Value;
string textValue;
shared_ptr<uint8_t> arrayBufferValue;
size_t arrayBufferSize;
};

/**
* TypeSafe dynamic column value holder representing a sqlite columnValue
*/
struct SequelColumnValue {
SequelValue value;
string columnName;
};

enum ResultType
{
SequelResultOk,
Expand All @@ -30,6 +60,14 @@ struct SequelResult
jsi::Value value;
};

struct SequelOperationStatus
{
ResultType type;
string errorMessage;
int rowsAffected;
double insertId;
};

struct SequelLiteralUpdateResult
{
ResultType type;
Expand All @@ -45,8 +83,3 @@ struct SequelBatchOperationResult
int commands;
};

struct SQLiteValueWrapper
{
string name;
any value;
};
Loading