Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sqlite: support TypedArray and DataView in StatementSync #56385

Merged
merged 1 commit into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions doc/api/sqlite.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,11 +322,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
himself65 marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -354,11 +358,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 @@ -374,11 +382,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 @@ -393,11 +405,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 @@ -930,7 +930,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 @@ -1035,7 +1035,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()) {
himself65 marked this conversation as resolved.
Show resolved Hide resolved
} 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));
}
});
}
});
Loading