Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e8d4a31

Browse filesBrowse files
cjihrigaduh95
authored andcommitted
sqlite: add support for unknown named parameters
This commit adds a method for toggling support for unknown named parameters in prepared statements. Fixes: #55533 PR-URL: #57552 Reviewed-By: Edy Silva <edigleyssonsilva@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent f8aff90 commit e8d4a31
Copy full SHA for e8d4a31

File tree

Expand file treeCollapse file tree

4 files changed

+84
-3
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

4 files changed

+84
-3
lines changed
Open diff view settings
Collapse file

‎doc/api/sqlite.md‎

Copy file name to clipboardExpand all lines: doc/api/sqlite.md
+11Lines changed: 11 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,17 @@ are several caveats to be aware of when enabling bare named parameters:
516516
statement will result in an exception as it cannot be determined how to bind
517517
a bare name.
518518

519+
### `statement.setAllowUnknownNamedParameters(enabled)`
520+
521+
<!-- YAML
522+
added: REPLACEME
523+
-->
524+
525+
* `enabled` {boolean} Enables or disables support for unknown named parameters.
526+
527+
By default, if an unknown name is encountered while binding parameters, an
528+
exception is thrown. This method allows unknown named parameters to be ignored.
529+
519530
### `statement.setReadBigInts(enabled)`
520531

521532
<!-- YAML
Collapse file

‎src/node_sqlite.cc‎

Copy file name to clipboardExpand all lines: src/node_sqlite.cc
+29-3Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,7 @@ StatementSync::StatementSync(Environment* env,
13611361
// connection level and inherited by statements to reduce boilerplate.
13621362
use_big_ints_ = false;
13631363
allow_bare_named_params_ = true;
1364+
allow_unknown_named_params_ = false;
13641365
bare_named_params_ = std::nullopt;
13651366
}
13661367

@@ -1443,9 +1444,13 @@ bool StatementSync::BindParams(const FunctionCallbackInfo<Value>& args) {
14431444
}
14441445

14451446
if (r == 0) {
1446-
THROW_ERR_INVALID_STATE(
1447-
env(), "Unknown named parameter '%s'", *utf8_key);
1448-
return false;
1447+
if (allow_unknown_named_params_) {
1448+
continue;
1449+
} else {
1450+
THROW_ERR_INVALID_STATE(
1451+
env(), "Unknown named parameter '%s'", *utf8_key);
1452+
return false;
1453+
}
14491454
}
14501455
}
14511456

@@ -2033,6 +2038,23 @@ void StatementSync::SetAllowBareNamedParameters(
20332038
stmt->allow_bare_named_params_ = args[0]->IsTrue();
20342039
}
20352040

2041+
void StatementSync::SetAllowUnknownNamedParameters(
2042+
const FunctionCallbackInfo<Value>& args) {
2043+
StatementSync* stmt;
2044+
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
2045+
Environment* env = Environment::GetCurrent(args);
2046+
THROW_AND_RETURN_ON_BAD_STATE(
2047+
env, stmt->IsFinalized(), "statement has been finalized");
2048+
2049+
if (!args[0]->IsBoolean()) {
2050+
THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
2051+
"The \"enabled\" argument must be a boolean.");
2052+
return;
2053+
}
2054+
2055+
stmt->allow_unknown_named_params_ = args[0]->IsTrue();
2056+
}
2057+
20362058
void StatementSync::SetReadBigInts(const FunctionCallbackInfo<Value>& args) {
20372059
StatementSync* stmt;
20382060
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
@@ -2098,6 +2120,10 @@ Local<FunctionTemplate> StatementSync::GetConstructorTemplate(
20982120
tmpl,
20992121
"setAllowBareNamedParameters",
21002122
StatementSync::SetAllowBareNamedParameters);
2123+
SetProtoMethod(isolate,
2124+
tmpl,
2125+
"setAllowUnknownNamedParameters",
2126+
StatementSync::SetAllowUnknownNamedParameters);
21012127
SetProtoMethod(
21022128
isolate, tmpl, "setReadBigInts", StatementSync::SetReadBigInts);
21032129
env->set_sqlite_statement_sync_constructor_template(tmpl);
Collapse file

‎src/node_sqlite.h‎

Copy file name to clipboardExpand all lines: src/node_sqlite.h
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ class StatementSync : public BaseObject {
123123
const v8::FunctionCallbackInfo<v8::Value>& args);
124124
static void SetAllowBareNamedParameters(
125125
const v8::FunctionCallbackInfo<v8::Value>& args);
126+
static void SetAllowUnknownNamedParameters(
127+
const v8::FunctionCallbackInfo<v8::Value>& args);
126128
static void SetReadBigInts(const v8::FunctionCallbackInfo<v8::Value>& args);
127129
void Finalize();
128130
bool IsFinalized();
@@ -136,6 +138,7 @@ class StatementSync : public BaseObject {
136138
sqlite3_stmt* statement_;
137139
bool use_big_ints_;
138140
bool allow_bare_named_params_;
141+
bool allow_unknown_named_params_;
139142
std::optional<std::map<std::string, std::string>> bare_named_params_;
140143
bool BindParams(const v8::FunctionCallbackInfo<v8::Value>& args);
141144
bool BindValue(const v8::Local<v8::Value>& value, const int index);
Collapse file

‎test/parallel/test-sqlite-named-parameters.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-sqlite-named-parameters.js
+41Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,44 @@ suite('named parameters', () => {
7777
});
7878
});
7979
});
80+
81+
suite('StatementSync.prototype.setAllowUnknownNamedParameters()', () => {
82+
test('unknown named parameter support can be toggled', (t) => {
83+
const db = new DatabaseSync(':memory:');
84+
t.after(() => { db.close(); });
85+
const setup = db.exec(
86+
'CREATE TABLE data(key INTEGER, val INTEGER) STRICT;'
87+
);
88+
t.assert.strictEqual(setup, undefined);
89+
const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
90+
t.assert.strictEqual(stmt.setAllowUnknownNamedParameters(true), undefined);
91+
const params = { $a: 1, $b: 2, $k: 42, $y: 25, $v: 84, $z: 99 };
92+
t.assert.deepStrictEqual(
93+
stmt.run(params),
94+
{ changes: 1, lastInsertRowid: 1 },
95+
);
96+
t.assert.strictEqual(stmt.setAllowUnknownNamedParameters(false), undefined);
97+
t.assert.throws(() => {
98+
stmt.run(params);
99+
}, {
100+
code: 'ERR_INVALID_STATE',
101+
message: /Unknown named parameter '\$a'/,
102+
});
103+
});
104+
105+
test('throws when input is not a boolean', (t) => {
106+
const db = new DatabaseSync(':memory:');
107+
t.after(() => { db.close(); });
108+
const setup = db.exec(
109+
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
110+
);
111+
t.assert.strictEqual(setup, undefined);
112+
const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
113+
t.assert.throws(() => {
114+
stmt.setAllowUnknownNamedParameters();
115+
}, {
116+
code: 'ERR_INVALID_ARG_TYPE',
117+
message: /The "enabled" argument must be a boolean/,
118+
});
119+
});
120+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.