Skip to content

Commit

Permalink
sqlite: support TypedArray and DataView in StatementSync
Browse files Browse the repository at this point in the history
Co-authored-by: Antoine du Hamel <[email protected]>
PR-URL: #56385
Fixes: #56384
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
  • Loading branch information
himself65 and aduh95 authored Jan 5, 2025
1 parent 383e1a2 commit 08b7d38
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 6 deletions.
24 changes: 20 additions & 4 deletions doc/api/sqlite.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,11 +339,15 @@ over hand-crafted SQL strings when handling user input.

<!-- YAML
added: v22.5.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/56385
description: Add support for `DataView` and typed array objects for `anonymousParameters`.
-->

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

<!-- YAML
added: v22.5.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/56385
description: Add support for `DataView` and typed array objects for `anonymousParameters`.
-->

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

<!-- YAML
added: v23.4.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/56385
description: Add support for `DataView` and typed array objects for `anonymousParameters`.
-->

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

<!-- YAML
added: v22.5.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/56385
description: Add support for `DataView` and typed array objects for `anonymousParameters`.
-->

* `namedParameters` {Object} An optional object used to bind named parameters.
The keys of this object are used to configure the mapping.
* `...anonymousParameters` {null|number|bigint|string|Buffer|Uint8Array} Zero or
* `...anonymousParameters` {null|number|bigint|string|Buffer|TypedArray|DataView} Zero or
more values to bind to anonymous parameters.
* Returns: {Object}
* `changes`: {number|bigint} The number of rows modified, inserted, or deleted
Expand Down
4 changes: 2 additions & 2 deletions src/node_sqlite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,7 @@ bool StatementSync::BindParams(const FunctionCallbackInfo<Value>& args) {
int anon_idx = 1;
int anon_start = 0;

if (args[0]->IsObject() && !args[0]->IsUint8Array()) {
if (args[0]->IsObject() && !args[0]->IsArrayBufferView()) {
Local<Object> obj = args[0].As<Object>();
Local<Context> context = obj->GetIsolate()->GetCurrentContext();
Local<Array> keys;
Expand Down Expand Up @@ -1065,7 +1065,7 @@ bool StatementSync::BindValue(const Local<Value>& value, const int index) {
statement_, index, *val, val.length(), SQLITE_TRANSIENT);
} else if (value->IsNull()) {
r = sqlite3_bind_null(statement_, index);
} else if (value->IsUint8Array()) {
} else if (value->IsArrayBufferView()) {
ArrayBufferViewContents<uint8_t> buf(value);
r = sqlite3_bind_blob(
statement_, index, buf.data(), buf.length(), SQLITE_TRANSIENT);
Expand Down
61 changes: 61 additions & 0 deletions test/parallel/test-sqlite-typed-array-and-data-view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use strict';
require('../common');
const tmpdir = require('../common/tmpdir');
const { join } = require('node:path');
const { DatabaseSync } = require('node:sqlite');
const { suite, test } = require('node:test');
let cnt = 0;

tmpdir.refresh();

function nextDb() {
return join(tmpdir.path, `database-${cnt++}.db`);
}

const arrayBuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]).buffer;
const TypedArrays = [
['Int8Array', Int8Array],
['Uint8Array', Uint8Array],
['Uint8ClampedArray', Uint8ClampedArray],
['Int16Array', Int16Array],
['Uint16Array', Uint16Array],
['Int32Array', Int32Array],
['Uint32Array', Uint32Array],
['Float32Array', Float32Array],
['Float64Array', Float64Array],
['BigInt64Array', BigInt64Array],
['BigUint64Array', BigUint64Array],
['DataView', DataView],
];

suite('StatementSync with TypedArray/DataView', () => {
for (const [displayName, TypedArray] of TypedArrays) {
test(displayName, (t) => {
const db = new DatabaseSync(nextDb());
t.after(() => { db.close(); });
db.exec('CREATE TABLE test (data BLOB)');
// insert
{
const stmt = db.prepare('INSERT INTO test VALUES (?)');
stmt.run(new TypedArray(arrayBuffer));
}
// select all
{
const stmt = db.prepare('SELECT * FROM test');
const row = stmt.get();
t.assert.ok(row.data instanceof Uint8Array);
t.assert.strictEqual(row.data.length, 8);
t.assert.deepStrictEqual(row.data, new Uint8Array(arrayBuffer));
}
// query
{
const stmt = db.prepare('SELECT * FROM test WHERE data = ?');
const rows = stmt.all(new TypedArray(arrayBuffer));
t.assert.strictEqual(rows.length, 1);
t.assert.ok(rows[0].data instanceof Uint8Array);
t.assert.strictEqual(rows[0].data.length, 8);
t.assert.deepStrictEqual(rows[0].data, new Uint8Array(arrayBuffer));
}
});
}
});

0 comments on commit 08b7d38

Please sign in to comment.