88#include " node_errors.h"
99#include " node_mem-inl.h"
1010#include " node_url.h"
11+ #include " simdutf.h"
1112#include " sqlite3.h"
1213#include " threadpoolwork-inl.h"
1314#include " util-inl.h"
@@ -55,6 +56,18 @@ using v8::TryCatch;
5556using v8::Uint8Array;
5657using v8::Value;
5758
59+ inline MaybeLocal<String> Utf8StringMaybeOneByte (Isolate* isolate,
60+ const char * data,
61+ size_t length) {
62+ int len = static_cast <int >(length);
63+ if (simdutf::validate_ascii (data, length)) {
64+ return String::NewFromOneByte (
65+ isolate, reinterpret_cast <const uint8_t *>(data), NewStringType::kNormal ,
66+ len);
67+ }
68+ return String::NewFromUtf8 (isolate, data, NewStringType::kNormal , len);
69+ }
70+
5871#define CHECK_ERROR_OR_THROW (isolate, db, expr, expected, ret ) \
5972 do { \
6073 int r_ = (expr); \
@@ -97,7 +110,8 @@ using v8::Value;
97110 case SQLITE_TEXT: { \
98111 const char * v = \
99112 reinterpret_cast <const char *>(sqlite3_##from##_text (__VA_ARGS__)); \
100- (result) = String::NewFromUtf8 ((isolate), v).As <Value>(); \
113+ int v_len = sqlite3_##from##_bytes (__VA_ARGS__); \
114+ (result) = Utf8StringMaybeOneByte ((isolate), v, v_len).As <Value>(); \
101115 break ; \
102116 } \
103117 case SQLITE_NULL: { \
@@ -2147,6 +2161,7 @@ StatementSync::~StatementSync() {
21472161void StatementSync::Finalize () {
21482162 sqlite3_finalize (statement_);
21492163 statement_ = nullptr ;
2164+ cached_column_names_.clear ();
21502165}
21512166
21522167inline bool StatementSync::IsFinalized () {
@@ -2325,7 +2340,40 @@ MaybeLocal<Name> StatementSync::ColumnNameToName(const int column) {
23252340 return MaybeLocal<Name>();
23262341 }
23272342
2328- return String::NewFromUtf8 (env ()->isolate (), col_name).As <Name>();
2343+ return String::NewFromUtf8 (
2344+ env ()->isolate (), col_name, NewStringType::kInternalized )
2345+ .As <Name>();
2346+ }
2347+
2348+ bool StatementSync::GetCachedColumnNames (LocalVector<Name>* keys) {
2349+ Isolate* isolate = env ()->isolate ();
2350+
2351+ int reprepare_count = sqlite3_stmt_status (
2352+ statement_, SQLITE_STMTSTATUS_REPREPARE, 0 );
2353+ if (reprepare_count != cached_column_names_reprepare_count_) {
2354+ cached_column_names_.clear ();
2355+ int num_cols = sqlite3_column_count (statement_);
2356+ if (num_cols == 0 ) {
2357+ cached_column_names_reprepare_count_ = reprepare_count;
2358+ return true ;
2359+ }
2360+ cached_column_names_.reserve (num_cols);
2361+ for (int i = 0 ; i < num_cols; ++i) {
2362+ Local<Name> key;
2363+ if (!ColumnNameToName (i).ToLocal (&key)) {
2364+ cached_column_names_.clear ();
2365+ return false ;
2366+ }
2367+ cached_column_names_.emplace_back (Global<Name>(isolate, key));
2368+ }
2369+ cached_column_names_reprepare_count_ = reprepare_count;
2370+ }
2371+
2372+ keys->reserve (cached_column_names_.size ());
2373+ for (const auto & name : cached_column_names_) {
2374+ keys->emplace_back (name.Get (isolate));
2375+ }
2376+ return true ;
23292377}
23302378
23312379MaybeLocal<Value> StatementExecutionHelper::ColumnToValue (Environment* env,
@@ -2347,7 +2395,9 @@ MaybeLocal<Name> StatementExecutionHelper::ColumnNameToName(Environment* env,
23472395 return MaybeLocal<Name>();
23482396 }
23492397
2350- return String::NewFromUtf8 (env->isolate (), col_name).As <Name>();
2398+ return String::NewFromUtf8 (
2399+ env->isolate (), col_name, NewStringType::kInternalized )
2400+ .As <Name>();
23512401}
23522402
23532403void StatementSync::MemoryInfo (MemoryTracker* tracker) const {}
@@ -3251,12 +3301,7 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
32513301 if (iter->stmt_ ->return_arrays_ ) {
32523302 row_value = Array::New (isolate, row_values.data (), row_values.size ());
32533303 } else {
3254- row_keys.reserve (num_cols);
3255- for (int i = 0 ; i < num_cols; ++i) {
3256- Local<Name> key;
3257- if (!iter->stmt_ ->ColumnNameToName (i).ToLocal (&key)) return ;
3258- row_keys.emplace_back (key);
3259- }
3304+ if (!iter->stmt_ ->GetCachedColumnNames (&row_keys)) return ;
32603305
32613306 DCHECK_EQ (row_keys.size (), row_values.size ());
32623307 row_value = Object::New (
0 commit comments