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 allowBareNamedParameters option in db connection
  • Loading branch information
miguelmarcondesf committed Jun 12, 2025
commit 88be767bf4e8540b6903c336ff54be3ca17e2c3f
1 change: 1 addition & 0 deletions src/env_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
V(ack_string, "ack") \
V(address_string, "address") \
V(aliases_string, "aliases") \
V(allow_bare_named_params_string, "allowBareNamedParameters") \
V(alpn_callback_string, "ALPNCallback") \
V(args_string, "args") \
V(asn1curve_string, "asn1Curve") \
Expand Down
17 changes: 16 additions & 1 deletion src/node_sqlite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,21 @@ void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) {
open_config.set_return_arrays(return_arrays_v.As<Boolean>()->Value());
}
}

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()) {
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());
}
}
}

new DatabaseSync(
Expand Down Expand Up @@ -1802,10 +1817,10 @@ StatementSync::StatementSync(Environment* env,
statement_ = stmt;
use_big_ints_ = db_->use_big_ints();
return_arrays_ = db_->return_arrays();
allow_bare_named_params_ = db_->allow_bare_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_bare_named_params_ = true;
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 @@ -47,6 +47,14 @@ class DatabaseOpenConfiguration {

inline bool get_return_arrays() const { return return_arrays_; }

inline void set_allow_bare_named_params(bool flag) {
allow_bare_named_params_ = flag;
}

inline bool get_allow_bare_named_params() const {
return allow_bare_named_params_;
}

private:
std::string location_;
bool read_only_ = false;
Expand All @@ -55,6 +63,7 @@ class DatabaseOpenConfiguration {
int timeout_ = 0;
bool use_big_ints_ = false;
bool return_arrays_ = false;
bool allow_bare_named_params_ = true;
};

class StatementSync;
Expand Down Expand Up @@ -94,6 +103,9 @@ class DatabaseSync : public BaseObject {
bool IsOpen();
bool use_big_ints() const { return open_config_.get_use_big_ints(); }
bool return_arrays() const { return open_config_.get_return_arrays(); }
bool allow_bare_named_params() const {
return open_config_.get_allow_bare_named_params();
}
sqlite3* Connection();

// In some situations, such as when using custom functions, it is possible
Expand Down
43 changes: 43 additions & 0 deletions test/parallel/test-sqlite-database-sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,49 @@ suite('DatabaseSync() constructor', () => {
const query = db.prepare('SELECT key, val FROM data WHERE key = 1');
t.assert.deepStrictEqual(query.get(), { __proto__: null, key: 1, val: 'one' });
});

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

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

const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
t.assert.deepStrictEqual(
stmt.run({ k: 1, v: 2 }),
{ changes: 1, lastInsertRowid: 1 },
);
});

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

const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
t.assert.throws(() => {
stmt.run({ k: 2, v: 4 });
}, {
code: 'ERR_INVALID_STATE',
message: /Unknown named parameter 'k'/,
});
});
});

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