Skip to content

Commit b62c50e

Browse files
committed
sqlite: add sqlite prepare options args
1 parent 842448b commit b62c50e

File tree

4 files changed

+171
-167
lines changed

4 files changed

+171
-167
lines changed

src/node_sqlite.cc

Lines changed: 84 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,90 @@ void DatabaseSync::Prepare(const FunctionCallbackInfo<Value>& args) {
11551155
BaseObjectPtr<StatementSync> stmt =
11561156
StatementSync::Create(env, BaseObjectPtr<DatabaseSync>(db), s);
11571157
db->statements_.insert(stmt.get());
1158+
1159+
// Parse options if provided
1160+
if (args.Length() > 1 && !args[1]->IsUndefined()) {
1161+
if (!args[1]->IsObject()) {
1162+
THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
1163+
"The \"options\" argument must be an object.");
1164+
return;
1165+
}
1166+
Local<Object> options = args[1].As<Object>();
1167+
1168+
Local<Value> return_arrays_v;
1169+
if (!options
1170+
->Get(env->context(),
1171+
FIXED_ONE_BYTE_STRING(env->isolate(), "returnArrays"))
1172+
.ToLocal(&return_arrays_v)) {
1173+
return;
1174+
}
1175+
if (!return_arrays_v->IsUndefined()) {
1176+
if (!return_arrays_v->IsBoolean()) {
1177+
THROW_ERR_INVALID_ARG_TYPE(
1178+
env->isolate(),
1179+
"The \"options.returnArrays\" argument must be a boolean.");
1180+
return;
1181+
}
1182+
stmt->return_arrays_ = return_arrays_v->IsTrue();
1183+
}
1184+
1185+
Local<Value> read_big_ints_v;
1186+
if (!options
1187+
->Get(env->context(),
1188+
FIXED_ONE_BYTE_STRING(env->isolate(), "readBigInts"))
1189+
.ToLocal(&read_big_ints_v)) {
1190+
return;
1191+
}
1192+
if (!read_big_ints_v->IsUndefined()) {
1193+
if (!read_big_ints_v->IsBoolean()) {
1194+
THROW_ERR_INVALID_ARG_TYPE(
1195+
env->isolate(),
1196+
"The \"options.readBigInts\" argument must be a boolean.");
1197+
return;
1198+
}
1199+
stmt->use_big_ints_ = read_big_ints_v->IsTrue();
1200+
}
1201+
1202+
Local<Value> allow_bare_named_params_v;
1203+
if (!options
1204+
->Get(env->context(),
1205+
FIXED_ONE_BYTE_STRING(env->isolate(),
1206+
"allowBareNamedParameters"))
1207+
.ToLocal(&allow_bare_named_params_v)) {
1208+
return;
1209+
}
1210+
if (!allow_bare_named_params_v->IsUndefined()) {
1211+
if (!allow_bare_named_params_v->IsBoolean()) {
1212+
THROW_ERR_INVALID_ARG_TYPE(
1213+
env->isolate(),
1214+
"The \"options.allowBareNamedParameters\" argument must be a "
1215+
"boolean.");
1216+
return;
1217+
}
1218+
stmt->allow_bare_named_params_ = allow_bare_named_params_v->IsTrue();
1219+
}
1220+
1221+
Local<Value> allow_unknown_named_params_v;
1222+
if (!options
1223+
->Get(env->context(),
1224+
FIXED_ONE_BYTE_STRING(env->isolate(),
1225+
"allowUnknownNamedParameters"))
1226+
.ToLocal(&allow_unknown_named_params_v)) {
1227+
return;
1228+
}
1229+
if (!allow_unknown_named_params_v->IsUndefined()) {
1230+
if (!allow_unknown_named_params_v->IsBoolean()) {
1231+
THROW_ERR_INVALID_ARG_TYPE(
1232+
env->isolate(),
1233+
"The \"options.allowUnknownNamedParameters\" argument must be a "
1234+
"boolean.");
1235+
return;
1236+
}
1237+
stmt->allow_unknown_named_params_ =
1238+
allow_unknown_named_params_v->IsTrue();
1239+
}
1240+
}
1241+
11581242
args.GetReturnValue().Set(stmt->object());
11591243
}
11601244

@@ -2587,73 +2671,6 @@ void StatementSync::ExpandedSQLGetter(const FunctionCallbackInfo<Value>& args) {
25872671
args.GetReturnValue().Set(result);
25882672
}
25892673

2590-
void StatementSync::SetAllowBareNamedParameters(
2591-
const FunctionCallbackInfo<Value>& args) {
2592-
StatementSync* stmt;
2593-
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
2594-
Environment* env = Environment::GetCurrent(args);
2595-
THROW_AND_RETURN_ON_BAD_STATE(
2596-
env, stmt->IsFinalized(), "statement has been finalized");
2597-
2598-
if (!args[0]->IsBoolean()) {
2599-
THROW_ERR_INVALID_ARG_TYPE(
2600-
env->isolate(),
2601-
"The \"allowBareNamedParameters\" argument must be a boolean.");
2602-
return;
2603-
}
2604-
2605-
stmt->allow_bare_named_params_ = args[0]->IsTrue();
2606-
}
2607-
2608-
void StatementSync::SetAllowUnknownNamedParameters(
2609-
const FunctionCallbackInfo<Value>& args) {
2610-
StatementSync* stmt;
2611-
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
2612-
Environment* env = Environment::GetCurrent(args);
2613-
THROW_AND_RETURN_ON_BAD_STATE(
2614-
env, stmt->IsFinalized(), "statement has been finalized");
2615-
2616-
if (!args[0]->IsBoolean()) {
2617-
THROW_ERR_INVALID_ARG_TYPE(env->isolate(),
2618-
"The \"enabled\" argument must be a boolean.");
2619-
return;
2620-
}
2621-
2622-
stmt->allow_unknown_named_params_ = args[0]->IsTrue();
2623-
}
2624-
2625-
void StatementSync::SetReadBigInts(const FunctionCallbackInfo<Value>& args) {
2626-
StatementSync* stmt;
2627-
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
2628-
Environment* env = Environment::GetCurrent(args);
2629-
THROW_AND_RETURN_ON_BAD_STATE(
2630-
env, stmt->IsFinalized(), "statement has been finalized");
2631-
2632-
if (!args[0]->IsBoolean()) {
2633-
THROW_ERR_INVALID_ARG_TYPE(
2634-
env->isolate(), "The \"readBigInts\" argument must be a boolean.");
2635-
return;
2636-
}
2637-
2638-
stmt->use_big_ints_ = args[0]->IsTrue();
2639-
}
2640-
2641-
void StatementSync::SetReturnArrays(const FunctionCallbackInfo<Value>& args) {
2642-
StatementSync* stmt;
2643-
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
2644-
Environment* env = Environment::GetCurrent(args);
2645-
THROW_AND_RETURN_ON_BAD_STATE(
2646-
env, stmt->IsFinalized(), "statement has been finalized");
2647-
2648-
if (!args[0]->IsBoolean()) {
2649-
THROW_ERR_INVALID_ARG_TYPE(
2650-
env->isolate(), "The \"returnArrays\" argument must be a boolean.");
2651-
return;
2652-
}
2653-
2654-
stmt->return_arrays_ = args[0]->IsTrue();
2655-
}
2656-
26572674
void IllegalConstructor(const FunctionCallbackInfo<Value>& args) {
26582675
THROW_ERR_ILLEGAL_CONSTRUCTOR(Environment::GetCurrent(args));
26592676
}
@@ -3002,18 +3019,6 @@ Local<FunctionTemplate> StatementSync::GetConstructorTemplate(
30023019
tmpl,
30033020
FIXED_ONE_BYTE_STRING(isolate, "expandedSQL"),
30043021
StatementSync::ExpandedSQLGetter);
3005-
SetProtoMethod(isolate,
3006-
tmpl,
3007-
"setAllowBareNamedParameters",
3008-
StatementSync::SetAllowBareNamedParameters);
3009-
SetProtoMethod(isolate,
3010-
tmpl,
3011-
"setAllowUnknownNamedParameters",
3012-
StatementSync::SetAllowUnknownNamedParameters);
3013-
SetProtoMethod(
3014-
isolate, tmpl, "setReadBigInts", StatementSync::SetReadBigInts);
3015-
SetProtoMethod(
3016-
isolate, tmpl, "setReturnArrays", StatementSync::SetReturnArrays);
30173022
env->set_sqlite_statement_sync_constructor_template(tmpl);
30183023
}
30193024
return tmpl;

src/node_sqlite.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,6 @@ class StatementSync : public BaseObject {
220220
static void SourceSQLGetter(const v8::FunctionCallbackInfo<v8::Value>& args);
221221
static void ExpandedSQLGetter(
222222
const v8::FunctionCallbackInfo<v8::Value>& args);
223-
static void SetAllowBareNamedParameters(
224-
const v8::FunctionCallbackInfo<v8::Value>& args);
225-
static void SetAllowUnknownNamedParameters(
226-
const v8::FunctionCallbackInfo<v8::Value>& args);
227-
static void SetReadBigInts(const v8::FunctionCallbackInfo<v8::Value>& args);
228-
static void SetReturnArrays(const v8::FunctionCallbackInfo<v8::Value>& args);
229223
v8::MaybeLocal<v8::Value> ColumnToValue(const int column);
230224
v8::MaybeLocal<v8::Name> ColumnNameToName(const int column);
231225
void Finalize();

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

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,33 @@ suite('named parameters', () => {
7979
});
8080
});
8181

82-
suite('StatementSync.prototype.setAllowUnknownNamedParameters()', () => {
83-
test('unknown named parameter support can be toggled', (t) => {
82+
suite('allowUnknownNamedParameters', () => {
83+
test('unknown named parameters can be allowed', (t) => {
8484
const db = new DatabaseSync(':memory:');
8585
t.after(() => { db.close(); });
8686
const setup = db.exec(
8787
'CREATE TABLE data(key INTEGER, val INTEGER) STRICT;'
8888
);
8989
t.assert.strictEqual(setup, undefined);
90-
const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
91-
t.assert.strictEqual(stmt.setAllowUnknownNamedParameters(true), undefined);
90+
const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)', {
91+
allowUnknownNamedParameters: true,
92+
});
9293
const params = { $a: 1, $b: 2, $k: 42, $y: 25, $v: 84, $z: 99 };
9394
t.assert.deepStrictEqual(
9495
stmt.run(params),
9596
{ changes: 1, lastInsertRowid: 1 },
9697
);
97-
t.assert.strictEqual(stmt.setAllowUnknownNamedParameters(false), undefined);
98+
});
99+
100+
test('unknown named parameters are rejected by default', (t) => {
101+
const db = new DatabaseSync(':memory:');
102+
t.after(() => { db.close(); });
103+
const setup = db.exec(
104+
'CREATE TABLE data(key INTEGER, val INTEGER) STRICT;'
105+
);
106+
t.assert.strictEqual(setup, undefined);
107+
const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
108+
const params = { $a: 1, $b: 2, $k: 42, $y: 25, $v: 84, $z: 99 };
98109
t.assert.throws(() => {
99110
stmt.run(params);
100111
}, {
@@ -110,12 +121,13 @@ suite('StatementSync.prototype.setAllowUnknownNamedParameters()', () => {
110121
'CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;'
111122
);
112123
t.assert.strictEqual(setup, undefined);
113-
const stmt = db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)');
114124
t.assert.throws(() => {
115-
stmt.setAllowUnknownNamedParameters();
125+
db.prepare('INSERT INTO data (key, val) VALUES ($k, $v)', {
126+
allowUnknownNamedParameters: 'true',
127+
});
116128
}, {
117129
code: 'ERR_INVALID_ARG_TYPE',
118-
message: /The "enabled" argument must be a boolean/,
130+
message: /The "options\.allowUnknownNamedParameters" argument must be a boolean/,
119131
});
120132
});
121133
});

0 commit comments

Comments
 (0)