diff --git a/src/wgdb.cc b/src/wgdb.cc index 102455a..5a58797 100644 --- a/src/wgdb.cc +++ b/src/wgdb.cc @@ -108,6 +108,74 @@ void do_create_record(uv_work_t* req){ baton->data = data; } +void do_create_index(uv_work_t* req){ + Baton* baton = static_cast(req->data); + IndexData* data = static_cast(baton->data); + + wg_int lock = wg_start_write(baton->wgdb->db_ptr); + if(!lock){ + char buffer[1024]; + sprintf(buffer, "wgdb database %s could not acquire write lock", baton->wgdb->db_name); + baton->error = buffer; + return; + } + + if(wg_column_to_index_id(baton->wgdb->db_ptr, data->field, WG_INDEX_TYPE_TTREE, data->matchrec, data->reclen) == -1){ + if(wg_create_index(baton->wgdb->db_ptr, data->field, WG_INDEX_TYPE_TTREE, data->matchrec, data->reclen) != 0){ + char buffer[1024]; + sprintf(buffer, "creation of index on field %d failed for wgdb database %s", data->field, baton->wgdb->db_name); + baton->error = buffer; + } + } else{ + char buffer[1024]; + sprintf(buffer, "index on field %d already exists for wgdb database %s", data->field, baton->wgdb->db_name); + baton->error = buffer; + } + + if(!wg_end_write(baton->wgdb->db_ptr, lock)){ + char buffer[1024]; + sprintf(buffer, "wgdb database %s could not release write lock", baton->wgdb->db_name); + baton->error = buffer; + return; + } +} + +void do_drop_index(uv_work_t* req){ + Baton* baton = static_cast(req->data); + IndexData* data = static_cast(baton->data); + + wg_int lock = wg_start_write(baton->wgdb->db_ptr); + if(!lock){ + char buffer[1024]; + sprintf(buffer, "wgdb database %s could not acquire write lock", baton->wgdb->db_name); + baton->error = buffer; + return; + } + + wg_int index_id = wg_column_to_index_id(baton->wgdb->db_ptr, data->field, 0, data->matchrec, data->reclen); + + if(index_id == -1){ + char buffer[1024]; + sprintf(buffer, "index on field %d does not exist for wgdb database %s", data->field, baton->wgdb->db_name); + baton->error = buffer; + + } else{ + if(wg_drop_index(baton->wgdb->db_ptr, index_id) != 0){ + char buffer[1024]; + sprintf(buffer, "failed to drop index on field %d for wgdb database %s", data->field, baton->wgdb->db_name); + baton->error = buffer; + + } + } + + if(!wg_end_write(baton->wgdb->db_ptr, lock)){ + char buffer[1024]; + sprintf(buffer, "wgdb database %s could not release write lock", baton->wgdb->db_name); + baton->error = buffer; + return; + } +} + void do_first_record(uv_work_t* req){ Baton* baton = static_cast(req->data); @@ -487,6 +555,10 @@ void WgDB::Init(Handle target){ FunctionTemplate::New(WgDB::FindRecord)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("query"), FunctionTemplate::New(WgDB::Query)->GetFunction()); + // tpl->PrototypeTemplate()->Set(String::NewSymbol("createIndex"), + // FunctionTemplate::New(WgDB::CreateIndex)->GetFunction()); + // tpl->PrototypeTemplate()->Set(String::NewSymbol("dropIndex"), + // FunctionTemplate::New(WgDB::DropIndex)->GetFunction()); tpl->Set(String::NewSymbol("EQUAL"), Int32::New(int(WG_COND_EQUAL))); tpl->Set(String::NewSymbol("NOT_EQUAL"), Int32::New(int(WG_COND_NOT_EQUAL))); @@ -812,6 +884,110 @@ Handle WgDB::Query(const Arguments& args){ return scope.Close(Undefined()); } +Handle WgDB::CreateIndex(const Arguments& args){ + HandleScope scope; + int argc = args.Length(); + + if(argc < 1){ + return ThrowException(Exception::Error(String::New("query requires at least 1 parameter"))); + } + + if(!args[0]->IsInt32()){ + return ThrowException(Exception::TypeError(String::New("query argument 1 must be an integer"))); + } + + + IndexData* data = new IndexData(); + WgDB* db = ObjectWrap::Unwrap(args.This()); + data->field = args[0]->Int32Value(); + + if(argc > 1 && args[1]->IsArray()){ + Local arg_array = Local::Cast(args[0]->ToObject()); + data->reclen = arg_array->Length(); + wg_int tmp[data->reclen]; + + for(int i = 0; i < data->reclen; ++i){ + Local next = arg_array->Get(i); + if(next->IsUndefined()){ + tmp[i] = 0; + } else{ + tmp[i] = v8_to_encoded(db->db_ptr, next); + } + } + + data->matchrec = tmp; + } else if(argc > 2 && !args[1]->IsArray()){ + return ThrowException(Exception::TypeError(String::New("query argument 2 must be an array"))); + } + + Baton* baton = new Baton(); + if(args[argc - 1]->IsFunction()){ + baton->has_cb = true; + baton->callback = Persistent::New(Local::Cast(args[argc - 1])); + } + baton->wgdb = db; + baton->data = data; + db->Ref(); + + uv_work_t *req = new uv_work_t; + req->data = baton; + uv_queue_work(uv_default_loop(), req, do_create_index, do_after_no_result); + + return scope.Close(Undefined()); +} + +Handle WgDB::DropIndex(const Arguments& args){ + HandleScope scope; + int argc = args.Length(); + + if(argc < 1){ + return ThrowException(Exception::Error(String::New("query requires at least 1 parameter"))); + } + + if(!args[0]->IsInt32()){ + return ThrowException(Exception::TypeError(String::New("query argument 1 must be an integer"))); + } + + + IndexData* data = new IndexData(); + WgDB* db = ObjectWrap::Unwrap(args.This()); + data->field = args[0]->Int32Value(); + + if(argc > 1 && args[1]->IsArray()){ + Local arg_array = Local::Cast(args[0]->ToObject()); + data->reclen = arg_array->Length(); + wg_int tmp[data->reclen]; + + for(int i = 0; i < data->reclen; ++i){ + Local next = arg_array->Get(i); + if(next->IsUndefined()){ + tmp[i] = 0; + } else{ + tmp[i] = v8_to_encoded(db->db_ptr, next); + } + } + + data->matchrec = tmp; + } else if(argc > 2 && !args[1]->IsArray()){ + return ThrowException(Exception::TypeError(String::New("query argument 2 must be an array"))); + } + + Baton* baton = new Baton(); + if(args[argc - 1]->IsFunction()){ + baton->has_cb = true; + baton->callback = Persistent::New(Local::Cast(args[argc - 1])); + } + baton->wgdb = db; + baton->data = data; + db->Ref(); + + uv_work_t *req = new uv_work_t; + req->data = baton; + uv_queue_work(uv_default_loop(), req, do_drop_index, do_after_no_result); + + return scope.Close(Undefined()); +} + /* * * Record Class Definitions diff --git a/src/wgdb.h b/src/wgdb.h index f0b24f1..13e4497 100644 --- a/src/wgdb.h +++ b/src/wgdb.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "utils.h" @@ -27,6 +28,8 @@ class WgDB : ObjectWrap{ static Handle Import(const Arguments& args); static Handle Query(const Arguments& args); static Handle FindRecord(const Arguments& args); + static Handle CreateIndex(const Arguments& args); + static Handle DropIndex(const Arguments& args); }; class Record : ObjectWrap{