Browse Source

add query method and cursor class

master
Brett Langdon 12 years ago
parent
commit
b350bc5feb
3 changed files with 213 additions and 0 deletions
  1. +1
    -0
      src/main.cc
  2. +195
    -0
      src/wgdb.cc
  3. +17
    -0
      src/wgdb.h

+ 1
- 0
src/main.cc View File

@ -9,6 +9,7 @@ using namespace v8;
void init(Handle<Object> target){ void init(Handle<Object> target){
WgDB::Init(target); WgDB::Init(target);
Record::Init(); Record::Init();
Cursor::Init();
} }
NODE_MODULE(wgdb, init); NODE_MODULE(wgdb, init);

+ 195
- 0
src/wgdb.cc View File

@ -1,6 +1,7 @@
#include "wgdb.h" #include "wgdb.h"
Persistent<Function> Record::constructor; Persistent<Function> Record::constructor;
Persistent<Function> Cursor::constructor;
/* /*
* *
@ -39,6 +40,12 @@ struct FindData {
void* data; void* data;
}; };
struct CursorData {
int arglen;
wg_query_arg* arglist;
wg_query* query;
};
/* /*
* *
@ -248,6 +255,53 @@ void do_find_record(uv_work_t* req){
} }
void do_cursor_next(uv_work_t* req){
Baton* baton = static_cast<Baton*>(req->data);
Cursor* cursor = static_cast<Cursor*>(baton->data);
wg_int lock = wg_start_read(baton->wgdb->db_ptr);
if(!lock){
char buffer[1024];
sprintf(buffer, "wgdb database %s could not acquire read lock", baton->wgdb->db_name);
baton->error = buffer;
return;
}
RecordData* new_data = new RecordData();
new_data->record = wg_fetch(cursor->wgdb->db_ptr, cursor->query);
baton->data = new_data;
if(!wg_end_read(baton->wgdb->db_ptr, lock)){
char buffer[1024];
sprintf(buffer, "wgdb database %s could not releae read lock", baton->wgdb->db_name);
baton->error = buffer;
}
}
void do_query(uv_work_t* req){
Baton* baton = static_cast<Baton*>(req->data);
CursorData* data = static_cast<CursorData*>(baton->data);
wg_int lock = wg_start_read(baton->wgdb->db_ptr);
if(!lock){
char buffer[1024];
sprintf(buffer, "wgdb database %s could not acquire read lock", baton->wgdb->db_name);
baton->error = buffer;
return;
}
data->query = wg_make_query(baton->wgdb->db_ptr, NULL, 0, data->arglist, data->arglen);
baton->data = data;
if(!wg_end_read(baton->wgdb->db_ptr, lock)){
char buffer[1024];
sprintf(buffer, "wgdb database %s could not releae read lock", baton->wgdb->db_name);
baton->error = buffer;
}
}
void do_record_next(uv_work_t* req){ void do_record_next(uv_work_t* req){
Baton* baton = static_cast<Baton*>(req->data); Baton* baton = static_cast<Baton*>(req->data);
@ -449,6 +503,8 @@ void WgDB::Init(Handle<Object> target){
FunctionTemplate::New(WgDB::Import)->GetFunction()); FunctionTemplate::New(WgDB::Import)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("findRecord"), tpl->PrototypeTemplate()->Set(String::NewSymbol("findRecord"),
FunctionTemplate::New(WgDB::FindRecord)->GetFunction()); FunctionTemplate::New(WgDB::FindRecord)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("query"),
FunctionTemplate::New(WgDB::Query)->GetFunction());
tpl->Set(String::NewSymbol("EQUAL"), Int32::New(int(WG_COND_EQUAL))); tpl->Set(String::NewSymbol("EQUAL"), Int32::New(int(WG_COND_EQUAL)));
tpl->Set(String::NewSymbol("NOT_EQUAL"), Int32::New(int(WG_COND_NOT_EQUAL))); tpl->Set(String::NewSymbol("NOT_EQUAL"), Int32::New(int(WG_COND_NOT_EQUAL)));
@ -712,6 +768,68 @@ Handle<Value> WgDB::FindRecord(const Arguments& args){
return scope.Close(Undefined()); return scope.Close(Undefined());
} }
Handle<Value> WgDB::Query(const Arguments& args){
HandleScope scope;
int argc = args.Length();
if(argc < 1){
return ThrowException(Exception::Error(String::New("query requires 1 parameter")));
}
if(!args[0]->IsArray()){
return ThrowException(Exception::TypeError(String::New("query argument 1 must be an array")));
}
Baton* baton = new Baton();
if(args[argc - 1]->IsFunction()){
baton->has_cb = true;
baton->callback = Persistent<Function>::New(Local<Function>::Cast(args[argc - 1]));
}
WgDB* db = ObjectWrap::Unwrap<WgDB>(args.This());
baton->wgdb = db;
db->Ref();
CursorData* data = new CursorData();
Local<Array> arg_array = Local<Array>::Cast(args[0]->ToObject());
data->arglen = arg_array->Length();
wg_query_arg arglist[data->arglen];
data->arglist = arglist;
int i;
for(i = 0; i < data->arglen; ++i){
Local<Value> next_val = arg_array->Get(i);
if(!next_val->IsArray()){
return ThrowException(Exception::TypeError(String::New("query argument 1 must be an array of arrays: [ [<field>, <cond>, <vaue>], ... ]")));
}
Local<Array> next = Local<Array>::Cast(next_val->ToObject());
if(next->Length() != 3){
return ThrowException(Exception::TypeError(String::New("query argument 1 must be an array of arrays: [ [<field>, <cond>, <vaue>], ... ]")));
}
Local<Value> field = next->Get(0);
if(!field->IsInt32()){
return ThrowException(Exception::TypeError(String::New("query argument 1 must be an array of arrays: [ [<field>, <cond>, <vaue>], ... ]")));
}
Local<Value> cond = next->Get(1);
if(!cond->IsInt32()){
return ThrowException(Exception::TypeError(String::New("query argument 1 must be an array of arrays: [ [<field>, <cond>, <vaue>], ... ]")));
}
data->arglist[i].column = field->Int32Value();
data->arglist[i].cond = cond->Int32Value();
data->arglist[i].value = v8_to_encoded_param(baton->wgdb->db_ptr, next->Get(2));
}
baton->data = data;
uv_work_t *req = new uv_work_t;
req->data = baton;
uv_queue_work(uv_default_loop(), req, do_query, Cursor::do_after_create_cursor);
return scope.Close(Undefined());
}
/* /*
* *
* Record Class Definitions * Record Class Definitions
@ -869,3 +987,80 @@ Handle<Value> Record::GetField(const Arguments& args){
return scope.Close(Undefined()); return scope.Close(Undefined());
} }
/*
*
* Cursor Class Definitions
*
*/
Cursor::~Cursor(){
if(this->wgdb && this->wgdb->db_ptr){
wg_free_query(this->wgdb->db_ptr, this->query);
int i;
for(i = 0; i < this->arglen; ++i){
wg_free_query_param(this->wgdb->db_ptr, this->arglist[i].value);
}
}
}
void Cursor::Init(){
HandleScope scope;
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("cursor"));
tpl->InstanceTemplate()->SetInternalFieldCount(2);
tpl->PrototypeTemplate()->Set(String::NewSymbol("next"),
FunctionTemplate::New(Cursor::Next)->GetFunction());
constructor = Persistent<Function>::New(tpl->GetFunction());
}
Handle<Value> Cursor::New(const Arguments& args){
HandleScope scope;
Cursor* cursor = new Cursor();
cursor->Wrap(args.This());
return scope.Close(args.This());
}
Handle<Value> Cursor::Next(const Arguments& args){
HandleScope scope;
int argc = args.Length();
Baton* baton = new Baton();
if(argc > 0 && args[argc - 1]->IsFunction()){
baton->has_cb = true;
baton->callback = Persistent<Function>::New(Local<Function>::Cast(args[argc - 1]));
}
Cursor* cursor = ObjectWrap::Unwrap<Cursor>(args.This());
baton->wgdb = cursor->wgdb;
baton->data = cursor;
cursor->Ref();
uv_work_t *req = new uv_work_t;
req->data = baton;
uv_queue_work(uv_default_loop(), req, do_cursor_next, Record::do_after_create_record);
return scope.Close(Undefined());
}
void Cursor::do_after_create_cursor(uv_work_t* req, int status){
Baton* baton = static_cast<Baton*>(req->data);
CursorData* data = static_cast<CursorData*>(baton->data);
Local<Value> result;
if(!baton->error){
Local<Object> cursor_obj = Cursor::constructor->NewInstance(0, NULL);
Cursor* cursor = ObjectWrap::Unwrap<Cursor>(cursor_obj);
cursor->arglen = data->arglen;
cursor->arglist = data->arglist;
cursor->query = data->query;
cursor->wgdb = baton->wgdb;
result = Local<Value>::New(cursor_obj);
} else{
result = Local<Value>::New(Undefined());
}
end_call(baton->has_cb, baton->callback, baton->error, result);
baton->callback.Dispose();
delete baton;
delete req;
}

+ 17
- 0
src/wgdb.h View File

@ -25,6 +25,7 @@ class WgDB : ObjectWrap{
static Handle<Value> FirstRecord(const Arguments& args); static Handle<Value> FirstRecord(const Arguments& args);
static Handle<Value> Dump(const Arguments& args); static Handle<Value> Dump(const Arguments& args);
static Handle<Value> Import(const Arguments& args); static Handle<Value> Import(const Arguments& args);
static Handle<Value> Query(const Arguments& args);
static Handle<Value> FindRecord(const Arguments& args); static Handle<Value> FindRecord(const Arguments& args);
}; };
@ -47,4 +48,20 @@ class Record : ObjectWrap{
static void do_after_create_record(uv_work_t* req, int status); static void do_after_create_record(uv_work_t* req, int status);
}; };
class Cursor : ObjectWrap{
public:
WgDB* wgdb;
wg_query* query;
wg_query_arg* arglist;
int arglen;
~Cursor();
static Persistent<Function> constructor;
static void Init();
static Handle<Value> New(const Arguments& args);
static Handle<Value> Next(const Arguments& args);
static void do_after_create_cursor(uv_work_t* req, int status);
};
#endif #endif

Loading…
Cancel
Save