Skip to content

Commit 46c1763

Browse files
himself65aduh95
andcommitted
sqlite: support TypedArray and DataView in StatementSync
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent ca3c8f1 commit 46c1763

File tree

3 files changed

+83
-6
lines changed

3 files changed

+83
-6
lines changed

doc/api/sqlite.md

+20-4
Original file line numberDiff line numberDiff line change
@@ -322,11 +322,15 @@ over hand-crafted SQL strings when handling user input.
322322

323323
<!-- YAML
324324
added: v22.5.0
325+
changes:
326+
- version: REPLACEME
327+
pr-url: https://github.com/nodejs/node/pull/56385
328+
description: Add support for `DataView` and typed array objects for `anonymousParameters`.
325329
-->
326330

327331
* `namedParameters` {Object} An optional object used to bind named parameters.
328332
The keys of this object are used to configure the mapping.
329-
* `...anonymousParameters` {null|number|bigint|string|Buffer|Uint8Array} Zero or
333+
* `...anonymousParameters` {null|number|bigint|string|Buffer|TypedArray|DataView} Zero or
330334
more values to bind to anonymous parameters.
331335
* Returns: {Array} An array of objects. Each object corresponds to a row
332336
returned by executing the prepared statement. The keys and values of each
@@ -354,11 +358,15 @@ execution of this prepared statement. This property is a wrapper around
354358

355359
<!-- YAML
356360
added: v22.5.0
361+
changes:
362+
- version: REPLACEME
363+
pr-url: https://github.com/nodejs/node/pull/56385
364+
description: Add support for `DataView` and typed array objects for `anonymousParameters`.
357365
-->
358366

359367
* `namedParameters` {Object} An optional object used to bind named parameters.
360368
The keys of this object are used to configure the mapping.
361-
* `...anonymousParameters` {null|number|bigint|string|Buffer|Uint8Array} Zero or
369+
* `...anonymousParameters` {null|number|bigint|string|Buffer|TypedArray|DataView} Zero or
362370
more values to bind to anonymous parameters.
363371
* Returns: {Object|undefined} An object corresponding to the first row returned
364372
by executing the prepared statement. The keys and values of the object
@@ -374,11 +382,15 @@ values in `namedParameters` and `anonymousParameters`.
374382

375383
<!-- YAML
376384
added: v23.4.0
385+
changes:
386+
- version: REPLACEME
387+
pr-url: https://github.com/nodejs/node/pull/56385
388+
description: Add support for `DataView` and typed array objects for `anonymousParameters`.
377389
-->
378390

379391
* `namedParameters` {Object} An optional object used to bind named parameters.
380392
The keys of this object are used to configure the mapping.
381-
* `...anonymousParameters` {null|number|bigint|string|Buffer|Uint8Array} Zero or
393+
* `...anonymousParameters` {null|number|bigint|string|Buffer|TypedArray|DataView} Zero or
382394
more values to bind to anonymous parameters.
383395
* Returns: {Iterator} An iterable iterator of objects. Each object corresponds to a row
384396
returned by executing the prepared statement. The keys and values of each
@@ -393,11 +405,15 @@ the values in `namedParameters` and `anonymousParameters`.
393405

394406
<!-- YAML
395407
added: v22.5.0
408+
changes:
409+
- version: REPLACEME
410+
pr-url: https://github.com/nodejs/node/pull/56385
411+
description: Add support for `DataView` and typed array objects for `anonymousParameters`.
396412
-->
397413

398414
* `namedParameters` {Object} An optional object used to bind named parameters.
399415
The keys of this object are used to configure the mapping.
400-
* `...anonymousParameters` {null|number|bigint|string|Buffer|Uint8Array} Zero or
416+
* `...anonymousParameters` {null|number|bigint|string|Buffer|TypedArray|DataView} Zero or
401417
more values to bind to anonymous parameters.
402418
* Returns: {Object}
403419
* `changes`: {number|bigint} The number of rows modified, inserted, or deleted

src/node_sqlite.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@ bool StatementSync::BindParams(const FunctionCallbackInfo<Value>& args) {
930930
int anon_idx = 1;
931931
int anon_start = 0;
932932

933-
if (args[0]->IsObject() && !args[0]->IsUint8Array()) {
933+
if (args[0]->IsObject() && !args[0]->IsArrayBufferView()) {
934934
Local<Object> obj = args[0].As<Object>();
935935
Local<Context> context = obj->GetIsolate()->GetCurrentContext();
936936
Local<Array> keys;
@@ -1035,7 +1035,7 @@ bool StatementSync::BindValue(const Local<Value>& value, const int index) {
10351035
statement_, index, *val, val.length(), SQLITE_TRANSIENT);
10361036
} else if (value->IsNull()) {
10371037
r = sqlite3_bind_null(statement_, index);
1038-
} else if (value->IsUint8Array()) {
1038+
} else if (value->IsArrayBufferView()) {
10391039
ArrayBufferViewContents<uint8_t> buf(value);
10401040
r = sqlite3_bind_blob(
10411041
statement_, index, buf.data(), buf.length(), SQLITE_TRANSIENT);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
'use strict';
2+
require('../common');
3+
const tmpdir = require('../common/tmpdir');
4+
const { join } = require('node:path');
5+
const { DatabaseSync } = require('node:sqlite');
6+
const { suite, test } = require('node:test');
7+
let cnt = 0;
8+
9+
tmpdir.refresh();
10+
11+
function nextDb() {
12+
return join(tmpdir.path, `database-${cnt++}.db`);
13+
}
14+
15+
const arrayBuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]).buffer;
16+
const TypedArrays = [
17+
['Int8Array', Int8Array],
18+
['Uint8Array', Uint8Array],
19+
['Uint8ClampedArray', Uint8ClampedArray],
20+
['Int16Array', Int16Array],
21+
['Uint16Array', Uint16Array],
22+
['Int32Array', Int32Array],
23+
['Uint32Array', Uint32Array],
24+
['Float32Array', Float32Array],
25+
['Float64Array', Float64Array],
26+
['BigInt64Array', BigInt64Array],
27+
['BigUint64Array', BigUint64Array],
28+
['DataView', DataView],
29+
];
30+
31+
suite('StatementSync with TypedArray/DataView', () => {
32+
for (const [displayName, TypedArray] of TypedArrays) {
33+
test(displayName, (t) => {
34+
const db = new DatabaseSync(nextDb());
35+
t.after(() => { db.close(); });
36+
db.exec('CREATE TABLE test (data BLOB)');
37+
// insert
38+
{
39+
const stmt = db.prepare('INSERT INTO test VALUES (?)');
40+
stmt.run(new TypedArray(arrayBuffer));
41+
}
42+
// select all
43+
{
44+
const stmt = db.prepare('SELECT * FROM test');
45+
const row = stmt.get();
46+
t.assert.ok(row.data instanceof Uint8Array);
47+
t.assert.strictEqual(row.data.length, 8);
48+
t.assert.deepStrictEqual(row.data, new Uint8Array(arrayBuffer));
49+
}
50+
// query
51+
{
52+
const stmt = db.prepare('SELECT * FROM test WHERE data = ?');
53+
const rows = stmt.all(new TypedArray(arrayBuffer));
54+
t.assert.strictEqual(rows.length, 1);
55+
t.assert.ok(rows[0].data instanceof Uint8Array);
56+
t.assert.strictEqual(rows[0].data.length, 8);
57+
t.assert.deepStrictEqual(rows[0].data, new Uint8Array(arrayBuffer));
58+
}
59+
});
60+
}
61+
});

0 commit comments

Comments
 (0)