Skip to content

Commit ff709c4

Browse files
src: precompute field names
Field names do not change from row to row, so let's create JS strings only during the process of calling back into JS with the first row, not with each row. We save the JS strings we created while calling back with the first row, and re-use them when creating objects for subsequent rows. Re: nodejs/abi-stable-node#458
1 parent 1609684 commit ff709c4

File tree

2 files changed

+18
-5
lines changed

2 files changed

+18
-5
lines changed

src/statement.cc

+17-4
Original file line numberDiff line numberDiff line change
@@ -587,8 +587,9 @@ void Statement::Work_AfterAll(napi_env e, napi_status status, void* data) {
587587
Napi::Array result(Napi::Array::New(env, baton->rows.size()));
588588
auto it = static_cast<Rows::const_iterator>(baton->rows.begin());
589589
decltype(it) end = baton->rows.end();
590+
std::vector<napi_value> js_names;
590591
for (int i = 0; it < end; ++it, i++) {
591-
(result).Set(i, RowToJS(env, it->get()));
592+
(result).Set(i, RowToJS(env, it->get(), &js_names));
592593
}
593594

594595
Napi::Value argv[] = { env.Null(), result };
@@ -711,8 +712,9 @@ void Statement::AsyncEach(uv_async_t* handle) {
711712
Napi::Value argv[2];
712713
argv[0] = env.Null();
713714

715+
std::vector<napi_value> js_names;
714716
for(auto& row : rows) {
715-
argv[1] = RowToJS(env,row.get());
717+
argv[1] = RowToJS(env, row.get(), &js_names);
716718
async->retrieved++;
717719
TRY_CATCH_CALL(async->stmt->Value(), cb, 2, argv);
718720
}
@@ -787,11 +789,19 @@ void Statement::Work_AfterReset(napi_env e, napi_status status, void* data) {
787789
STATEMENT_END();
788790
}
789791

790-
Napi::Value Statement::RowToJS(Napi::Env env, Row* row) {
792+
Napi::Value Statement::RowToJS(Napi::Env env, Row* row, std::vector<napi_value>* js_names) {
793+
// Must fill this array if empty before we enter the escapable handle scope below.
794+
if (js_names != nullptr && js_names->empty()) {
795+
for (auto& field : *row) {
796+
js_names->push_back(Napi::String::New(env, field->name));
797+
}
798+
}
799+
791800
Napi::EscapableHandleScope scope(env);
792801

793802
auto result = Napi::Object::New(env);
794803

804+
size_t js_name_idx = 0;
795805
for (auto& field : *row) {
796806

797807
Napi::Value value;
@@ -816,7 +826,10 @@ Napi::Value Statement::RowToJS(Napi::Env env, Row* row) {
816826
} break;
817827
}
818828

819-
result.Set(field->name, value);
829+
napi_value field_name = js_names && js_names->empty()
830+
? Napi::String::New(env, field->name)
831+
: (*js_names)[js_name_idx++];
832+
result.Set(field_name, value);
820833
}
821834

822835
return scope.Escape(result);

src/statement.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ class Statement : public Napi::ObjectWrap<Statement> {
220220
bool Bind(const Parameters &parameters);
221221

222222
static void GetRow(Row* row, sqlite3_stmt* stmt);
223-
static Napi::Value RowToJS(Napi::Env env, Row* row);
223+
static Napi::Value RowToJS(Napi::Env env, Row* row, std::vector<napi_value>* js_names = nullptr);
224224
void Schedule(Work_Callback callback, Baton* baton);
225225
void Process();
226226
void CleanQueue();

0 commit comments

Comments
 (0)