@stoolap/node 0.3.3 → 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 +75 -39
- package/binding.gyp +31 -0
- package/index.d.ts +141 -128
- package/index.js +14 -584
- package/lib/database.js +367 -0
- package/lib/ffi.js +183 -0
- package/lib/parse.js +246 -0
- package/lib/statement.js +371 -0
- package/lib/transaction.js +248 -0
- package/package.json +16 -24
- package/src/stoolap.c +3322 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { processParams } = require("./ffi");
|
|
4
|
+
const { parseRows, parseRaw } = require("./parse");
|
|
5
|
+
|
|
6
|
+
class Transaction {
|
|
7
|
+
#ptr = null;
|
|
8
|
+
#stoolap = null;
|
|
9
|
+
#dbPtr = null;
|
|
10
|
+
#pendingAsync = 0;
|
|
11
|
+
#tail = Promise.resolve();
|
|
12
|
+
#closingPromise = null;
|
|
13
|
+
#owner = null;
|
|
14
|
+
|
|
15
|
+
constructor(ptr, stoolap, owner, dbPtr) {
|
|
16
|
+
this.#ptr = ptr;
|
|
17
|
+
this.#stoolap = stoolap;
|
|
18
|
+
this.#owner = owner || null;
|
|
19
|
+
this.#dbPtr = dbPtr || null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_invalidate() {
|
|
23
|
+
this.#ptr = null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#checkOpen() {
|
|
27
|
+
if (!this.#ptr) throw new Error("Transaction is closed");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#checkSyncReady() {
|
|
31
|
+
this.#checkOpen();
|
|
32
|
+
if (this.#closingPromise || this.#pendingAsync > 0) {
|
|
33
|
+
throw new Error("Transaction has pending async operations");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#enqueueAsync(operation) {
|
|
38
|
+
this.#checkOpen();
|
|
39
|
+
if (this.#closingPromise) throw new Error("Transaction is closing");
|
|
40
|
+
|
|
41
|
+
const ptr = this.#ptr;
|
|
42
|
+
const run = async () => {
|
|
43
|
+
this.#pendingAsync += 1;
|
|
44
|
+
try {
|
|
45
|
+
return await operation(ptr);
|
|
46
|
+
} finally {
|
|
47
|
+
this.#pendingAsync -= 1;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const promise = this.#tail.then(run, run);
|
|
52
|
+
this.#tail = promise.catch(() => {});
|
|
53
|
+
return promise;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// -- Execute --
|
|
57
|
+
|
|
58
|
+
async execute(sql, params) {
|
|
59
|
+
return this.#enqueueAsync((ptr) => {
|
|
60
|
+
if (!params) return this.#stoolap.txExecAsync(ptr, sql);
|
|
61
|
+
if (Array.isArray(params)) {
|
|
62
|
+
if (params.length === 0) return this.#stoolap.txExecAsync(ptr, sql);
|
|
63
|
+
return this.#stoolap.txExecAsync(ptr, sql, params);
|
|
64
|
+
}
|
|
65
|
+
const p = processParams(sql, params);
|
|
66
|
+
return p.values
|
|
67
|
+
? this.#stoolap.txExecAsync(ptr, p.sql, p.values)
|
|
68
|
+
: this.#stoolap.txExecAsync(ptr, sql);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
executeSync(sql, params) {
|
|
73
|
+
this.#checkSyncReady();
|
|
74
|
+
if (!params) return this.#stoolap.txExec(this.#ptr, sql);
|
|
75
|
+
if (Array.isArray(params)) {
|
|
76
|
+
if (params.length === 0) return this.#stoolap.txExec(this.#ptr, sql);
|
|
77
|
+
return this.#stoolap.txExec(this.#ptr, sql, params);
|
|
78
|
+
}
|
|
79
|
+
const p = processParams(sql, params);
|
|
80
|
+
return p.values
|
|
81
|
+
? this.#stoolap.txExec(this.#ptr, p.sql, p.values)
|
|
82
|
+
: this.#stoolap.txExec(this.#ptr, sql);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// -- Query --
|
|
86
|
+
|
|
87
|
+
async query(sql, params) {
|
|
88
|
+
const buf = await this.#enqueueAsync((ptr) => {
|
|
89
|
+
if (!params) return this.#stoolap.txQueryBufAsync(ptr, sql);
|
|
90
|
+
if (Array.isArray(params)) {
|
|
91
|
+
if (params.length === 0) return this.#stoolap.txQueryBufAsync(ptr, sql);
|
|
92
|
+
return this.#stoolap.txQueryBufAsync(ptr, sql, params);
|
|
93
|
+
}
|
|
94
|
+
const p = processParams(sql, params);
|
|
95
|
+
return p.values
|
|
96
|
+
? this.#stoolap.txQueryBufAsync(ptr, p.sql, p.values)
|
|
97
|
+
: this.#stoolap.txQueryBufAsync(ptr, sql);
|
|
98
|
+
});
|
|
99
|
+
return parseRows(buf);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
querySync(sql, params) {
|
|
103
|
+
this.#checkSyncReady();
|
|
104
|
+
let result;
|
|
105
|
+
if (!params) {
|
|
106
|
+
result = this.#stoolap.txQuery(this.#ptr, sql);
|
|
107
|
+
} else if (Array.isArray(params)) {
|
|
108
|
+
result =
|
|
109
|
+
params.length === 0
|
|
110
|
+
? this.#stoolap.txQuery(this.#ptr, sql)
|
|
111
|
+
: this.#stoolap.txQuery(this.#ptr, sql, params);
|
|
112
|
+
} else {
|
|
113
|
+
const p = processParams(sql, params);
|
|
114
|
+
result = p.values
|
|
115
|
+
? this.#stoolap.txQuery(this.#ptr, p.sql, p.values)
|
|
116
|
+
: this.#stoolap.txQuery(this.#ptr, sql);
|
|
117
|
+
}
|
|
118
|
+
return Array.isArray(result) ? result : parseRows(result);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// -- QueryOne --
|
|
122
|
+
|
|
123
|
+
async queryOne(sql, params) {
|
|
124
|
+
const rows = await this.query(sql, params);
|
|
125
|
+
return rows.length === 0 ? null : rows[0];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
queryOneSync(sql, params) {
|
|
129
|
+
this.#checkSyncReady();
|
|
130
|
+
if (!params) return this.#stoolap.txQueryOne(this.#ptr, sql);
|
|
131
|
+
if (Array.isArray(params)) {
|
|
132
|
+
if (params.length === 0) return this.#stoolap.txQueryOne(this.#ptr, sql);
|
|
133
|
+
return this.#stoolap.txQueryOne(this.#ptr, sql, params);
|
|
134
|
+
}
|
|
135
|
+
const p = processParams(sql, params);
|
|
136
|
+
return p.values
|
|
137
|
+
? this.#stoolap.txQueryOne(this.#ptr, p.sql, p.values)
|
|
138
|
+
: this.#stoolap.txQueryOne(this.#ptr, sql);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// -- QueryRaw --
|
|
142
|
+
|
|
143
|
+
async queryRaw(sql, params) {
|
|
144
|
+
const buf = await this.#enqueueAsync((ptr) => {
|
|
145
|
+
if (!params) return this.#stoolap.txQueryBufAsync(ptr, sql);
|
|
146
|
+
if (Array.isArray(params)) {
|
|
147
|
+
if (params.length === 0) return this.#stoolap.txQueryBufAsync(ptr, sql);
|
|
148
|
+
return this.#stoolap.txQueryBufAsync(ptr, sql, params);
|
|
149
|
+
}
|
|
150
|
+
const p = processParams(sql, params);
|
|
151
|
+
return p.values
|
|
152
|
+
? this.#stoolap.txQueryBufAsync(ptr, p.sql, p.values)
|
|
153
|
+
: this.#stoolap.txQueryBufAsync(ptr, sql);
|
|
154
|
+
});
|
|
155
|
+
return parseRaw(buf);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
queryRawSync(sql, params) {
|
|
159
|
+
this.#checkSyncReady();
|
|
160
|
+
let buf;
|
|
161
|
+
if (!params) {
|
|
162
|
+
buf = this.#stoolap.txQueryBuf(this.#ptr, sql);
|
|
163
|
+
} else if (Array.isArray(params)) {
|
|
164
|
+
buf =
|
|
165
|
+
params.length === 0
|
|
166
|
+
? this.#stoolap.txQueryBuf(this.#ptr, sql)
|
|
167
|
+
: this.#stoolap.txQueryBuf(this.#ptr, sql, params);
|
|
168
|
+
} else {
|
|
169
|
+
const p = processParams(sql, params);
|
|
170
|
+
buf = p.values
|
|
171
|
+
? this.#stoolap.txQueryBuf(this.#ptr, p.sql, p.values)
|
|
172
|
+
: this.#stoolap.txQueryBuf(this.#ptr, sql);
|
|
173
|
+
}
|
|
174
|
+
return parseRaw(buf);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// -- Batch --
|
|
178
|
+
|
|
179
|
+
executeBatchSync(sql, paramsArray) {
|
|
180
|
+
this.#checkSyncReady();
|
|
181
|
+
if (paramsArray.length > 0 && Array.isArray(paramsArray[0])) {
|
|
182
|
+
return this.#stoolap.txExecBatch(this.#dbPtr, this.#ptr, sql, paramsArray);
|
|
183
|
+
}
|
|
184
|
+
let totalChanges = 0;
|
|
185
|
+
for (const params of paramsArray) {
|
|
186
|
+
const p = processParams(sql, params);
|
|
187
|
+
const result = p.values
|
|
188
|
+
? this.#stoolap.txExec(this.#ptr, p.sql, p.values)
|
|
189
|
+
: this.#stoolap.txExec(this.#ptr, sql);
|
|
190
|
+
totalChanges += result.changes;
|
|
191
|
+
}
|
|
192
|
+
return { changes: totalChanges };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// -- Commit / Rollback --
|
|
196
|
+
|
|
197
|
+
async commit() {
|
|
198
|
+
this.#checkOpen();
|
|
199
|
+
if (this.#closingPromise) return this.#closingPromise;
|
|
200
|
+
|
|
201
|
+
const ptr = this.#ptr;
|
|
202
|
+
this.#closingPromise = this.#tail
|
|
203
|
+
.then(() => this.#stoolap.txCommitAsync(ptr))
|
|
204
|
+
.finally(() => {
|
|
205
|
+
this.#ptr = null;
|
|
206
|
+
this.#closingPromise = null;
|
|
207
|
+
if (this.#owner) this.#owner._untrackChild(this);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
this.#tail = this.#closingPromise.catch(() => {});
|
|
211
|
+
return this.#closingPromise;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
commitSync() {
|
|
215
|
+
this.#checkSyncReady();
|
|
216
|
+
const ptr = this.#ptr;
|
|
217
|
+
this.#ptr = null;
|
|
218
|
+
this.#stoolap.txCommit(ptr);
|
|
219
|
+
if (this.#owner) this.#owner._untrackChild(this);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async rollback() {
|
|
223
|
+
this.#checkOpen();
|
|
224
|
+
if (this.#closingPromise) return this.#closingPromise;
|
|
225
|
+
|
|
226
|
+
const ptr = this.#ptr;
|
|
227
|
+
this.#closingPromise = this.#tail
|
|
228
|
+
.then(() => this.#stoolap.txRollbackAsync(ptr))
|
|
229
|
+
.finally(() => {
|
|
230
|
+
this.#ptr = null;
|
|
231
|
+
this.#closingPromise = null;
|
|
232
|
+
if (this.#owner) this.#owner._untrackChild(this);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
this.#tail = this.#closingPromise.catch(() => {});
|
|
236
|
+
return this.#closingPromise;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
rollbackSync() {
|
|
240
|
+
this.#checkSyncReady();
|
|
241
|
+
const ptr = this.#ptr;
|
|
242
|
+
this.#ptr = null;
|
|
243
|
+
this.#stoolap.txRollback(ptr);
|
|
244
|
+
if (this.#owner) this.#owner._untrackChild(this);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
module.exports = { Transaction };
|
package/package.json
CHANGED
|
@@ -1,42 +1,35 @@
|
|
|
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",
|
|
7
|
-
"napi": {
|
|
8
|
-
"binaryName": "stoolap",
|
|
9
|
-
"targets": [
|
|
10
|
-
"aarch64-apple-darwin",
|
|
11
|
-
"x86_64-apple-darwin",
|
|
12
|
-
"x86_64-unknown-linux-gnu",
|
|
13
|
-
"aarch64-unknown-linux-gnu",
|
|
14
|
-
"x86_64-pc-windows-msvc"
|
|
15
|
-
]
|
|
16
|
-
},
|
|
17
7
|
"files": [
|
|
18
8
|
"index.js",
|
|
19
|
-
"index.d.ts"
|
|
9
|
+
"index.d.ts",
|
|
10
|
+
"lib/",
|
|
11
|
+
"src/stoolap.c",
|
|
12
|
+
"binding.gyp"
|
|
20
13
|
],
|
|
21
14
|
"scripts": {
|
|
22
|
-
"
|
|
23
|
-
"build
|
|
15
|
+
"install": "node-gyp rebuild",
|
|
16
|
+
"build": "node-gyp rebuild",
|
|
24
17
|
"test": "node --test __test__/index.spec.mjs",
|
|
25
|
-
"
|
|
18
|
+
"bench": "node benchmark.mjs"
|
|
26
19
|
},
|
|
27
20
|
"optionalDependencies": {
|
|
28
|
-
"@stoolap/
|
|
29
|
-
"@stoolap/
|
|
30
|
-
"@stoolap/
|
|
31
|
-
"@stoolap/
|
|
32
|
-
"@stoolap/
|
|
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"
|
|
33
26
|
},
|
|
34
27
|
"devDependencies": {
|
|
35
|
-
"
|
|
36
|
-
"
|
|
28
|
+
"better-sqlite3": "^12.6.2",
|
|
29
|
+
"node-gyp": "^11.2.0"
|
|
37
30
|
},
|
|
38
31
|
"engines": {
|
|
39
|
-
"node": ">=
|
|
32
|
+
"node": ">= 18"
|
|
40
33
|
},
|
|
41
34
|
"license": "Apache-2.0",
|
|
42
35
|
"repository": {
|
|
@@ -54,7 +47,6 @@
|
|
|
54
47
|
"mvcc",
|
|
55
48
|
"acid",
|
|
56
49
|
"stoolap",
|
|
57
|
-
"napi",
|
|
58
50
|
"native"
|
|
59
51
|
]
|
|
60
52
|
}
|