Skip to content

Commit 2b2a0bf

Browse files
gurgundayRafaelGSS
authored andcommitted
sqlite: add setReturnArrays method to StatementSync
PR-URL: #57542 Reviewed-By: Colin Ihrig <[email protected]>
1 parent 74ac98c commit 2b2a0bf

File tree

4 files changed

+308
-47
lines changed

4 files changed

+308
-47
lines changed

src/env_properties.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@
335335
V(require_string, "require") \
336336
V(resource_string, "resource") \
337337
V(retry_string, "retry") \
338+
V(return_arrays_string, "returnArrays") \
338339
V(return_string, "return") \
339340
V(salt_length_string, "saltLength") \
340341
V(scheme_string, "scheme") \

src/node_sqlite.cc

Lines changed: 113 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,6 +1368,7 @@ StatementSync::StatementSync(Environment* env,
13681368
statement_ = stmt;
13691369
// In the future, some of these options could be set at the database
13701370
// connection level and inherited by statements to reduce boilerplate.
1371+
return_arrays_ = false;
13711372
use_big_ints_ = false;
13721373
allow_bare_named_params_ = true;
13731374
allow_unknown_named_params_ = false;
@@ -1567,28 +1568,45 @@ void StatementSync::All(const FunctionCallbackInfo<Value>& args) {
15671568
auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); });
15681569
int num_cols = sqlite3_column_count(stmt->statement_);
15691570
LocalVector<Value> rows(isolate);
1570-
LocalVector<Name> row_keys(isolate);
1571-
while ((r = sqlite3_step(stmt->statement_)) == SQLITE_ROW) {
1572-
if (row_keys.size() == 0) {
1573-
row_keys.reserve(num_cols);
1571+
1572+
if (stmt->return_arrays_) {
1573+
while ((r = sqlite3_step(stmt->statement_)) == SQLITE_ROW) {
1574+
LocalVector<Value> array_values(isolate);
1575+
array_values.reserve(num_cols);
15741576
for (int i = 0; i < num_cols; ++i) {
1575-
Local<Name> key;
1576-
if (!stmt->ColumnNameToName(i).ToLocal(&key)) return;
1577-
row_keys.emplace_back(key);
1577+
Local<Value> val;
1578+
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1579+
array_values.emplace_back(val);
15781580
}
1581+
Local<Array> row_array =
1582+
Array::New(isolate, array_values.data(), array_values.size());
1583+
rows.emplace_back(row_array);
15791584
}
1585+
} else {
1586+
LocalVector<Name> row_keys(isolate);
1587+
1588+
while ((r = sqlite3_step(stmt->statement_)) == SQLITE_ROW) {
1589+
if (row_keys.size() == 0) {
1590+
row_keys.reserve(num_cols);
1591+
for (int i = 0; i < num_cols; ++i) {
1592+
Local<Name> key;
1593+
if (!stmt->ColumnNameToName(i).ToLocal(&key)) return;
1594+
row_keys.emplace_back(key);
1595+
}
1596+
}
15801597

1581-
LocalVector<Value> row_values(isolate);
1582-
row_values.reserve(num_cols);
1583-
for (int i = 0; i < num_cols; ++i) {
1584-
Local<Value> val;
1585-
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1586-
row_values.emplace_back(val);
1587-
}
1598+
LocalVector<Value> row_values(isolate);
1599+
row_values.reserve(num_cols);
1600+
for (int i = 0; i < num_cols; ++i) {
1601+
Local<Value> val;
1602+
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1603+
row_values.emplace_back(val);
1604+
}
15881605

1589-
Local<Object> row = Object::New(
1590-
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
1591-
rows.emplace_back(row);
1606+
Local<Object> row_obj = Object::New(
1607+
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
1608+
rows.emplace_back(row_obj);
1609+
}
15921610
}
15931611

15941612
CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_DONE, void());
@@ -1601,9 +1619,10 @@ void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) {
16011619
Environment* env = Environment::GetCurrent(args);
16021620
THROW_AND_RETURN_ON_BAD_STATE(
16031621
env, stmt->IsFinalized(), "statement has been finalized");
1622+
auto isolate = env->isolate();
16041623
auto context = env->context();
16051624
int r = sqlite3_reset(stmt->statement_);
1606-
CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());
1625+
CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void());
16071626

16081627
if (!stmt->BindParams(args)) {
16091628
return;
@@ -1623,13 +1642,15 @@ void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) {
16231642

16241643
BaseObjectPtr<StatementSyncIterator> iter =
16251644
StatementSyncIterator::Create(env, BaseObjectPtr<StatementSync>(stmt));
1645+
16261646
if (iter->object()
16271647
->GetPrototype()
16281648
.As<Object>()
16291649
->SetPrototype(context, js_iterator_prototype)
16301650
.IsNothing()) {
16311651
return;
16321652
}
1653+
16331654
args.GetReturnValue().Set(iter->object());
16341655
}
16351656

@@ -1660,24 +1681,37 @@ void StatementSync::Get(const FunctionCallbackInfo<Value>& args) {
16601681
return;
16611682
}
16621683

1663-
LocalVector<Name> keys(isolate);
1664-
keys.reserve(num_cols);
1665-
LocalVector<Value> values(isolate);
1666-
values.reserve(num_cols);
1684+
if (stmt->return_arrays_) {
1685+
LocalVector<Value> array_values(isolate);
1686+
array_values.reserve(num_cols);
1687+
for (int i = 0; i < num_cols; ++i) {
1688+
Local<Value> val;
1689+
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1690+
array_values.emplace_back(val);
1691+
}
1692+
Local<Array> result =
1693+
Array::New(isolate, array_values.data(), array_values.size());
1694+
args.GetReturnValue().Set(result);
1695+
} else {
1696+
LocalVector<Name> keys(isolate);
1697+
keys.reserve(num_cols);
1698+
LocalVector<Value> values(isolate);
1699+
values.reserve(num_cols);
16671700

1668-
for (int i = 0; i < num_cols; ++i) {
1669-
Local<Name> key;
1670-
if (!stmt->ColumnNameToName(i).ToLocal(&key)) return;
1671-
Local<Value> val;
1672-
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1673-
keys.emplace_back(key);
1674-
values.emplace_back(val);
1675-
}
1701+
for (int i = 0; i < num_cols; ++i) {
1702+
Local<Name> key;
1703+
if (!stmt->ColumnNameToName(i).ToLocal(&key)) return;
1704+
Local<Value> val;
1705+
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1706+
keys.emplace_back(key);
1707+
values.emplace_back(val);
1708+
}
16761709

1677-
Local<Object> result =
1678-
Object::New(isolate, Null(isolate), keys.data(), values.data(), num_cols);
1710+
Local<Object> result = Object::New(
1711+
isolate, Null(isolate), keys.data(), values.data(), num_cols);
16791712

1680-
args.GetReturnValue().Set(result);
1713+
args.GetReturnValue().Set(result);
1714+
}
16811715
}
16821716

16831717
void StatementSync::Run(const FunctionCallbackInfo<Value>& args) {
@@ -1877,6 +1911,22 @@ void StatementSync::SetReadBigInts(const FunctionCallbackInfo<Value>& args) {
18771911
stmt->use_big_ints_ = args[0]->IsTrue();
18781912
}
18791913

1914+
void StatementSync::SetReturnArrays(const FunctionCallbackInfo<Value>& args) {
1915+
StatementSync* stmt;
1916+
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
1917+
Environment* env = Environment::GetCurrent(args);
1918+
THROW_AND_RETURN_ON_BAD_STATE(
1919+
env, stmt->IsFinalized(), "statement has been finalized");
1920+
1921+
if (!args[0]->IsBoolean()) {
1922+
THROW_ERR_INVALID_ARG_TYPE(
1923+
env->isolate(), "The \"returnArrays\" argument must be a boolean.");
1924+
return;
1925+
}
1926+
1927+
stmt->return_arrays_ = args[0]->IsTrue();
1928+
}
1929+
18801930
void IllegalConstructor(const FunctionCallbackInfo<Value>& args) {
18811931
THROW_ERR_ILLEGAL_CONSTRUCTOR(Environment::GetCurrent(args));
18821932
}
@@ -1932,6 +1982,8 @@ Local<FunctionTemplate> StatementSync::GetConstructorTemplate(
19321982
StatementSync::SetAllowUnknownNamedParameters);
19331983
SetProtoMethod(
19341984
isolate, tmpl, "setReadBigInts", StatementSync::SetReadBigInts);
1985+
SetProtoMethod(
1986+
isolate, tmpl, "setReturnArrays", StatementSync::SetReturnArrays);
19351987
env->set_sqlite_statement_sync_constructor_template(tmpl);
19361988
}
19371989
return tmpl;
@@ -2023,22 +2075,36 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
20232075
}
20242076

20252077
int num_cols = sqlite3_column_count(iter->stmt_->statement_);
2026-
LocalVector<Name> row_keys(isolate);
2027-
LocalVector<Value> row_values(isolate);
2028-
row_keys.reserve(num_cols);
2029-
row_values.reserve(num_cols);
2030-
for (int i = 0; i < num_cols; ++i) {
2031-
Local<Name> key;
2032-
if (!iter->stmt_->ColumnNameToName(i).ToLocal(&key)) return;
2033-
Local<Value> val;
2034-
if (!iter->stmt_->ColumnToValue(i).ToLocal(&val)) return;
2035-
row_keys.emplace_back(key);
2036-
row_values.emplace_back(val);
2078+
Local<Value> row_value;
2079+
2080+
if (iter->stmt_->return_arrays_) {
2081+
LocalVector<Value> array_values(isolate);
2082+
array_values.reserve(num_cols);
2083+
for (int i = 0; i < num_cols; ++i) {
2084+
Local<Value> val;
2085+
if (!iter->stmt_->ColumnToValue(i).ToLocal(&val)) return;
2086+
array_values.emplace_back(val);
2087+
}
2088+
row_value = Array::New(isolate, array_values.data(), array_values.size());
2089+
} else {
2090+
LocalVector<Name> row_keys(isolate);
2091+
LocalVector<Value> row_values(isolate);
2092+
row_keys.reserve(num_cols);
2093+
row_values.reserve(num_cols);
2094+
for (int i = 0; i < num_cols; ++i) {
2095+
Local<Name> key;
2096+
if (!iter->stmt_->ColumnNameToName(i).ToLocal(&key)) return;
2097+
Local<Value> val;
2098+
if (!iter->stmt_->ColumnToValue(i).ToLocal(&val)) return;
2099+
row_keys.emplace_back(key);
2100+
row_values.emplace_back(val);
2101+
}
2102+
2103+
row_value = Object::New(
2104+
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
20372105
}
20382106

2039-
Local<Object> row = Object::New(
2040-
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
2041-
LocalVector<Value> values(isolate, {Boolean::New(isolate, false), row});
2107+
LocalVector<Value> values(isolate, {Boolean::New(isolate, false), row_value});
20422108
Local<Object> result = Object::New(
20432109
isolate, Null(isolate), keys.data(), values.data(), keys.size());
20442110
args.GetReturnValue().Set(result);

src/node_sqlite.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class StatementSync : public BaseObject {
126126
static void SetAllowUnknownNamedParameters(
127127
const v8::FunctionCallbackInfo<v8::Value>& args);
128128
static void SetReadBigInts(const v8::FunctionCallbackInfo<v8::Value>& args);
129+
static void SetReturnArrays(const v8::FunctionCallbackInfo<v8::Value>& args);
129130
void Finalize();
130131
bool IsFinalized();
131132

@@ -136,6 +137,7 @@ class StatementSync : public BaseObject {
136137
~StatementSync() override;
137138
BaseObjectPtr<DatabaseSync> db_;
138139
sqlite3_stmt* statement_;
140+
bool return_arrays_ = false;
139141
bool use_big_ints_;
140142
bool allow_bare_named_params_;
141143
bool allow_unknown_named_params_;

0 commit comments

Comments
 (0)