Skip to content

Commit b23c629

Browse files
author
Oscar Franco
committed
Refactor all error throwing code out
2 parents e4fbe07 + 4f85109 commit b23c629

File tree

7 files changed

+69
-57
lines changed

7 files changed

+69
-57
lines changed

README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ Inspired/compatible with [react-native-sqlite-storage](https://github.com/andpor
2727

2828
## Gotchas
2929

30-
- **It's not possible to use a browser to debug a JSI app**, use [Flipper](https://github.com/facebook/flipper) (on android Flipper also has an integrated SQLite Database explorer).
30+
- **Javascript cannot represent intergers larger than 53 bits**, be careful when loading data if it came from other systems. [Read more](https://github.com/ospfranco/react-native-quick-sqlite/issues/16#issuecomment-1018412991).
31+
- **It's not possible to use a browser to debug a JSI app**, use [Flipper](https://github.com/facebook/flipper) (for android Flipper also has SQLite Database explorer).
3132
- Your app will now include C++, you will need to install the NDK on your machine for android.
3233
- This library supports SQLite BLOBs which are mapped to JS ArrayBuffers, check out the sample project on how to use it
34+
- From version 2.0.0 onwards errors are no longer thrown on invalid SQL statements. The response contains a `status` number, `0` signals correct execution, `1` signals an error.
35+
- From version 3.0.0 onwards no JS errors are thown, every operation returns an object with a `status` field.
3336
- If you want to run the example project on android, you will have to change the paths on the android/CMakeLists.txt file, they are already there, just uncomment them.
34-
- Starting with version 2.0.0 the library no longer throws errors when an invalid statement is passed, but returns a status (0 or 1) field in the response.
35-
- This library cannot retrieve integers larger than 53 bits because it's not possible to represent such numbers in JavaScript. [Read more](https://github.com/ospfranco/react-native-quick-sqlite/issues/16#issuecomment-1018412991).
3637

3738
## Use TypeORM
3839

@@ -76,19 +77,19 @@ interface ISQLite {
7677
In your code
7778

7879
```typescript
79-
// If you want to register the (globalThis) types for the low level API do an empty import
8080
import 'react-native-quick-sqlite';
8181

8282
// `sqlite` is a globally registered object, so you can directly call it from anywhere in your javascript
83-
// The methods `throw` when an execution error happens, so try/catch them
84-
try {
85-
sqlite.open('myDatabase', 'databases');
86-
} catch (e) {
87-
console.log(e); // [react-native-quick-sqlite]: Could not open database file: ERR XXX
83+
// the import on the top of the file only registers typescript types but it is not mandatory
84+
const dbOpenResult = sqlite.open('myDatabase', 'databases');
85+
86+
// status === 1, operation failed
87+
if (dbOpenResult.status) {
88+
console.error('Database could not be opened');
8889
}
8990
```
9091

91-
Some query examples:
92+
### Example queries
9293

9394
```typescript
9495
let result = sqlite.executeSql('myDatabase', 'SELECT somevalue FROM sometable');
@@ -129,7 +130,7 @@ if (!result.status) {
129130

130131
## Learn React Native JSI
131132

132-
If you want to learn how to make your own JSI module and also get a reference guide for all things C++/JSI you can buy my [JSI/C++ Cheatsheet](http://ospfranco.gumroad.com/l/IeeIvl)
133+
If you want to learn how to make your own JSI module buy my [JSI/C++ Cheatsheet](http://ospfranco.gumroad.com/l/IeeIvl), I'm also available for [freelance work](mailto:[email protected]?subject=Freelance)!
133134

134135
## License
135136

cpp/react-native-quick-sqlite.cpp

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ const vector<string> mapParams(jsi::Runtime &rt, jsi::Array &params)
3333

3434
string docPathStr;
3535

36+
jsi::Object createError(jsi::Runtime &rt, string message) {
37+
auto res = jsi::Object(rt);
38+
res.setProperty(rt, "status", jsi::Value(1));
39+
res.setProperty(rt, "message", jsi::String::createFromUtf8(rt, message));
40+
return res;
41+
}
42+
3643
void installSequel(jsi::Runtime &rt, const char *docPath)
3744
{
3845

@@ -47,22 +54,19 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
4754
[](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
4855
{
4956
if(count == 0) {
50-
jsi::detail::throwJSError(rt, "[react-native-quick-sqlite] database name is required");
51-
return {};
57+
return createError(rt, "[react-native-quick-sqlite][open] database name is required");
5258
}
5359

5460
if (!args[0].isString())
5561
{
56-
jsi::detail::throwJSError(rt, "[react-native-quick-sqlite] database name must be a string");
57-
return {};
62+
return createError(rt, "[react-native-quick-sqlite][open] database name must be a string");
5863
}
5964

6065
string dbName = args[0].asString(rt).utf8(rt);
6166
string tempDocPath = string(docPathStr);
6267
if(count > 1) {
6368
if(!args[1].isString()) {
64-
jsi::detail::throwJSError(rt, "[react-native-quick-sqlite] database location must be a string");
65-
return {};
69+
return createError(rt, "[react-native-quick-sqlite][open] database location must be a string");
6670
}
6771

6872
tempDocPath = tempDocPath + "/" + args[1].asString(rt).utf8(rt);
@@ -73,8 +77,7 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
7377

7478
if (result.type == SequelResultError)
7579
{
76-
jsi::detail::throwJSError(rt, result.message.c_str());
77-
return {};
80+
return createError(rt, result.message.c_str());
7881
}
7982

8083
return move(result.value);
@@ -110,20 +113,23 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
110113
1,
111114
[](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
112115
{
116+
if(count == 0) {
117+
return createError(rt, "[react-native-quick-sqlite][close] database name is required");
118+
}
119+
113120
if (!args[0].isString())
114121
{
115-
jsi::detail::throwJSError(rt, "dbName must be a string");
116-
return {};
122+
return createError(rt, "[react-native-quick-sqlite][close] database name must be a string");
117123
}
118124

125+
119126
string dbName = args[0].asString(rt).utf8(rt);
120127

121128
SequelResult result = sequel_close(dbName);
122129

123130
if (result.type == SequelResultError)
124131
{
125-
jsi::detail::throwJSError(rt, result.message.c_str());
126-
return {};
132+
return createError(rt, result.message.c_str());
127133
}
128134

129135
return move(result.value);
@@ -136,20 +142,23 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
136142
1,
137143
[](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
138144
{
145+
if(count == 0) {
146+
return createError(rt, "[react-native-quick-sqlite][open] database name is required");
147+
}
148+
139149
if (!args[0].isString())
140150
{
141-
jsi::detail::throwJSError(rt, "dbName must be a string");
142-
return {};
151+
return createError(rt, "[react-native-quick-sqlite][open] database name must be a string");
143152
}
144153

154+
145155
string dbName = args[0].asString(rt).utf8(rt);
146156

147157
SequelResult result = sequel_remove(dbName, docPathStr);
148158

149159
if (result.type == SequelResultError)
150160
{
151-
jsi::detail::throwJSError(rt, result.message.c_str());
152-
return {};
161+
return createError(rt, result.message.c_str());
153162
}
154163

155164
return jsi::Value::undefined();
@@ -169,11 +178,7 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
169178

170179
if (result.type == SequelResultError)
171180
{
172-
// jsi::detail::throwJSError(rt, result.message.c_str());
173-
auto res = jsi::Object(rt);
174-
res.setProperty(rt, "status", jsi::Value(1));
175-
res.setProperty(rt, "message", jsi::String::createFromUtf8(rt, result.message.c_str()));
176-
return move(res);
181+
return createError(rt, result.message.c_str());
177182
}
178183

179184
return move(result.value);
@@ -188,16 +193,16 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
188193
[](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value
189194
{
190195
if(sizeof(args) < 2) {
191-
jsi::detail::throwJSError(rt, "[react-native-quick-sqlite][execSQLBatch] - Incorrect parameter count");
192-
return {};
196+
return createError(rt, "[react-native-quick-sqlite][execSQLBatch] - Incorrect parameter count");
193197
}
198+
194199
const string dbName = args[0].asString(rt).utf8(rt);
195200
const jsi::Value &params = args[1];
196201
if(params.isNull() || params.isUndefined())
197202
{
198-
jsi::detail::throwJSError(rt, "[react-native-quick-sqlite][execSQLBatch] - An array of SQL commands or parameters is needed");
199-
return {};
203+
return createError(rt, "[react-native-quick-sqlite][execSQLBatch] - An array of SQL commands or parameters is needed");
200204
}
205+
201206
int rowsAffected = 0;
202207
const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
203208
try
@@ -208,8 +213,7 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
208213
const jsi::Array &command = batchParams.getValueAtIndex(rt, i).asObject(rt).asArray(rt);
209214
if(command.length(rt) == 0) {
210215
sequel_execute(rt, dbName, "ROLLBACK", jsi::Value::undefined());
211-
jsi::detail::throwJSError(rt, "[react-native-quick-sqlite][execSQLBatch] - No SQL Commands found");
212-
return {};
216+
return createError(rt, "[react-native-quick-sqlite][execSQLBatch] - No SQL Commands found on batch index " + std::to_string(i));
213217
}
214218
const string query = command.getValueAtIndex(rt, 0).asString(rt).utf8(rt);
215219
const jsi::Value &commandParams = command.length(rt) > 1 ? command.getValueAtIndex(rt, 1) : jsi::Value::undefined();
@@ -224,10 +228,8 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
224228
if (result.type == SequelResultError)
225229
{
226230
sequel_execute(rt, dbName, "ROLLBACK", jsi::Value::undefined());
227-
auto res = jsi::Object(rt);
228-
res.setProperty(rt, "status", jsi::Value(1));
229-
res.setProperty(rt, "message", jsi::String::createFromUtf8(rt, result.message.c_str()));
230-
return move(res);
231+
return createError(rt, result.message.c_str());
232+
231233
} else {
232234
if(result.value.getObject(rt).hasProperty(rt, jsi::PropNameID::forAscii(rt, "rowsAffected")))
233235
{
@@ -240,10 +242,8 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
240242
if (result.type == SequelResultError)
241243
{
242244
sequel_execute(rt, dbName, "ROLLBACK", jsi::Value::undefined());
243-
auto res = jsi::Object(rt);
244-
res.setProperty(rt, "status", jsi::Value(1));
245-
res.setProperty(rt, "message", jsi::String::createFromUtf8(rt, result.message.c_str()));
246-
return move(res);
245+
246+
return createError(rt, result.message.c_str());
247247
} else {
248248
if(result.value.getObject(rt).hasProperty(rt, jsi::PropNameID::forAscii(rt, "rowsAffected")))
249249
{
@@ -255,7 +255,9 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
255255
sequel_execute(rt, dbName, "COMMIT", jsi::Value::undefined());
256256
} catch (...) {
257257
sequel_execute(rt, dbName, "ROLLBACK", jsi::Value::undefined());
258+
return createError(rt, "[react-native-quick-sqlite][execSQLBatch] - Unexpected error");
258259
}
260+
259261
auto res = jsi::Object(rt);
260262
res.setProperty(rt, "status", jsi::Value(0));
261263
res.setProperty(rt, "rowsAffected", jsi::Value(rowsAffected));
@@ -307,11 +309,10 @@ void installSequel(jsi::Runtime &rt, const char *docPath)
307309
} catch (...) {
308310
sqFile.close();
309311
sequel_execute_literal_update(dbName, "ROLLBACK");
310-
jsi::detail::throwJSError(rt, "Unexpected error, transaction was rolledback");
311-
return {};
312+
return createError(rt, "[react-native-quick-sqlite][loadSQLFile] Unexpected error, transaction was rolledback");
312313
}
313314
} else {
314-
jsi::detail::throwJSError(rt, "Unable to open file");
315+
return createError(rt, "[react-native-quick-sqlite][loadSQLFile] Could not open file");
315316
return {};
316317
}
317318
});

example/ios/Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ PODS:
185185
- React-cxxreact (= 0.63.4)
186186
- React-jsi (= 0.63.4)
187187
- React-jsinspector (0.63.4)
188-
- react-native-quick-sqlite (1.0.5):
188+
- react-native-quick-sqlite (2.0.3):
189189
- React-Core
190190
- React-RCTActionSheet (0.63.4):
191191
- React-Core/RCTActionSheetHeaders (= 0.63.4)
@@ -357,7 +357,7 @@ SPEC CHECKSUMS:
357357
React-jsi: a0418934cf48f25b485631deb27c64dc40fb4c31
358358
React-jsiexecutor: 93bd528844ad21dc07aab1c67cb10abae6df6949
359359
React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a
360-
react-native-quick-sqlite: b86820d88ce8c0ee4b5491a2ba1ebbf807a311b4
360+
react-native-quick-sqlite: 132b2712269190bd42c73d044b4ce941e95b6a0a
361361
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
362362
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
363363
React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0

example/src/App.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from 'react-native';
1111
import { createDb } from './Database';
1212
import type { User } from './model/User';
13-
import { Buffer } from "buffer";
13+
import { Buffer } from 'buffer';
1414

1515
export default function App() {
1616
let [users, setUsers] = React.useState<User[]>([]);
@@ -36,7 +36,14 @@ export default function App() {
3636
backgroundColor: 'white',
3737
}}
3838
>
39-
<Image style={{width: 64, height: 64}} source={{uri: `data:image/png;base64,${Buffer.from(info.item.avatar).toString("base64")}`}}></Image>
39+
<Image
40+
style={{ width: 64, height: 64 }}
41+
source={{
42+
uri: `data:image/png;base64,${Buffer.from(
43+
info.item.avatar
44+
).toString('base64')}`,
45+
}}
46+
/>
4047
<Text style={{ fontWeight: 'bold' }}>Name</Text>
4148
<Text>{info.item.name}</Text>
4249
<Text style={{ fontWeight: 'bold', marginTop: 10 }}>Age</Text>

0 commit comments

Comments
 (0)