@stoolap/node 0.5.0-beta.2 → 0.5.0-beta.4
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 +1 -1
- package/lib/ffi.js +4 -2
- package/lib/parse.js +33 -1
- package/lib/statement.js +7 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -402,7 +402,7 @@ db.querySync(
|
|
|
402
402
|
);
|
|
403
403
|
```
|
|
404
404
|
|
|
405
|
-
Synchronous ad hoc statements pass named parameters to the engine as they are: the SQL is not rewritten, a `:name` inside a string literal is left alone, a name used twice is bound once, keys the SQL does not mention are ignored and a name the object lacks
|
|
405
|
+
Synchronous ad hoc statements pass named parameters to the engine as they are: the SQL is not rewritten, a `:name` inside a string literal is left alone, a name used twice is bound once, keys the SQL does not mention are ignored and a name the object lacks is an error. A prepared statement, and the asynchronous ad hoc methods, resolve `:name` placeholders in the driver and bind by position, which is the engine's fastest path.
|
|
406
406
|
|
|
407
407
|
### Error Handling
|
|
408
408
|
|
package/lib/ffi.js
CHANGED
|
@@ -163,8 +163,10 @@ function processParams(sql, params) {
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
/* Rewrite :name placeholders to $n for a prepared statement. The engine binds
|
|
166
|
-
* prepared statements faster by position than by name
|
|
167
|
-
*
|
|
166
|
+
* prepared statements faster by position than by name (+10% on a point lookup
|
|
167
|
+
* since the engine's slot binding, +40% before), so a statement keeps its
|
|
168
|
+
* parameter names and binds an object's values positionally. Like the engine,
|
|
169
|
+
* it refuses an object that lacks one of the names. */
|
|
168
170
|
function rewriteNamedParams(sql) {
|
|
169
171
|
const seen = new Map();
|
|
170
172
|
const names = [];
|
package/lib/parse.js
CHANGED
|
@@ -13,6 +13,35 @@ const td = new TextDecoder();
|
|
|
13
13
|
|
|
14
14
|
let _off = 0;
|
|
15
15
|
|
|
16
|
+
/* Short ASCII strings are cut from a latin1 decode of an 8 KB block of the
|
|
17
|
+
* buffer instead of one Buffer.toString call per value: latin1 maps bytes to
|
|
18
|
+
* chars one to one, so offsets hold, and String.prototype.substring is a pure
|
|
19
|
+
* V8 operation (~10 ns against ~40 ns for toString). Measured crossover is
|
|
20
|
+
* about 40 bytes; longer values and any value with a byte >= 0x80 take the
|
|
21
|
+
* utf8 path. The block is bounded so a kept string pins at most 8 KB. */
|
|
22
|
+
const ASCII_FAST_MAX = 32;
|
|
23
|
+
const BLOCK_SIZE = 8192;
|
|
24
|
+
let _blk = "";
|
|
25
|
+
let _blkStart = -1;
|
|
26
|
+
let _blkEnd = -1;
|
|
27
|
+
|
|
28
|
+
function readText(bytes, nb, start, len) {
|
|
29
|
+
const end = start + len;
|
|
30
|
+
if (len <= ASCII_FAST_MAX) {
|
|
31
|
+
let k = start;
|
|
32
|
+
while (k < end && bytes[k] < 128) k++;
|
|
33
|
+
if (k === end) {
|
|
34
|
+
if (start < _blkStart || end > _blkEnd) {
|
|
35
|
+
_blkStart = start;
|
|
36
|
+
_blkEnd = Math.max(end, Math.min(bytes.length, start + BLOCK_SIZE));
|
|
37
|
+
_blk = nb.toString("latin1", _blkStart, _blkEnd);
|
|
38
|
+
}
|
|
39
|
+
return _blk.substring(start - _blkStart, end - _blkStart);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return nb.toString("utf8", start, end);
|
|
43
|
+
}
|
|
44
|
+
|
|
16
45
|
function readVal(bytes, dv, nb) {
|
|
17
46
|
const tag = bytes[_off++];
|
|
18
47
|
switch (tag) {
|
|
@@ -39,7 +68,7 @@ function readVal(bytes, dv, nb) {
|
|
|
39
68
|
const start = _off;
|
|
40
69
|
_off += len;
|
|
41
70
|
return nb
|
|
42
|
-
?
|
|
71
|
+
? readText(bytes, nb, start, len)
|
|
43
72
|
: td.decode(
|
|
44
73
|
new Uint8Array(bytes.buffer, bytes.byteOffset + start, len),
|
|
45
74
|
);
|
|
@@ -75,6 +104,7 @@ function parseRows(abuf) {
|
|
|
75
104
|
const nb = _hasBuffer ? Buffer.from(abuf) : null;
|
|
76
105
|
|
|
77
106
|
_off = 0;
|
|
107
|
+
_blkEnd = -1;
|
|
78
108
|
const colCount = dv.getUint32(0, true);
|
|
79
109
|
_off = 4;
|
|
80
110
|
const colNames = new Array(colCount);
|
|
@@ -107,6 +137,7 @@ function parseRaw(abuf) {
|
|
|
107
137
|
const nb = _hasBuffer ? Buffer.from(abuf) : null;
|
|
108
138
|
|
|
109
139
|
_off = 0;
|
|
140
|
+
_blkEnd = -1;
|
|
110
141
|
const colCount = dv.getUint32(0, true);
|
|
111
142
|
_off = 4;
|
|
112
143
|
const colNames = new Array(colCount);
|
|
@@ -176,6 +207,7 @@ function parseRowsCached(abuf, headerOff, factory, colCount) {
|
|
|
176
207
|
const dv = new DataView(abuf);
|
|
177
208
|
const nb = _hasBuffer ? Buffer.from(abuf) : null;
|
|
178
209
|
_off = headerOff;
|
|
210
|
+
_blkEnd = -1;
|
|
179
211
|
const rowCount = dv.getUint32(_off, true);
|
|
180
212
|
_off += 4;
|
|
181
213
|
const results = new Array(rowCount);
|
package/lib/statement.js
CHANGED
|
@@ -273,7 +273,13 @@ class PreparedStatement {
|
|
|
273
273
|
const names = this.#paramNames;
|
|
274
274
|
if (!names) return null;
|
|
275
275
|
const values = new Array(names.length);
|
|
276
|
-
for (let i = 0; i < names.length; i++)
|
|
276
|
+
for (let i = 0; i < names.length; i++) {
|
|
277
|
+
const name = names[i];
|
|
278
|
+
if (!(name in params)) {
|
|
279
|
+
throw new Error(`invalid argument: named parameter :${name} has no value`);
|
|
280
|
+
}
|
|
281
|
+
values[i] = params[name];
|
|
282
|
+
}
|
|
277
283
|
return values;
|
|
278
284
|
}
|
|
279
285
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stoolap/node",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.4",
|
|
4
4
|
"description": "High-performance Node.js driver for Stoolap embedded SQL database",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"bench": "node benchmark.mjs"
|
|
19
19
|
},
|
|
20
20
|
"optionalDependencies": {
|
|
21
|
-
"@stoolap/lib-darwin-arm64": "0.5.0-beta.
|
|
22
|
-
"@stoolap/lib-darwin-x64": "0.5.0-beta.
|
|
23
|
-
"@stoolap/lib-linux-arm64-gnu": "0.5.0-beta.
|
|
24
|
-
"@stoolap/lib-linux-x64-gnu": "0.5.0-beta.
|
|
25
|
-
"@stoolap/lib-win32-x64-msvc": "0.5.0-beta.
|
|
21
|
+
"@stoolap/lib-darwin-arm64": "0.5.0-beta.4",
|
|
22
|
+
"@stoolap/lib-darwin-x64": "0.5.0-beta.4",
|
|
23
|
+
"@stoolap/lib-linux-arm64-gnu": "0.5.0-beta.4",
|
|
24
|
+
"@stoolap/lib-linux-x64-gnu": "0.5.0-beta.4",
|
|
25
|
+
"@stoolap/lib-win32-x64-msvc": "0.5.0-beta.4"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"better-sqlite3": "^12.6.2",
|