Skip to content

Commit

Permalink
sqlite: cache column names in stmt.all()
Browse files Browse the repository at this point in the history
While the statement is running, it is impossible to modify the column
names and thus it is beneficial to create the host-language (JS) keys
once per all rows and reuse them for all results.

With this change the performance of `.all()` improves by around 25%
depending on the number of columns and rows in the result.
  • Loading branch information
indutny committed Oct 13, 2024
1 parent d881fcb commit b6f3f6d
Showing 1 changed file with 17 additions and 8 deletions.
25 changes: 17 additions & 8 deletions src/node_sqlite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -561,23 +561,32 @@ void StatementSync::All(const FunctionCallbackInfo<Value>& args) {
auto reset = OnScopeLeave([&]() { sqlite3_reset(stmt->statement_); });
int num_cols = sqlite3_column_count(stmt->statement_);
LocalVector<Value> rows(isolate);
LocalVector<Name> row_keys(isolate);
while ((r = sqlite3_step(stmt->statement_)) == SQLITE_ROW) {
LocalVector<Name> row_keys(isolate);
row_keys.reserve(num_cols);
if (row_keys.size() == 0) {
row_keys.reserve(num_cols);

for (int i = 0; i < num_cols; ++i) {
Local<Name> key;
if (!stmt->ColumnNameToName(i).ToLocal(&key)) return;
row_keys.emplace_back(key);
}
}

LocalVector<Value> row_values(isolate);
row_values.reserve(num_cols);

for (int i = 0; i < num_cols; ++i) {
Local<Name> key;
if (!stmt->ColumnNameToName(i).ToLocal(&key)) return;
for (size_t i = 0; i < row_keys.size(); ++i) {
Local<Value> val;
if (!stmt->ColumnToValue(i).ToLocal(&val)) return;
row_keys.emplace_back(key);
row_values.emplace_back(val);
}

Local<Object> row = Object::New(
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
Local<Object> row = Object::New(isolate,
Null(isolate),
row_keys.data(),
row_values.data(),
row_keys.size());
rows.emplace_back(row);
}

Expand Down

0 comments on commit b6f3f6d

Please sign in to comment.