@stoolap/node 0.3.4 → 0.3.5
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 +4 -2
- package/lib/database.js +2 -2
- package/lib/transaction.js +4 -2
- package/package.json +7 -6
- package/src/stoolap.c +51 -15
package/README.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# @stoolap/node
|
|
2
2
|
|
|
3
|
-
High-performance
|
|
3
|
+
High-performance JavaScript driver for [Stoolap](https://github.com/stoolap/stoolap), a modern embedded SQL database with MVCC, time-travel queries, and full ACID compliance.
|
|
4
4
|
|
|
5
|
-
Built with a native N-API C addon for minimal overhead. Provides both async and sync APIs.
|
|
5
|
+
Built with a native N-API C addon for minimal overhead. Works with Node.js, Bun, and Deno. Provides both async and sync APIs.
|
|
6
6
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://nodejs.org)
|
|
9
|
+
[](https://bun.sh)
|
|
10
|
+
[](https://deno.com)
|
|
9
11
|
|
|
10
12
|
## Installation
|
|
11
13
|
|
package/lib/database.js
CHANGED
|
@@ -312,7 +312,7 @@ class Database {
|
|
|
312
312
|
|
|
313
313
|
async begin() {
|
|
314
314
|
const txPtr = await this._beginAsync();
|
|
315
|
-
const tx = new Transaction(txPtr, this.#stoolap, this);
|
|
315
|
+
const tx = new Transaction(txPtr, this.#stoolap, this, this.#ptr);
|
|
316
316
|
this._trackChild(tx);
|
|
317
317
|
return tx;
|
|
318
318
|
}
|
|
@@ -320,7 +320,7 @@ class Database {
|
|
|
320
320
|
beginSync() {
|
|
321
321
|
this.#checkOpen();
|
|
322
322
|
const txPtr = this.#stoolap.txBegin(this.#ptr);
|
|
323
|
-
const tx = new Transaction(txPtr, this.#stoolap, this);
|
|
323
|
+
const tx = new Transaction(txPtr, this.#stoolap, this, this.#ptr);
|
|
324
324
|
this._trackChild(tx);
|
|
325
325
|
return tx;
|
|
326
326
|
}
|
package/lib/transaction.js
CHANGED
|
@@ -6,15 +6,17 @@ const { parseRows, parseRaw } = require("./parse");
|
|
|
6
6
|
class Transaction {
|
|
7
7
|
#ptr = null;
|
|
8
8
|
#stoolap = null;
|
|
9
|
+
#dbPtr = null;
|
|
9
10
|
#pendingAsync = 0;
|
|
10
11
|
#tail = Promise.resolve();
|
|
11
12
|
#closingPromise = null;
|
|
12
13
|
#owner = null;
|
|
13
14
|
|
|
14
|
-
constructor(ptr, stoolap, owner) {
|
|
15
|
+
constructor(ptr, stoolap, owner, dbPtr) {
|
|
15
16
|
this.#ptr = ptr;
|
|
16
17
|
this.#stoolap = stoolap;
|
|
17
18
|
this.#owner = owner || null;
|
|
19
|
+
this.#dbPtr = dbPtr || null;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
_invalidate() {
|
|
@@ -177,7 +179,7 @@ class Transaction {
|
|
|
177
179
|
executeBatchSync(sql, paramsArray) {
|
|
178
180
|
this.#checkSyncReady();
|
|
179
181
|
if (paramsArray.length > 0 && Array.isArray(paramsArray[0])) {
|
|
180
|
-
return this.#stoolap.txExecBatch(this.#ptr, sql, paramsArray);
|
|
182
|
+
return this.#stoolap.txExecBatch(this.#dbPtr, this.#ptr, sql, paramsArray);
|
|
181
183
|
}
|
|
182
184
|
let totalChanges = 0;
|
|
183
185
|
for (const params of paramsArray) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stoolap/node",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "High-performance Node.js driver for Stoolap embedded SQL database",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -13,15 +13,16 @@
|
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
15
|
"install": "node-gyp rebuild",
|
|
16
|
+
"build": "node-gyp rebuild",
|
|
16
17
|
"test": "node --test __test__/index.spec.mjs",
|
|
17
18
|
"bench": "node benchmark.mjs"
|
|
18
19
|
},
|
|
19
20
|
"optionalDependencies": {
|
|
20
|
-
"@stoolap/lib-darwin-arm64": "0.3.
|
|
21
|
-
"@stoolap/lib-darwin-x64": "0.3.
|
|
22
|
-
"@stoolap/lib-linux-arm64-gnu": "0.3.
|
|
23
|
-
"@stoolap/lib-linux-x64-gnu": "0.3.
|
|
24
|
-
"@stoolap/lib-win32-x64-msvc": "0.3.
|
|
21
|
+
"@stoolap/lib-darwin-arm64": "0.3.5",
|
|
22
|
+
"@stoolap/lib-darwin-x64": "0.3.5",
|
|
23
|
+
"@stoolap/lib-linux-arm64-gnu": "0.3.5",
|
|
24
|
+
"@stoolap/lib-linux-x64-gnu": "0.3.5",
|
|
25
|
+
"@stoolap/lib-win32-x64-msvc": "0.3.5"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"better-sqlite3": "^12.6.2",
|
package/src/stoolap.c
CHANGED
|
@@ -85,6 +85,8 @@ typedef int32_t (*fn_tx_exec)(StoolapTx*, const char*, int64_t*);
|
|
|
85
85
|
typedef int32_t (*fn_tx_exec_p)(StoolapTx*, const char*, const StoolapValue*, int32_t, int64_t*);
|
|
86
86
|
typedef int32_t (*fn_tx_query)(StoolapTx*, const char*, StoolapRows**);
|
|
87
87
|
typedef int32_t (*fn_tx_query_p)(StoolapTx*, const char*, const StoolapValue*, int32_t, StoolapRows**);
|
|
88
|
+
typedef int32_t (*fn_tx_stmt_exec)(StoolapTx*, StoolapStmt*, const StoolapValue*, int32_t, int64_t*);
|
|
89
|
+
typedef int32_t (*fn_tx_stmt_query)(StoolapTx*, StoolapStmt*, const StoolapValue*, int32_t, StoolapRows**);
|
|
88
90
|
typedef int32_t (*fn_tx_commit)(StoolapTx*);
|
|
89
91
|
typedef int32_t (*fn_tx_rollback)(StoolapTx*);
|
|
90
92
|
typedef const char* (*fn_tx_errmsg)(const StoolapTx*);
|
|
@@ -127,6 +129,8 @@ static struct {
|
|
|
127
129
|
fn_tx_exec_p tx_exec_p;
|
|
128
130
|
fn_tx_query tx_query;
|
|
129
131
|
fn_tx_query_p tx_query_p;
|
|
132
|
+
fn_tx_stmt_exec tx_stmt_exec;
|
|
133
|
+
fn_tx_stmt_query tx_stmt_query;
|
|
130
134
|
fn_tx_commit tx_commit;
|
|
131
135
|
fn_tx_rollback tx_rollback;
|
|
132
136
|
fn_tx_errmsg tx_errmsg;
|
|
@@ -1523,6 +1527,10 @@ static napi_value fn_load_library(napi_env env, napi_callback_info info) {
|
|
|
1523
1527
|
LOAD(tx_exec_p, "stoolap_tx_exec_params");
|
|
1524
1528
|
LOAD(tx_query, "stoolap_tx_query");
|
|
1525
1529
|
LOAD(tx_query_p, "stoolap_tx_query_params");
|
|
1530
|
+
/* Optional symbols — not in all engine versions */
|
|
1531
|
+
S.tx_stmt_exec = (fn_tx_stmt_exec) DLSYM(lib_handle, "stoolap_tx_stmt_exec");
|
|
1532
|
+
S.tx_stmt_query = (fn_tx_stmt_query)DLSYM(lib_handle, "stoolap_tx_stmt_query");
|
|
1533
|
+
|
|
1526
1534
|
LOAD(tx_commit, "stoolap_tx_commit");
|
|
1527
1535
|
LOAD(tx_rollback, "stoolap_tx_rollback");
|
|
1528
1536
|
LOAD(tx_errmsg, "stoolap_tx_errmsg");
|
|
@@ -2948,22 +2956,37 @@ static napi_value wrap_tx_rollback_async(napi_env env, napi_callback_info info)
|
|
|
2948
2956
|
* Batch exec in C — copies SQL once, pre-allocates param buffers,
|
|
2949
2957
|
* loops param sets in C. Eliminates N × JS↔C crossings + N×malloc/free. */
|
|
2950
2958
|
static napi_value wrap_tx_exec_batch(napi_env env, napi_callback_info info) {
|
|
2951
|
-
size_t argc =
|
|
2952
|
-
napi_value argv[
|
|
2959
|
+
size_t argc = 4;
|
|
2960
|
+
napi_value argv[4];
|
|
2953
2961
|
napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
|
|
2954
2962
|
|
|
2963
|
+
StoolapDB* db;
|
|
2964
|
+
napi_get_value_external(env, argv[0], (void**)&db);
|
|
2965
|
+
|
|
2955
2966
|
StoolapTx* tx;
|
|
2956
|
-
napi_get_value_external(env, argv[
|
|
2967
|
+
napi_get_value_external(env, argv[1], (void**)&tx);
|
|
2957
2968
|
|
|
2958
|
-
GET_SQL_STRING(env, argv[
|
|
2969
|
+
GET_SQL_STRING(env, argv[2], sql);
|
|
2959
2970
|
|
|
2960
2971
|
uint32_t batch_len;
|
|
2961
|
-
napi_get_array_length(env, argv[
|
|
2972
|
+
napi_get_array_length(env, argv[3], &batch_len);
|
|
2962
2973
|
if (batch_len == 0) return make_changes(env, 0);
|
|
2963
2974
|
|
|
2975
|
+
/* Prepare statement once if tx_stmt_exec is available */
|
|
2976
|
+
StoolapStmt* stmt = NULL;
|
|
2977
|
+
int use_stmt = (S.tx_stmt_exec != NULL);
|
|
2978
|
+
int32_t rc;
|
|
2979
|
+
if (use_stmt) {
|
|
2980
|
+
rc = S.prepare(db, sql, &stmt);
|
|
2981
|
+
if (rc != STOOLAP_OK) {
|
|
2982
|
+
const char* msg = S.errmsg(db);
|
|
2983
|
+
THROW(env, msg ? msg : "Prepare error");
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2964
2987
|
/* Get param count from first element — pre-allocate ONCE */
|
|
2965
2988
|
napi_value first_arr;
|
|
2966
|
-
napi_get_element(env, argv[
|
|
2989
|
+
napi_get_element(env, argv[3], 0, &first_arr);
|
|
2967
2990
|
uint32_t param_count;
|
|
2968
2991
|
napi_get_array_length(env, first_arr, ¶m_count);
|
|
2969
2992
|
|
|
@@ -2974,7 +2997,7 @@ static napi_value wrap_tx_exec_batch(napi_env env, napi_callback_info info) {
|
|
|
2974
2997
|
|
|
2975
2998
|
for (uint32_t i = 0; i < batch_len; i++) {
|
|
2976
2999
|
napi_value params_arr;
|
|
2977
|
-
napi_get_element(env, argv[
|
|
3000
|
+
napi_get_element(env, argv[3], i, ¶ms_arr);
|
|
2978
3001
|
|
|
2979
3002
|
/* Convert params into pre-allocated buffers */
|
|
2980
3003
|
int tbuf_cnt = 0;
|
|
@@ -2982,15 +3005,19 @@ static napi_value wrap_tx_exec_batch(napi_env env, napi_callback_info info) {
|
|
|
2982
3005
|
napi_value elem;
|
|
2983
3006
|
napi_get_element(env, params_arr, j, &elem);
|
|
2984
3007
|
if (js_to_value(env, elem, &vals[j], tbufs, &tbuf_cnt) != 0) {
|
|
2985
|
-
/* Cleanup on error */
|
|
2986
3008
|
for (int k = 0; k < tbuf_cnt; k++) free(tbufs[k]);
|
|
2987
3009
|
free(vals); free(tbufs);
|
|
3010
|
+
if (stmt) S.stmt_finalize(stmt);
|
|
2988
3011
|
THROW(env, "Failed to convert parameters");
|
|
2989
3012
|
}
|
|
2990
3013
|
}
|
|
2991
3014
|
|
|
2992
3015
|
int64_t affected = 0;
|
|
2993
|
-
|
|
3016
|
+
if (use_stmt) {
|
|
3017
|
+
rc = S.tx_stmt_exec(tx, stmt, vals, (int32_t)param_count, &affected);
|
|
3018
|
+
} else {
|
|
3019
|
+
rc = S.tx_exec_p(tx, sql, vals, (int32_t)param_count, &affected);
|
|
3020
|
+
}
|
|
2994
3021
|
|
|
2995
3022
|
/* Free only text buffers, keep vals/tbufs arrays for reuse */
|
|
2996
3023
|
for (int k = 0; k < tbuf_cnt; k++) { free(tbufs[k]); tbufs[k] = NULL; }
|
|
@@ -2998,6 +3025,7 @@ static napi_value wrap_tx_exec_batch(napi_env env, napi_callback_info info) {
|
|
|
2998
3025
|
if (rc != STOOLAP_OK) {
|
|
2999
3026
|
free(vals); free(tbufs);
|
|
3000
3027
|
const char* msg = S.tx_errmsg(tx);
|
|
3028
|
+
if (stmt) S.stmt_finalize(stmt);
|
|
3001
3029
|
THROW(env, msg ? msg : "Transaction batch exec error");
|
|
3002
3030
|
}
|
|
3003
3031
|
|
|
@@ -3006,6 +3034,7 @@ static napi_value wrap_tx_exec_batch(napi_env env, napi_callback_info info) {
|
|
|
3006
3034
|
|
|
3007
3035
|
free(vals);
|
|
3008
3036
|
free(tbufs);
|
|
3037
|
+
if (stmt) S.stmt_finalize(stmt);
|
|
3009
3038
|
return make_changes(env, total_affected);
|
|
3010
3039
|
}
|
|
3011
3040
|
|
|
@@ -3170,21 +3199,28 @@ static napi_value wrap_db_exec_batch_buf(napi_env env, napi_callback_info info)
|
|
|
3170
3199
|
int32_t rc = S.begin(db, &tx);
|
|
3171
3200
|
if (rc != STOOLAP_OK) { const char* msg = S.errmsg(db); THROW(env, msg ? msg : "Begin error"); }
|
|
3172
3201
|
StoolapStmt* stmt = NULL;
|
|
3173
|
-
|
|
3174
|
-
if (
|
|
3202
|
+
int use_stmt = (S.tx_stmt_exec != NULL);
|
|
3203
|
+
if (use_stmt) {
|
|
3204
|
+
rc = S.prepare(db, sql, &stmt);
|
|
3205
|
+
if (rc != STOOLAP_OK) { S.tx_rollback(tx); const char* msg = S.errmsg(db); THROW(env, msg ? msg : "Prepare error"); }
|
|
3206
|
+
}
|
|
3175
3207
|
int64_t total = 0;
|
|
3176
3208
|
for (uint32_t i = 0; i < row_count; i++) {
|
|
3177
3209
|
StoolapValue vals[MAX_STACK_PARAMS];
|
|
3178
3210
|
size_t consumed = 0;
|
|
3179
3211
|
int decoded = decode_params_buf(ptr, (size_t)(end - ptr), vals, ppr, &consumed);
|
|
3180
|
-
if (decoded != ppr) { S.stmt_finalize(stmt); S.tx_rollback(tx); THROW(env, "Batch param decode error"); }
|
|
3212
|
+
if (decoded != ppr) { if (stmt) S.stmt_finalize(stmt); S.tx_rollback(tx); THROW(env, "Batch param decode error"); }
|
|
3181
3213
|
ptr += consumed;
|
|
3182
3214
|
int64_t affected = 0;
|
|
3183
|
-
|
|
3184
|
-
|
|
3215
|
+
if (use_stmt) {
|
|
3216
|
+
rc = S.tx_stmt_exec(tx, stmt, vals, decoded, &affected);
|
|
3217
|
+
} else {
|
|
3218
|
+
rc = S.tx_exec_p(tx, sql, vals, decoded, &affected);
|
|
3219
|
+
}
|
|
3220
|
+
if (rc != STOOLAP_OK) { const char* msg = S.tx_errmsg(tx); if (stmt) S.stmt_finalize(stmt); S.tx_rollback(tx); THROW(env, msg ? msg : "Batch exec error"); }
|
|
3185
3221
|
total += affected;
|
|
3186
3222
|
}
|
|
3187
|
-
S.stmt_finalize(stmt);
|
|
3223
|
+
if (stmt) S.stmt_finalize(stmt);
|
|
3188
3224
|
rc = S.tx_commit(tx);
|
|
3189
3225
|
if (rc != STOOLAP_OK) { const char* msg = S.errmsg(db); THROW(env, msg ? msg : "Commit error"); }
|
|
3190
3226
|
return make_changes(env, total);
|