Skip to content

Commit e8ec01d

Browse files
gurgundayaduh95
authored andcommitted
sqlite: add setReturnArrays method to StatementSync
PR-URL: #57542 Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
1 parent 11723e4 commit e8ec01d

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
@@ -328,6 +328,7 @@
328328
V(require_string, "require") \
329329
V(resource_string, "resource") \
330330
V(retry_string, "retry") \
331+
V(return_arrays_string, "returnArrays") \
331332
V(return_string, "return") \
332333
V(salt_length_string, "saltLength") \
333334
V(scheme_string, "scheme") \

src/node_sqlite.cc

Lines changed: 113 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,7 @@ StatementSync::StatementSync(Environment* env,
13781378
statement_ = stmt;
13791379
// In the future, some of these options could be set at the database
13801380
// connection level and inherited by statements to reduce boilerplate.
1381+
return_arrays_ = false;
13811382
use_big_ints_ = false;
13821383
allow_bare_named_params_ = true;
13831384
allow_unknown_named_params_ = false;
@@ -1577,28 +1578,45 @@ void StatementSync::All(const FunctionCallbackInfo<Value>& args) {
15771578
auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); });
15781579
int num_cols = sqlite3_column_count(stmt->statement_);
15791580
LocalVector<Value> rows(isolate);
1580-
LocalVector<Name> row_keys(isolate);
1581-
while ((r = sqlite3_step(stmt->statement_)) == SQLITE_ROW) {
1582-
if (row_keys.size() == 0) {
1583-
row_keys.reserve(num_cols);
1581+
1582+
if (stmt->return_arrays_) {
1583+
while ((r = sqlite3_step(stmt->statement_)) == SQLITE_ROW) {
1584+
LocalVector<Value> array_values(isolate);
1585+
array_values.reserve(num_cols);
15841586
for (int i = 0; i < num_cols; ++i) {
1585-
Local<Name> key;
1586-
if (!stmt->ColumnNameToName(i).ToLocal(&key)) return;
1587-
row_keys.emplace_back(key);
1587+
Local<Value> val;
1588+
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1589+
array_values.emplace_back(val);
15881590
}
1591+
Local<Array> row_array =
1592+
Array::New(isolate, array_values.data(), array_values.size());
1593+
rows.emplace_back(row_array);
15891594
}
1595+
} else {
1596+
LocalVector<Name> row_keys(isolate);
1597+
1598+
while ((r = sqlite3_step(stmt->statement_)) == SQLITE_ROW) {
1599+
if (row_keys.size() == 0) {
1600+
row_keys.reserve(num_cols);
1601+
for (int i = 0; i < num_cols; ++i) {
1602+
Local<Name> key;
1603+
if (!stmt->ColumnNameToName(i).ToLocal(&key)) return;
1604+
row_keys.emplace_back(key);
1605+
}
1606+
}
15901607

1591-
LocalVector<Value> row_values(isolate);
1592-
row_values.reserve(num_cols);
1593-
for (int i = 0; i < num_cols; ++i) {
1594-
Local<Value> val;
1595-
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1596-
row_values.emplace_back(val);
1597-
}
1608+
LocalVector<Value> row_values(isolate);
1609+
row_values.reserve(num_cols);
1610+
for (int i = 0; i < num_cols; ++i) {
1611+
Local<Value> val;
1612+
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1613+
row_values.emplace_back(val);
1614+
}
15981615

1599-
Local<Object> row = Object::New(
1600-
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
1601-
rows.emplace_back(row);
1616+
Local<Object> row_obj = Object::New(
1617+
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
1618+
rows.emplace_back(row_obj);
1619+
}
16021620
}
16031621

16041622
CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_DONE, void());
@@ -1611,9 +1629,10 @@ void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) {
16111629
Environment* env = Environment::GetCurrent(args);
16121630
THROW_AND_RETURN_ON_BAD_STATE(
16131631
env, stmt->IsFinalized(), "statement has been finalized");
1632+
auto isolate = env->isolate();
16141633
auto context = env->context();
16151634
int r = sqlite3_reset(stmt->statement_);
1616-
CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void());
1635+
CHECK_ERROR_OR_THROW(isolate, stmt->db_.get(), r, SQLITE_OK, void());
16171636

16181637
if (!stmt->BindParams(args)) {
16191638
return;
@@ -1633,13 +1652,15 @@ void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) {
16331652

16341653
BaseObjectPtr<StatementSyncIterator> iter =
16351654
StatementSyncIterator::Create(env, BaseObjectPtr<StatementSync>(stmt));
1655+
16361656
if (iter->object()
16371657
->GetPrototype()
16381658
.As<Object>()
16391659
->SetPrototype(context, js_iterator_prototype)
16401660
.IsNothing()) {
16411661
return;
16421662
}
1663+
16431664
args.GetReturnValue().Set(iter->object());
16441665
}
16451666

@@ -1670,24 +1691,37 @@ void StatementSync::Get(const FunctionCallbackInfo<Value>& args) {
16701691
return;
16711692
}
16721693

1673-
LocalVector<Name> keys(isolate);
1674-
keys.reserve(num_cols);
1675-
LocalVector<Value> values(isolate);
1676-
values.reserve(num_cols);
1694+
if (stmt->return_arrays_) {
1695+
LocalVector<Value> array_values(isolate);
1696+
array_values.reserve(num_cols);
1697+
for (int i = 0; i < num_cols; ++i) {
1698+
Local<Value> val;
1699+
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1700+
array_values.emplace_back(val);
1701+
}
1702+
Local<Array> result =
1703+
Array::New(isolate, array_values.data(), array_values.size());
1704+
args.GetReturnValue().Set(result);
1705+
} else {
1706+
LocalVector<Name> keys(isolate);
1707+
keys.reserve(num_cols);
1708+
LocalVector<Value> values(isolate);
1709+
values.reserve(num_cols);
16771710

1678-
for (int i = 0; i < num_cols; ++i) {
1679-
Local<Name> key;
1680-
if (!stmt->ColumnNameToName(i).ToLocal(&key)) return;
1681-
Local<Value> val;
1682-
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1683-
keys.emplace_back(key);
1684-
values.emplace_back(val);
1685-
}
1711+
for (int i = 0; i < num_cols; ++i) {
1712+
Local<Name> key;
1713+
if (!stmt->ColumnNameToName(i).ToLocal(&key)) return;
1714+
Local<Value> val;
1715+
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
1716+
keys.emplace_back(key);
1717+
values.emplace_back(val);
1718+
}
16861719

1687-
Local<Object> result =
1688-
Object::New(isolate, Null(isolate), keys.data(), values.data(), num_cols);
1720+
Local<Object> result = Object::New(
1721+
isolate, Null(isolate), keys.data(), values.data(), num_cols);
16891722

1690-
args.GetReturnValue().Set(result);
1723+
args.GetReturnValue().Set(result);
1724+
}
16911725
}
16921726

16931727
void StatementSync::Run(const FunctionCallbackInfo<Value>& args) {
@@ -1887,6 +1921,22 @@ void StatementSync::SetReadBigInts(const FunctionCallbackInfo<Value>& args) {
18871921
stmt->use_big_ints_ = args[0]->IsTrue();
18881922
}
18891923

1924+
void StatementSync::SetReturnArrays(const FunctionCallbackInfo<Value>& args) {
1925+
StatementSync* stmt;
1926+
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
1927+
Environment* env = Environment::GetCurrent(args);
1928+
THROW_AND_RETURN_ON_BAD_STATE(
1929+
env, stmt->IsFinalized(), "statement has been finalized");
1930+
1931+
if (!args[0]->IsBoolean()) {
1932+
THROW_ERR_INVALID_ARG_TYPE(
1933+
env->isolate(), "The \"returnArrays\" argument must be a boolean.");
1934+
return;
1935+
}
1936+
1937+
stmt->return_arrays_ = args[0]->IsTrue();
1938+
}
1939+
18901940
void IllegalConstructor(const FunctionCallbackInfo<Value>& args) {
18911941
THROW_ERR_ILLEGAL_CONSTRUCTOR(Environment::GetCurrent(args));
18921942
}
@@ -1942,6 +1992,8 @@ Local<FunctionTemplate> StatementSync::GetConstructorTemplate(
19421992
StatementSync::SetAllowUnknownNamedParameters);
19431993
SetProtoMethod(
19441994
isolate, tmpl, "setReadBigInts", StatementSync::SetReadBigInts);
1995+
SetProtoMethod(
1996+
isolate, tmpl, "setReturnArrays", StatementSync::SetReturnArrays);
19451997
env->set_sqlite_statement_sync_constructor_template(tmpl);
19461998
}
19471999
return tmpl;
@@ -2033,22 +2085,36 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
20332085
}
20342086

20352087
int num_cols = sqlite3_column_count(iter->stmt_->statement_);
2036-
LocalVector<Name> row_keys(isolate);
2037-
LocalVector<Value> row_values(isolate);
2038-
row_keys.reserve(num_cols);
2039-
row_values.reserve(num_cols);
2040-
for (int i = 0; i < num_cols; ++i) {
2041-
Local<Name> key;
2042-
if (!iter->stmt_->ColumnNameToName(i).ToLocal(&key)) return;
2043-
Local<Value> val;
2044-
if (!iter->stmt_->ColumnToValue(i).ToLocal(&val)) return;
2045-
row_keys.emplace_back(key);
2046-
row_values.emplace_back(val);
2088+
Local<Value> row_value;
2089+
2090+
if (iter->stmt_->return_arrays_) {
2091+
LocalVector<Value> array_values(isolate);
2092+
array_values.reserve(num_cols);
2093+
for (int i = 0; i < num_cols; ++i) {
2094+
Local<Value> val;
2095+
if (!iter->stmt_->ColumnToValue(i).ToLocal(&val)) return;
2096+
array_values.emplace_back(val);
2097+
}
2098+
row_value = Array::New(isolate, array_values.data(), array_values.size());
2099+
} else {
2100+
LocalVector<Name> row_keys(isolate);
2101+
LocalVector<Value> row_values(isolate);
2102+
row_keys.reserve(num_cols);
2103+
row_values.reserve(num_cols);
2104+
for (int i = 0; i < num_cols; ++i) {
2105+
Local<Name> key;
2106+
if (!iter->stmt_->ColumnNameToName(i).ToLocal(&key)) return;
2107+
Local<Value> val;
2108+
if (!iter->stmt_->ColumnToValue(i).ToLocal(&val)) return;
2109+
row_keys.emplace_back(key);
2110+
row_values.emplace_back(val);
2111+
}
2112+
2113+
row_value = Object::New(
2114+
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
20472115
}
20482116

2049-
Local<Object> row = Object::New(
2050-
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
2051-
LocalVector<Value> values(isolate, {Boolean::New(isolate, false), row});
2117+
LocalVector<Value> values(isolate, {Boolean::New(isolate, false), row_value});
20522118
Local<Object> result = Object::New(
20532119
isolate, Null(isolate), keys.data(), values.data(), keys.size());
20542120
args.GetReturnValue().Set(result);

src/node_sqlite.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class StatementSync : public BaseObject {
128128
static void SetAllowUnknownNamedParameters(
129129
const v8::FunctionCallbackInfo<v8::Value>& args);
130130
static void SetReadBigInts(const v8::FunctionCallbackInfo<v8::Value>& args);
131+
static void SetReturnArrays(const v8::FunctionCallbackInfo<v8::Value>& args);
131132
void Finalize();
132133
bool IsFinalized();
133134

@@ -138,6 +139,7 @@ class StatementSync : public BaseObject {
138139
~StatementSync() override;
139140
BaseObjectPtr<DatabaseSync> db_;
140141
sqlite3_stmt* statement_;
142+
bool return_arrays_ = false;
141143
bool use_big_ints_;
142144
bool allow_bare_named_params_;
143145
bool allow_unknown_named_params_;

0 commit comments

Comments
 (0)