@op-engineering/op-sqlite 2.0.0 → 2.0.2
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/README.md +82 -24
- package/android/CMakeLists.txt +4 -2
- package/cpp/DumbHostObject.cpp +32 -27
- package/cpp/DumbHostObject.h +16 -16
- package/cpp/PreparedStatementHostObject.cpp +88 -0
- package/cpp/PreparedStatementHostObject.h +36 -0
- package/cpp/SmartHostObject.cpp +33 -0
- package/cpp/SmartHostObject.h +26 -0
- package/cpp/ThreadPool.cpp +103 -116
- package/cpp/ThreadPool.h +27 -27
- package/cpp/bindings.cpp +525 -530
- package/cpp/bindings.h +6 -5
- package/cpp/bridge.cpp +713 -651
- package/cpp/bridge.h +41 -19
- package/cpp/logs.h +17 -17
- package/cpp/macros.h +1 -1
- package/cpp/sqlbatchexecutor.cpp +75 -77
- package/cpp/sqlbatchexecutor.h +9 -8
- package/cpp/sqlite3.h +1295 -1389
- package/cpp/types.h +5 -4
- package/cpp/utils.cpp +159 -191
- package/cpp/utils.h +28 -35
- package/ios/OPSQLite.mm +13 -5
- package/lib/commonjs/index.js +2 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +2 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/index.d.ts +6 -0
- package/package.json +2 -1
- package/src/index.ts +8 -0
- package/cpp/DynamicHostObject.cpp +0 -32
- package/cpp/DynamicHostObject.h +0 -26
package/README.md
CHANGED
|
@@ -20,7 +20,9 @@ You can find the [benchmarking code in the example app](https://github.com/OP-En
|
|
|
20
20
|
|
|
21
21
|

|
|
22
22
|
|
|
23
|
-
Memory consumption is also
|
|
23
|
+
Memory consumption is also 1/4 compared to `react-native-quick-sqlite`. This query used to take 1.2 GB of peak memory usage, and now runs in 250mbs.
|
|
24
|
+
|
|
25
|
+
You can also turn on Memory Mapping to make your queries even faster by skipping the kernel during I/O, this comes with some disadvantages though. If you want even more speed and you can re-use your queries you can use prepared statements.
|
|
24
26
|
|
|
25
27
|
# Encryption
|
|
26
28
|
|
|
@@ -39,8 +41,8 @@ You can use relative location to navigate in and out of the **default location**
|
|
|
39
41
|
```ts
|
|
40
42
|
import { open } from '@op-engineering/op-sqlite';
|
|
41
43
|
|
|
42
|
-
const
|
|
43
|
-
name: '
|
|
44
|
+
const db = open({
|
|
45
|
+
name: 'myDB',
|
|
44
46
|
location: '../files/databases',
|
|
45
47
|
});
|
|
46
48
|
```
|
|
@@ -53,20 +55,42 @@ You can also pass absolute paths to completely change the location of the databa
|
|
|
53
55
|
|
|
54
56
|
```ts
|
|
55
57
|
import {
|
|
58
|
+
IOS_LIBRARY_PATH, // Default iOS
|
|
56
59
|
IOS_DOCUMENT_PATH,
|
|
57
|
-
|
|
58
|
-
ANDROID_DATABASE_PATH,
|
|
60
|
+
ANDROID_DATABASE_PATH, // Default Android
|
|
59
61
|
ANDROID_FILES_PATH,
|
|
60
62
|
ANDROID_EXTERNAL_FILES_PATH,
|
|
61
63
|
open,
|
|
62
64
|
} from '@op-engineering/op-sqlite';
|
|
63
65
|
|
|
64
|
-
const
|
|
65
|
-
name: '
|
|
66
|
+
const db = open({
|
|
67
|
+
name: 'myDb',
|
|
66
68
|
location: Platform.OS === 'ios' ? IOS_LIBRARY_PATH : ANDROID_DATABASE_PATH,
|
|
67
69
|
});
|
|
68
70
|
```
|
|
69
71
|
|
|
72
|
+
Here is an example if you want to access the SD card app's directory:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
const db = open({
|
|
76
|
+
name: 'myDB',
|
|
77
|
+
location:
|
|
78
|
+
Platform.OS === 'ios' ? IOS_LIBRARY_PATH : ANDROID_EXTERNAL_FILES_PATH,
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
You can even drill down:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const db = open({
|
|
86
|
+
name: 'myDB',
|
|
87
|
+
location:
|
|
88
|
+
Platform.OS === 'ios'
|
|
89
|
+
? IOS_LIBRARY_PATH
|
|
90
|
+
: `${ANDROID_EXTERNAL_FILES_PATH}/dbs/`,
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
70
94
|
## In-memory
|
|
71
95
|
|
|
72
96
|
Using SQLite in-memory mode is supported by passing a `':memory:'` as a location:
|
|
@@ -80,6 +104,21 @@ const largeDb = open({
|
|
|
80
104
|
});
|
|
81
105
|
```
|
|
82
106
|
|
|
107
|
+
# Speed
|
|
108
|
+
|
|
109
|
+
op-sqlite is already the fastest solution it can be, but it doesn't mean you cannot tweak SQLite to be faster (at the cost of some disadvantages). One possible tweak is turning on [Memory Mapping](https://www.sqlite.org/mmap.html). It allows to read/write to/from the disk without going through the kernel. However, if your queries throw an error your application might crash.
|
|
110
|
+
|
|
111
|
+
To turn on Memory Mapping, execute the following pragma statement after opening a db:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
const db = open({
|
|
115
|
+
name: 'mydb.sqlite',
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// 0 turns of memory mapping, any other number enables it with the cache size
|
|
119
|
+
db.execute('PRAGMA mmap_size=268435456');
|
|
120
|
+
```
|
|
121
|
+
|
|
83
122
|
# API
|
|
84
123
|
|
|
85
124
|
```typescript
|
|
@@ -112,7 +151,7 @@ db = {
|
|
|
112
151
|
}
|
|
113
152
|
```
|
|
114
153
|
|
|
115
|
-
|
|
154
|
+
## Simple queries
|
|
116
155
|
|
|
117
156
|
The basic query is **synchronous**, it will block rendering on large operations, further below you will find async versions.
|
|
118
157
|
|
|
@@ -140,7 +179,7 @@ try {
|
|
|
140
179
|
}
|
|
141
180
|
```
|
|
142
181
|
|
|
143
|
-
|
|
182
|
+
## Multiple statements in a single string
|
|
144
183
|
|
|
145
184
|
You can execute multiple statements in a single operation. The API however is not really thought for this use case and the results (and their metadata) will be mangled, so you can discard it.
|
|
146
185
|
|
|
@@ -164,7 +203,7 @@ let t2name = db.execute(
|
|
|
164
203
|
console.log(t2name.rows?._array[0].name); // outputs "T2"
|
|
165
204
|
```
|
|
166
205
|
|
|
167
|
-
|
|
206
|
+
## Transactions
|
|
168
207
|
|
|
169
208
|
Throwing an error inside the callback will ROLLBACK the transaction.
|
|
170
209
|
|
|
@@ -193,7 +232,7 @@ await db.transaction('myDatabase', (tx) => {
|
|
|
193
232
|
});
|
|
194
233
|
```
|
|
195
234
|
|
|
196
|
-
|
|
235
|
+
## Batch operation
|
|
197
236
|
|
|
198
237
|
Batch execution allows the transactional execution of a set of commands
|
|
199
238
|
|
|
@@ -210,7 +249,7 @@ const res = db.executeSqlBatch('myDatabase', commands);
|
|
|
210
249
|
console.log(`Batch affected ${result.rowsAffected} rows`);
|
|
211
250
|
```
|
|
212
251
|
|
|
213
|
-
|
|
252
|
+
## Dynamic Column Metadata
|
|
214
253
|
|
|
215
254
|
In some scenarios, dynamic applications may need to get some metadata information about the returned result set.
|
|
216
255
|
|
|
@@ -231,7 +270,7 @@ metadata.forEach((column) => {
|
|
|
231
270
|
});
|
|
232
271
|
```
|
|
233
272
|
|
|
234
|
-
|
|
273
|
+
## Async operations
|
|
235
274
|
|
|
236
275
|
You might have too much SQL to process and it will cause your application to freeze. There are async versions for some of the operations. This will offload the SQLite processing to a different thread.
|
|
237
276
|
|
|
@@ -245,7 +284,7 @@ db.executeAsync(
|
|
|
245
284
|
);
|
|
246
285
|
```
|
|
247
286
|
|
|
248
|
-
|
|
287
|
+
## Blobs
|
|
249
288
|
|
|
250
289
|
Blobs are supported via `ArrayBuffer`, you need to be careful about the semantics though. You cannot instantiate an instance of `ArrayBuffer` directly, nor pass a typed array directly. Here is an example:
|
|
251
290
|
|
|
@@ -273,7 +312,22 @@ const result = db.execute('SELECT content FROM BlobTable');
|
|
|
273
312
|
const finalUint8 = new Uint8Array(result.rows!._array[0].content);
|
|
274
313
|
```
|
|
275
314
|
|
|
276
|
-
|
|
315
|
+
## Prepared statements
|
|
316
|
+
|
|
317
|
+
A lot of the work when executing queries is not iterating through the result set itself but, sometimes, planning the execution. If you have a query which is expensive but you can re-use (even if you have to change the arguments) you can use a `prepared statement`:
|
|
318
|
+
|
|
319
|
+
```ts
|
|
320
|
+
const statement = db.prepareStatement('SELECT * FROM User WHERE name = ?;');
|
|
321
|
+
statement.bind(['Oscar']);
|
|
322
|
+
let results1 = statement.execute();
|
|
323
|
+
|
|
324
|
+
statement.bind(['Carlos']);
|
|
325
|
+
let results2 = statement.execute();
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
You only pay the price of parsing the query once, and each subsequent execution should be faster.
|
|
329
|
+
|
|
330
|
+
# Attach or Detach other databases
|
|
277
331
|
|
|
278
332
|
SQLite supports attaching or detaching other database files into your main database connection through an alias.
|
|
279
333
|
You can do any operation you like on this attached database like JOIN results across tables in different schemas, or update data or objects.
|
|
@@ -300,7 +354,7 @@ if (!detachResult.status) {
|
|
|
300
354
|
}
|
|
301
355
|
```
|
|
302
356
|
|
|
303
|
-
|
|
357
|
+
# Loading SQL Dump Files
|
|
304
358
|
|
|
305
359
|
If you have a SQL dump file, you can load it directly, with low memory consumption:
|
|
306
360
|
|
|
@@ -312,7 +366,7 @@ const { rowsAffected, commands } = db
|
|
|
312
366
|
});
|
|
313
367
|
```
|
|
314
368
|
|
|
315
|
-
|
|
369
|
+
# Hooks
|
|
316
370
|
|
|
317
371
|
You can subscribe to changes in your database by using an update hook:
|
|
318
372
|
|
|
@@ -374,7 +428,7 @@ db.commitHook(null);
|
|
|
374
428
|
db.rollbackHook(null);
|
|
375
429
|
```
|
|
376
430
|
|
|
377
|
-
|
|
431
|
+
# Use built-in SQLite
|
|
378
432
|
|
|
379
433
|
On iOS you can use the embedded SQLite, when running `pod-install` add an environment flag:
|
|
380
434
|
|
|
@@ -384,11 +438,11 @@ OP_SQLITE_USE_PHONE_VERSION=1 npx pod-install
|
|
|
384
438
|
|
|
385
439
|
On Android, it is not possible to link the OS SQLite. It is also a bad idea due to vendor changes, old android bugs, etc. Unfortunately, this means this library will add some megabytes to your app size.
|
|
386
440
|
|
|
387
|
-
|
|
441
|
+
# Enable compile-time options
|
|
388
442
|
|
|
389
443
|
By specifying pre-processor flags, you can enable optional features like FTS5, Geopoly, etc.
|
|
390
444
|
|
|
391
|
-
|
|
445
|
+
## iOS
|
|
392
446
|
|
|
393
447
|
Add a `post_install` block to your `<PROJECT_ROOT>/ios/Podfile` like so:
|
|
394
448
|
|
|
@@ -407,7 +461,7 @@ end
|
|
|
407
461
|
Replace the `<SQLITE_FLAGS>` part with the flags you want to add.
|
|
408
462
|
For example, you could add `SQLITE_ENABLE_FTS5=1` to `GCC_PREPROCESSOR_DEFINITIONS` to enable FTS5 in the iOS project.
|
|
409
463
|
|
|
410
|
-
|
|
464
|
+
## Android
|
|
411
465
|
|
|
412
466
|
You can specify flags via `<PROJECT_ROOT>/android/gradle.properties` like so:
|
|
413
467
|
|
|
@@ -415,14 +469,18 @@ You can specify flags via `<PROJECT_ROOT>/android/gradle.properties` like so:
|
|
|
415
469
|
OPSQLiteFlags="-DSQLITE_ENABLE_FTS5=1"
|
|
416
470
|
```
|
|
417
471
|
|
|
418
|
-
|
|
472
|
+
# Additional configuration
|
|
419
473
|
|
|
420
|
-
|
|
474
|
+
## App groups (iOS only)
|
|
421
475
|
|
|
422
476
|
On iOS, the SQLite database can be placed in an app group, in order to make it accessible from other apps in that app group. E.g. for sharing capabilities.
|
|
423
477
|
|
|
424
478
|
To use an app group, add the app group ID as the value for the `OPSQLite_AppGroup` key in your project's `Info.plist` file. You'll also need to configure the app group in your project settings. (Xcode -> Project Settings -> Signing & Capabilities -> Add Capability -> App Groups)
|
|
425
479
|
|
|
426
|
-
|
|
480
|
+
# Contribute
|
|
481
|
+
|
|
482
|
+
You need to have clang-format installed (`brew install clang-format`)
|
|
483
|
+
|
|
484
|
+
# License
|
|
427
485
|
|
|
428
486
|
MIT License.
|
package/android/CMakeLists.txt
CHANGED
|
@@ -29,8 +29,10 @@ add_library(
|
|
|
29
29
|
../cpp/ThreadPool.cpp
|
|
30
30
|
../cpp/sqlbatchexecutor.h
|
|
31
31
|
../cpp/sqlbatchexecutor.cpp
|
|
32
|
-
../cpp/
|
|
33
|
-
../cpp/
|
|
32
|
+
../cpp/SmartHostObject.cpp
|
|
33
|
+
../cpp/SmartHostObject.h
|
|
34
|
+
../cpp/PreparedStatementHostObject.h
|
|
35
|
+
../cpp/PreparedStatementHostObject.cpp
|
|
34
36
|
../cpp/DumbHostObject.cpp
|
|
35
37
|
../cpp/DumbHostObject.h
|
|
36
38
|
../cpp/macros.h
|
package/cpp/DumbHostObject.cpp
CHANGED
|
@@ -1,37 +1,42 @@
|
|
|
1
1
|
#include "DumbHostObject.h"
|
|
2
|
+
#include "SmartHostObject.h"
|
|
2
3
|
#include "utils.h"
|
|
3
4
|
#include <iostream>
|
|
4
5
|
|
|
5
6
|
namespace opsqlite {
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
namespace jsi = facebook::jsi;
|
|
9
|
+
|
|
10
|
+
DumbHostObject::DumbHostObject(
|
|
11
|
+
std::shared_ptr<std::vector<SmartHostObject>> metadata) {
|
|
12
|
+
this->metadata = metadata;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
std::vector<jsi::PropNameID>
|
|
16
|
+
DumbHostObject::getPropertyNames(jsi::Runtime &rt) {
|
|
17
|
+
std::vector<jsi::PropNameID> keys;
|
|
18
|
+
|
|
19
|
+
for (auto field : *metadata) {
|
|
20
|
+
// TODO improve this by generating the propName once on metadata creation
|
|
21
|
+
keys.push_back(jsi::PropNameID::forAscii(
|
|
22
|
+
rt, std::get<std::string>(field.fields[0].second)));
|
|
23
|
+
}
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
25
|
+
return keys;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
jsi::Value DumbHostObject::get(jsi::Runtime &rt,
|
|
29
|
+
const jsi::PropNameID &propNameID) {
|
|
30
|
+
auto name = propNameID.utf8(rt);
|
|
31
|
+
auto fields = metadata.get();
|
|
32
|
+
for (int i = 0; i < fields->size(); i++) {
|
|
33
|
+
auto fieldName = std::get<std::string>(fields->at(i).fields[0].second);
|
|
34
|
+
if (fieldName == name) {
|
|
35
|
+
return toJSI(rt, values.at(i));
|
|
35
36
|
}
|
|
37
|
+
}
|
|
36
38
|
|
|
39
|
+
return {};
|
|
37
40
|
}
|
|
41
|
+
|
|
42
|
+
} // namespace opsqlite
|
package/cpp/DumbHostObject.h
CHANGED
|
@@ -3,31 +3,31 @@
|
|
|
3
3
|
|
|
4
4
|
#include <stdio.h>
|
|
5
5
|
|
|
6
|
-
#include
|
|
6
|
+
#include "SmartHostObject.h"
|
|
7
|
+
#include "types.h"
|
|
7
8
|
#include <any>
|
|
9
|
+
#include <jsi/jsi.h>
|
|
8
10
|
#include <vector>
|
|
9
|
-
#include "types.h"
|
|
10
|
-
#include "DynamicHostObject.h"
|
|
11
11
|
|
|
12
12
|
namespace opsqlite {
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
namespace jsi = facebook::jsi;
|
|
15
|
+
|
|
16
|
+
class JSI_EXPORT DumbHostObject : public jsi::HostObject {
|
|
17
|
+
public:
|
|
18
|
+
DumbHostObject(){};
|
|
19
|
+
|
|
20
|
+
DumbHostObject(std::shared_ptr<std::vector<SmartHostObject>> metadata);
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
public:
|
|
18
|
-
DumbHostObject() {};
|
|
19
|
-
|
|
20
|
-
DumbHostObject(std::shared_ptr<std::vector<DynamicHostObject>> metadata);
|
|
22
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt);
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propNameID);
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
std::vector<JSVariant> values;
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
std::shared_ptr<std::vector<DynamicHostObject>> metadata;
|
|
29
|
-
};
|
|
28
|
+
std::shared_ptr<std::vector<SmartHostObject>> metadata;
|
|
29
|
+
};
|
|
30
30
|
|
|
31
|
-
}
|
|
31
|
+
} // namespace opsqlite
|
|
32
32
|
|
|
33
33
|
#endif /* DumbHostObject_h */
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PreparedStatementHostObject.cpp
|
|
3
|
+
// op-sqlite
|
|
4
|
+
//
|
|
5
|
+
// Created by Oscar Franco on 5/12/23.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "PreparedStatementHostObject.h"
|
|
9
|
+
#include "bridge.h"
|
|
10
|
+
#include "macros.h"
|
|
11
|
+
#include "utils.h"
|
|
12
|
+
|
|
13
|
+
namespace opsqlite {
|
|
14
|
+
|
|
15
|
+
namespace jsi = facebook::jsi;
|
|
16
|
+
|
|
17
|
+
PreparedStatementHostObject::PreparedStatementHostObject(
|
|
18
|
+
std::string dbName, sqlite3_stmt *statementPtr)
|
|
19
|
+
: _dbName(dbName), _statement(statementPtr) {}
|
|
20
|
+
|
|
21
|
+
std::vector<jsi::PropNameID>
|
|
22
|
+
PreparedStatementHostObject::getPropertyNames(jsi::Runtime &rt) {
|
|
23
|
+
std::vector<jsi::PropNameID> keys;
|
|
24
|
+
|
|
25
|
+
// for (auto field : fields) {
|
|
26
|
+
// keys.push_back(jsi::PropNameID::forAscii(rt, field.first));
|
|
27
|
+
// }
|
|
28
|
+
|
|
29
|
+
return keys;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
jsi::Value PreparedStatementHostObject::get(jsi::Runtime &rt,
|
|
33
|
+
const jsi::PropNameID &propNameID) {
|
|
34
|
+
auto name = propNameID.utf8(rt);
|
|
35
|
+
|
|
36
|
+
if (name == "bind") {
|
|
37
|
+
return HOSTFN("bind", 1) {
|
|
38
|
+
if (_statement == NULL) {
|
|
39
|
+
throw std::runtime_error("statement has been freed");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
std::vector<JSVariant> params;
|
|
43
|
+
|
|
44
|
+
const jsi::Value &originalParams = args[0];
|
|
45
|
+
params = toVariantVec(rt, originalParams);
|
|
46
|
+
|
|
47
|
+
std::vector<DumbHostObject> results;
|
|
48
|
+
std::shared_ptr<std::vector<SmartHostObject>> metadata =
|
|
49
|
+
std::make_shared<std::vector<SmartHostObject>>();
|
|
50
|
+
|
|
51
|
+
sqlite_bind_statement(_statement, ¶ms);
|
|
52
|
+
|
|
53
|
+
return {};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (name == "execute") {
|
|
58
|
+
return HOSTFN("execute", 1) {
|
|
59
|
+
if (_statement == NULL) {
|
|
60
|
+
throw std::runtime_error("statement has been freed");
|
|
61
|
+
}
|
|
62
|
+
std::vector<DumbHostObject> results;
|
|
63
|
+
std::shared_ptr<std::vector<SmartHostObject>> metadata =
|
|
64
|
+
std::make_shared<std::vector<SmartHostObject>>();
|
|
65
|
+
|
|
66
|
+
auto status = sqlite_execute_prepared_statement(_dbName, _statement,
|
|
67
|
+
&results, metadata);
|
|
68
|
+
|
|
69
|
+
if (status.type == SQLiteError) {
|
|
70
|
+
throw std::runtime_error(status.message);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
auto jsiResult = createResult(rt, status, &results, metadata);
|
|
74
|
+
return jsiResult;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
PreparedStatementHostObject::~PreparedStatementHostObject() {
|
|
82
|
+
if (_statement != NULL) {
|
|
83
|
+
sqlite3_finalize(_statement);
|
|
84
|
+
_statement = NULL;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
} // namespace opsqlite
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PreparedStatementHostObject.hpp
|
|
3
|
+
// op-sqlite
|
|
4
|
+
//
|
|
5
|
+
// Created by Oscar Franco on 5/12/23.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#ifndef PreparedStatementHostObject_h
|
|
9
|
+
#define PreparedStatementHostObject_h
|
|
10
|
+
|
|
11
|
+
#include <jsi/jsi.h>
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <sqlite3.h>
|
|
14
|
+
#include <string>
|
|
15
|
+
|
|
16
|
+
namespace opsqlite {
|
|
17
|
+
namespace jsi = facebook::jsi;
|
|
18
|
+
|
|
19
|
+
class PreparedStatementHostObject : public jsi::HostObject {
|
|
20
|
+
public:
|
|
21
|
+
PreparedStatementHostObject(std::string dbName, sqlite3_stmt *statement);
|
|
22
|
+
virtual ~PreparedStatementHostObject();
|
|
23
|
+
|
|
24
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt);
|
|
25
|
+
|
|
26
|
+
jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propNameID);
|
|
27
|
+
|
|
28
|
+
private:
|
|
29
|
+
std::string _dbName;
|
|
30
|
+
// This shouldn't be de-allocated until sqlite3_finalize is called on it
|
|
31
|
+
sqlite3_stmt *_statement;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
} // namespace opsqlite
|
|
35
|
+
|
|
36
|
+
#endif /* PreparedStatementHostObject_hpp */
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#include "SmartHostObject.h"
|
|
2
|
+
#include "utils.h"
|
|
3
|
+
|
|
4
|
+
namespace opsqlite {
|
|
5
|
+
|
|
6
|
+
namespace jsi = facebook::jsi;
|
|
7
|
+
|
|
8
|
+
std::vector<jsi::PropNameID>
|
|
9
|
+
SmartHostObject::getPropertyNames(jsi::Runtime &rt) {
|
|
10
|
+
std::vector<jsi::PropNameID> keys;
|
|
11
|
+
|
|
12
|
+
for (auto field : fields) {
|
|
13
|
+
keys.push_back(jsi::PropNameID::forAscii(rt, field.first));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return keys;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
jsi::Value SmartHostObject::get(jsi::Runtime &rt,
|
|
20
|
+
const jsi::PropNameID &propNameID) {
|
|
21
|
+
auto name = propNameID.utf8(rt);
|
|
22
|
+
|
|
23
|
+
for (auto field : fields) {
|
|
24
|
+
auto fieldName = field.first;
|
|
25
|
+
if (fieldName == name) {
|
|
26
|
+
return toJSI(rt, field.second);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
} // namespace opsqlite
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#ifndef SmartHostObject_h
|
|
2
|
+
#define SmartHostObject_h
|
|
3
|
+
|
|
4
|
+
#include "types.h"
|
|
5
|
+
#include <any>
|
|
6
|
+
#include <jsi/jsi.h>
|
|
7
|
+
#include <vector>
|
|
8
|
+
|
|
9
|
+
namespace opsqlite {
|
|
10
|
+
|
|
11
|
+
namespace jsi = facebook::jsi;
|
|
12
|
+
|
|
13
|
+
class JSI_EXPORT SmartHostObject : public jsi::HostObject {
|
|
14
|
+
public:
|
|
15
|
+
SmartHostObject(){};
|
|
16
|
+
|
|
17
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt);
|
|
18
|
+
|
|
19
|
+
jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propNameID);
|
|
20
|
+
|
|
21
|
+
std::vector<std::pair<std::string, JSVariant>> fields;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
} // namespace opsqlite
|
|
25
|
+
|
|
26
|
+
#endif /* SmartHostObject_h */
|