From 62acd4888c9bfd93898f044cbd76ebffefae7e72 Mon Sep 17 00:00:00 2001 From: mike-git374 <217764531+mike-git374@users.noreply.github.com> Date: Wed, 5 Aug 2026 14:43:40 -0600 Subject: [PATCH] sqlite: bind ArrayBuffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/62061 Fixes: https://github.com/nodejs/node/issues/61396 Reviewed-By: René Reviewed-By: Edy Silva --- src/node_sqlite.cc | 9 ++- .../test-sqlite-typed-array-and-data-view.js | 69 +++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc index 038af9812f9..3ff6c274ddb 100644 --- a/src/node_sqlite.cc +++ b/src/node_sqlite.cc @@ -235,7 +235,8 @@ void JSValueToSQLiteResult(Isolate* isolate, } else if (value->IsString()) { Utf8Value val(isolate, value.As()); sqlite3_result_text(ctx, *val, val.length(), SQLITE_TRANSIENT); - } else if (value->IsArrayBufferView()) { + } else if (value->IsArrayBufferView() || value->IsArrayBuffer() || + value->IsSharedArrayBuffer()) { ArrayBufferViewContents buf(value); sqlite3_result_blob(ctx, buf.data(), buf.length(), SQLITE_TRANSIENT); } else if (value->IsBigInt()) { @@ -2665,7 +2666,8 @@ bool StatementSync::BindParams(const FunctionCallbackInfo& args) { int anon_idx = 1; int anon_start = 0; - if (args[0]->IsObject() && !args[0]->IsArrayBufferView()) { + if (args[0]->IsObject() && !args[0]->IsArrayBufferView() && + !args[0]->IsArrayBuffer() && !args[0]->IsSharedArrayBuffer()) { Local obj = args[0].As(); Local context = Isolate::GetCurrent()->GetCurrentContext(); Local keys; @@ -2791,7 +2793,8 @@ bool StatementSync::BindValue(const Local& value, const int index) { } } else if (value->IsNull()) { r = sqlite3_bind_null(statement_, index); - } else if (value->IsArrayBufferView()) { + } else if (value->IsArrayBufferView() || value->IsArrayBuffer() || + value->IsSharedArrayBuffer()) { ArrayBufferViewContents buf(value); r = sqlite3_bind_blob64(statement_, index, diff --git a/test/parallel/test-sqlite-typed-array-and-data-view.js b/test/parallel/test-sqlite-typed-array-and-data-view.js index 2d5269be09b..5236c182e06 100644 --- a/test/parallel/test-sqlite-typed-array-and-data-view.js +++ b/test/parallel/test-sqlite-typed-array-and-data-view.js @@ -5,6 +5,10 @@ const { DatabaseSync } = require('node:sqlite'); const { suite, test } = require('node:test'); const arrayBuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]).buffer; +const sharedArrayBuffer = new SharedArrayBuffer(8); +const typedArrayOnSharedArrayBuffer = new Uint8Array(sharedArrayBuffer); +typedArrayOnSharedArrayBuffer.set([1, 2, 3, 4, 5, 6, 7, 8]); + const TypedArrays = [ ['Int8Array', Int8Array], ['Uint8Array', Uint8Array], @@ -51,3 +55,68 @@ suite('StatementSync with TypedArray/DataView', () => { }); } }); + +suite('StatementSync with ArrayBuffer and SharedArrayBuffer', () => { + const buffers = [ + ['ArrayBuffer', arrayBuffer], + ['SharedArrayBuffer', sharedArrayBuffer], + ]; + + for (const [displayName, buffer] of buffers) { + test(`${displayName} - anonymous binding`, (t) => { + const db = new DatabaseSync(':memory:'); + t.after(() => { db.close(); }); + db.exec('CREATE TABLE test (data BLOB)'); + // insert + { + const stmt = db.prepare('INSERT INTO test VALUES (?)'); + stmt.run(buffer); + } + // 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(buffer); + 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)); + } + }); + + test(`${displayName} - named binding (object)`, (t) => { + const db = new DatabaseSync(':memory:'); + t.after(() => { db.close(); }); + db.exec('CREATE TABLE test (data BLOB)'); + // insert + { + const stmt = db.prepare('INSERT INTO test VALUES ($data)'); + stmt.run({ '$data': buffer }); + } + // 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 = $data'); + const rows = stmt.all({ '$data': buffer }); + 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)); + } + }); + } +});