Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
sqlite: add support for allowUnknownNamedParameters option in db conn…
…ection
  • Loading branch information
miguelmarcondesf committed Jun 12, 2025
commit 917a0932232f42818be17a70d43b178f23b05710
1 change: 1 addition & 0 deletions src/env_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
V(address_string, "address") \
V(aliases_string, "aliases") \
V(allow_bare_named_params_string, "allowBareNamedParameters") \
V(allow_unknown_named_params_string, "allowUnknownNamedParameters") \
V(alpn_callback_string, "ALPNCallback") \
V(args_string, "args") \
V(asn1curve_string, "asn1Curve") \
Expand Down
28 changes: 22 additions & 6 deletions src/node_sqlite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -995,18 +995,34 @@ void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) {
}
}

Local<Value> allow_bare_named_params__v;
Local<Value> allow_bare_named_params_v;
if (options->Get(env->context(), env->allow_bare_named_params_string())
.ToLocal(&allow_bare_named_params__v)) {
if (!allow_bare_named_params__v->IsUndefined()) {
if (!allow_bare_named_params__v->IsBoolean()) {
.ToLocal(&allow_bare_named_params_v)) {
if (!allow_bare_named_params_v->IsUndefined()) {
if (!allow_bare_named_params_v->IsBoolean()) {
THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
"The \"options.allowBareNamedParameters\" "
Comment thread
miguelmarcondesf marked this conversation as resolved.
Outdated
"argument must be a boolean.");
return;
}
open_config.set_allow_bare_named_params(
allow_bare_named_params__v.As<Boolean>()->Value());
allow_bare_named_params_v.As<Boolean>()->Value());
}
}

Local<Value> allow_unknown_named_params_v;
if (options->Get(env->context(), env->allow_unknown_named_params_string())
.ToLocal(&allow_unknown_named_params_v)) {
if (!allow_unknown_named_params_v->IsUndefined()) {
if (!allow_unknown_named_params_v->IsBoolean()) {
THROW_ERR_INVALID_ARG_TYPE(
env->isolate(),
"The \"options.allowUnknownNamedParameters\" "
Comment thread
miguelmarcondesf marked this conversation as resolved.
Outdated
"argument must be a boolean.");
return;
}
open_config.set_allow_unknown_named_params(
allow_unknown_named_params_v.As<Boolean>()->Value());
}
}
}
Expand Down Expand Up @@ -1818,10 +1834,10 @@ StatementSync::StatementSync(Environment* env,
use_big_ints_ = db_->use_big_ints();
return_arrays_ = db_->return_arrays();
allow_bare_named_params_ = db_->allow_bare_named_params();
allow_unknown_named_params_ = db_->allow_unknown_named_params();

// In the future, some of these options could be set at the database
// connection level and inherited by statements to reduce boilerplate.
allow_unknown_named_params_ = false;
bare_named_params_ = std::nullopt;
}

Expand Down
12 changes: 12 additions & 0 deletions src/node_sqlite.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ class DatabaseOpenConfiguration {
return allow_bare_named_params_;
}

inline void set_allow_unknown_named_params(bool flag) {
allow_unknown_named_params_ = flag;
}

inline bool get_allow_unknown_named_params() const {
return allow_unknown_named_params_;
}

private:
std::string location_;
bool read_only_ = false;
Expand All @@ -64,6 +72,7 @@ class DatabaseOpenConfiguration {
bool use_big_ints_ = false;
bool return_arrays_ = false;
bool allow_bare_named_params_ = true;
bool allow_unknown_named_params_ = false;
};

class StatementSync;
Expand Down Expand Up @@ -106,6 +115,9 @@ class DatabaseSync : public BaseObject {
bool allow_bare_named_params() const {
return open_config_.get_allow_bare_named_params();
}
bool allow_unknown_named_params() const {
return open_config_.get_allow_unknown_named_params();
}
sqlite3* Connection();

// In some situations, such as when using custom functions, it is possible
Expand Down
47 changes: 46 additions & 1 deletion test/parallel/test-sqlite-database-sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ suite('DatabaseSync() constructor', () => {
);
});

test('throws if bare named parameters are used when allowBareNamedParameters is false', (t) => {
test('throws if bare named parameters are used when option is false', (t) => {
const dbPath = nextDb();
const db = new DatabaseSync(dbPath, { allowBareNamedParameters: false });
t.after(() => { db.close(); });
Expand All @@ -311,6 +311,51 @@ suite('DatabaseSync() constructor', () => {
message: /Unknown named parameter 'k'/,
});
});

test('throws if options.allowUnknownNamedParameters is provided but is not a boolean', (t) => {
t.assert.throws(() => {
new DatabaseSync('foo', { allowUnknownNamedParameters: 42 });
}, {
code: 'ERR_INVALID_ARG_TYPE',
message: /The "options\.allowUnknownNamedParameters" argument must be a boolean/,
});
});

test('allows unknown named parameters', (t) => {
const dbPath = nextDb();
const db = new DatabaseSync(dbPath, { allowUnknownNamedParameters: true });
t.after(() => { db.close(); });
const setup = db.exec(
'CREATE TABLE data(key INTEGER, val INTEGER) STRICT;'
);
t.assert.strictEqual(setup, undefined);

const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
const params = { $a: 1, $b: 2, $k: 42, $y: 25, $v: 84, $z: 99 };
t.assert.deepStrictEqual(
stmt.run(params),
{ changes: 1, lastInsertRowid: 1 },
);
});

test('throws if unknown named parameters are used when option is false', (t) => {
const dbPath = nextDb();
const db = new DatabaseSync(dbPath, { allowUnknownNamedParameters: false });
t.after(() => { db.close(); });
const setup = db.exec(
'CREATE TABLE data(key INTEGER, val INTEGER) STRICT;'
);
t.assert.strictEqual(setup, undefined);

const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
const params = { $a: 1, $b: 2, $k: 42, $y: 25, $v: 84, $z: 99 };
t.assert.throws(() => {
stmt.run(params);
}, {
code: 'ERR_INVALID_STATE',
message: /Unknown named parameter '\$a'/,
});
});
});

suite('DatabaseSync.prototype.open()', () => {
Expand Down