Skip to content

Commit d52acdc

Browse files
committed
feat: implement StatementSync::Iterate
pass compilations, break no existing tests
1 parent 01b8402 commit d52acdc

File tree

2 files changed

+54
-45
lines changed

2 files changed

+54
-45
lines changed

src/node_sqlite.cc

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,52 @@ void IteratorFunc(const v8::FunctionCallbackInfo<v8::Value>& info) {
471471
info.GetReturnValue().Set(info.Holder());
472472
}
473473

474+
struct IterateCaptureContext {
475+
int num_cols;
476+
StatementSync* stmt;
477+
};
478+
479+
void StatementSync::IterateNextCallback(const FunctionCallbackInfo<Value>& args) {
480+
Environment* env = Environment::GetCurrent(args);
481+
auto isolate = env->isolate();
482+
auto context = env->context();
483+
484+
Local<v8::External> data = Local<v8::External>::Cast(args.Data());
485+
IterateCaptureContext* captureContext = static_cast<IterateCaptureContext*>(data->Value());
486+
auto stmt = captureContext->stmt;
487+
auto num_cols = captureContext->num_cols;
488+
489+
int r = sqlite3_step(captureContext->stmt->statement_);
490+
if (r != SQLITE_ROW) {
491+
CHECK_ERROR_OR_THROW(isolate, captureContext->stmt->db_, r, SQLITE_DONE, void());
492+
Local<Object> result = Object::New(isolate);
493+
result->Set(context, String::NewFromUtf8Literal(isolate, "done"), v8::Boolean::New(isolate, true)).Check();
494+
result->Set(context, String::NewFromUtf8Literal(isolate, "value"), v8::Null(isolate)).Check();
495+
496+
args.GetReturnValue().Set(result);
497+
return;
498+
}
499+
500+
Local<Object> row = Object::New(isolate);
501+
502+
for (int i = 0; i < num_cols; ++i) {
503+
Local<Value> key = stmt->ColumnNameToValue(i);
504+
if (key.IsEmpty()) return;
505+
Local<Value> val = stmt->ColumnToValue(i);
506+
if (val.IsEmpty()) return;
507+
508+
if (row->Set(env->context(), key, val).IsNothing()) {
509+
return;
510+
}
511+
}
512+
513+
Local<Object> result = Object::New(isolate);
514+
result->Set(context, String::NewFromUtf8Literal(isolate, "done"), v8::Boolean::New(isolate, false)).Check();
515+
result->Set(context, String::NewFromUtf8Literal(isolate, "value"), row).Check();
516+
517+
args.GetReturnValue().Set(result);
518+
}
519+
474520
void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) {
475521
StatementSync* stmt;
476522
ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This());
@@ -488,55 +534,16 @@ void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) {
488534

489535
v8::Local<v8::ObjectTemplate> iterableIteratorTemplate = v8::ObjectTemplate::New(isolate);
490536

491-
v8::Local<v8::FunctionTemplate> nextFuncTemplate = v8::FunctionTemplate::NewWithCache(
537+
IterateCaptureContext* captureContext = new IterateCaptureContext();
538+
captureContext->num_cols = sqlite3_column_count(stmt->statement_);
539+
captureContext->stmt = stmt;
540+
v8::Local<v8::FunctionTemplate> nextFuncTemplate = v8::FunctionTemplate::New(
492541
isolate,
493-
[](const v8::FunctionCallbackInfo<v8::Value>& info) {
494-
auto cache = info.Data().As<std::pair<StatementSync*, std::pair<Environment*, int>*>>();
495-
auto stmt = cache->first;
496-
auto env = cache->second->first;
497-
auto num_cols = cache->second->second;
498-
499-
auto isolate = env->isolate();
500-
auto context = env->context();
501-
502-
int r = sqlite3_step(stmt->statement_);
503-
if (r != SQLITE_ROW) {
504-
CHECK_ERROR_OR_THROW(isolate, stmt->db_, r, SQLITE_DONE, void());
505-
Local<Object> result = Object::New(isolate);
506-
result->Set(context, String::NewFromUtf8Literal(isolate, "done"), v8::Boolean::New(isolate, true)).Check();
507-
result->Set(context, String::NewFromUtf8Literal(isolate, "value"), v8::Null(isolate)).Check();
508-
509-
info.GetReturnValue().Set(result);
510-
return;
511-
}
512-
513-
Local<Object> row = Object::New(isolate);
514-
515-
for (int i = 0; i < num_cols; ++i) {
516-
Local<Value> key = stmt->ColumnNameToValue(i);
517-
if (key.IsEmpty()) return;
518-
Local<Value> val = stmt->ColumnToValue(i);
519-
if (val.IsEmpty()) return;
520-
521-
if (row->Set(env->context(), key, val).IsNothing()) {
522-
return;
523-
}
524-
}
525-
526-
Local<Object> result = Object::New(isolate);
527-
result->Set(context, String::NewFromUtf8Literal(isolate, "done"), v8::Boolean::New(isolate, false)).Check();
528-
result->Set(context, String::NewFromUtf8Literal(isolate, "value"), row).Check();
529-
530-
info.GetReturnValue().Set(result);
531-
},
532-
v8::External::New(isolate, new std::pair<StatementSync*, std::pair<Environment*, int>*>(
533-
stmt,
534-
new std::pair<Environment*, int>(env, sqlite3_column_count(stmt->statement_))
535-
))
542+
StatementSync::IterateNextCallback,
543+
v8::External::New(isolate, captureContext)
536544
);
537545

538546
v8::Local<v8::FunctionTemplate> iteratorFuncTemplate = v8::FunctionTemplate::New(isolate, IteratorFunc);
539-
540547
iterableIteratorTemplate->Set(String::NewFromUtf8Literal(isolate, "next"), nextFuncTemplate);
541548
iterableIteratorTemplate->Set(v8::Symbol::GetIterator(isolate), iteratorFuncTemplate->GetFunction(context).ToLocalChecked());
542549

src/node_sqlite.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class StatementSync : public BaseObject {
7373
bool BindValue(const v8::Local<v8::Value>& value, const int index);
7474
v8::Local<v8::Value> ColumnToValue(const int column);
7575
v8::Local<v8::Value> ColumnNameToValue(const int column);
76+
77+
static void IterateNextCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
7678
};
7779

7880
} // namespace sqlite

0 commit comments

Comments
 (0)