From c2d2cfba767333dc2c3bfd61b65b1fea2011bda5 Mon Sep 17 00:00:00 2001 From: MatricalDefunkt Date: Wed, 17 Dec 2025 19:44:43 +0530 Subject: [PATCH 1/2] sqlite: improve error messages for tag store When using SQLite tag store functions (sql.get`, sql.run`, etc.), preparation errors now show descriptive SQLite error messages instead of the generic 'Failed to prepare statement' message. The tag store's GetOrCreateStatement function now passes the database object to THROW_ERR_SQLITE_ERROR, allowing it to retrieve the actual error message from sqlite3_errmsg(), matching the behavior of the regular db.prepare() method. Fixes: https://github.com/nodejs/node/issues/61051 --- src/node_sqlite.cc | 4 ++-- test/parallel/test-sqlite-template-tag.js | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc index 0eccb2f7103563..f7c5148b8aca41 100644 --- a/src/node_sqlite.cc +++ b/src/node_sqlite.cc @@ -309,7 +309,7 @@ class CustomAggregate { static inline void xStepBase(sqlite3_context* ctx, int argc, sqlite3_value** argv, - Global CustomAggregate::*mptr) { + Global CustomAggregate::* mptr) { CustomAggregate* self = static_cast(sqlite3_user_data(ctx)); Environment* env = self->env_; @@ -2947,7 +2947,7 @@ BaseObjectPtr SQLTagStore::PrepareStatement( session->database_->connection_, sql.data(), sql.size(), &s, 0); if (r != SQLITE_OK) { - THROW_ERR_SQLITE_ERROR(isolate, "Failed to prepare statement"); + THROW_ERR_SQLITE_ERROR(isolate, session->database_.get()); sqlite3_finalize(s); return BaseObjectPtr(); } diff --git a/test/parallel/test-sqlite-template-tag.js b/test/parallel/test-sqlite-template-tag.js index 627de70392c1d8..f640e70f8c399a 100644 --- a/test/parallel/test-sqlite-template-tag.js +++ b/test/parallel/test-sqlite-template-tag.js @@ -102,3 +102,25 @@ test('TagStore capacity, size, and clear', () => { test('sql.db returns the associated DatabaseSync instance', () => { assert.strictEqual(sql.db, db); }); + +test('sql error messages are descriptive', () => { + assert.strictEqual(sql.run`INSERT INTO foo (text) VALUES (${'test'})`.changes, 1); + + // Test with non-existent column + assert.throws(() => { + const result = sql.get`SELECT nonexistent_column FROM foo`; + assert.fail(`Expected error, got: ${JSON.stringify(result)}`); + }, { + code: 'ERR_SQLITE_ERROR', + message: /no such column/i, + }); + + // Test with non-existent table + assert.throws(() => { + const result = sql.get`SELECT * FROM nonexistent_table`; + assert.fail(`Expected error, got: ${JSON.stringify(result)}`); + }, { + code: 'ERR_SQLITE_ERROR', + message: /no such table/i, + }); +}); From ed2915c73fd6d11c535b0d7a59f83011e0c45567 Mon Sep 17 00:00:00 2001 From: MatricalDefunkt Date: Thu, 18 Dec 2025 00:07:04 +0530 Subject: [PATCH 2/2] style: adjust formatting of pointer declaration in CustomAggregate --- src/node_sqlite.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc index f7c5148b8aca41..a6717853e434cb 100644 --- a/src/node_sqlite.cc +++ b/src/node_sqlite.cc @@ -309,7 +309,7 @@ class CustomAggregate { static inline void xStepBase(sqlite3_context* ctx, int argc, sqlite3_value** argv, - Global CustomAggregate::* mptr) { + Global CustomAggregate::*mptr) { CustomAggregate* self = static_cast(sqlite3_user_data(ctx)); Environment* env = self->env_;