diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/ejdb.js | 12 | ||||
-rw-r--r-- | node/ejdb_native.cc | 33 | ||||
-rw-r--r-- | node/tests/t2.js | 13 |
3 files changed, 42 insertions, 16 deletions
diff --git a/node/ejdb.js b/node/ejdb.js index fc30333..f49d705 100644 --- a/node/ejdb.js +++ b/node/ejdb.js @@ -108,21 +108,25 @@ EJDB.prototype.removeCollection = function(cname, prune, cb) { * To identify and update object it should contains `_id` property. * * Call variations: - * - save(cname, json object, [cb]) - * - save(cname, <Array of json objects>, [cb]) + * - save(cname, <json object>|<Array of json objects>, [cb]) + * - save(cname, <json object>|<Array of json objects>, [options], [cb]) * * @param {String} cname Name of collection. * @param {Array|Object} jsarr Signle JSON object or array of JSON objects to save * @param {Function} [cb] Callback function with arguments: (error, {Array} of OIDs for saved objects) */ -EJDB.prototype.save = function(cname, jsarr, cb) { +EJDB.prototype.save = function(cname, jsarr, opts, cb) { if (!jsarr) { return; } if (jsarr.constructor !== Array) { jsarr = [jsarr]; } - return this._impl.save(cname, jsarr, function(err, oids) { + if (typeof opts == "function") { + cb = opts; + opts = null; + } + return this._impl.save(cname, jsarr, (opts || {}), function(err, oids) { if (err) { if (cb) { cb(err); diff --git a/node/ejdb_native.cc b/node/ejdb_native.cc index 6bde344..bbe756a 100644 --- a/node/ejdb_native.cc +++ b/node/ejdb_native.cc @@ -41,6 +41,7 @@ namespace ejdb { static Persistent<String> sym_records; static Persistent<String> sym_cachedrecords; static Persistent<String> sym_explain; + static Persistent<String> sym_merge; /////////////////////////////////////////////////////////////////////////// @@ -437,8 +438,9 @@ namespace ejdb { std::vector<bson*> bsons; //bsons to save|query std::vector<bson_oid_t> ids; //saved updated oids bson_oid_t ref; //Bson ref + bool merge; //Merge bson on save - BSONCmdData(const char* _cname) : cname(_cname) { + BSONCmdData(const char* _cname) : cname(_cname), merge(false) { memset(&ref, 0, sizeof (ref)); } @@ -582,10 +584,11 @@ namespace ejdb { static Handle<Value> s_save(const Arguments& args) { HandleScope scope; - REQ_ARGS(3); + REQ_ARGS(4); REQ_STR_ARG(0, cname); //Collection name REQ_ARR_ARG(1, oarr); //Array of JSON objects - REQ_FUN_ARG(2, cb); //Callback + REQ_OBJ_ARG(2, opts); //Options obj + REQ_FUN_ARG(3, cb); //Callback BSONCmdData *cmdata = new BSONCmdData(*cname); for (uint32_t i = 0; i < oarr->Length(); ++i) { @@ -607,6 +610,9 @@ namespace ejdb { bson_finish(bs); cmdata->bsons.push_back(bs); } + if (opts->Get(sym_merge)->BooleanValue()) { + cmdata->merge = true; + } NodeEJDB *njb = ObjectWrap::Unwrap< NodeEJDB > (args.This()); BSONCmdTask *task = new BSONCmdTask(cb, njb, cmdSave, cmdata, BSONCmdTask::delete_val); uv_queue_work(uv_default_loop(), &task->uv_work, s_exec_cmd_eio, s_exec_cmd_eio_after); @@ -969,8 +975,8 @@ namespace ejdb { //Zero OID oid.ints[0] = 0; oid.ints[1] = 0; - oid.ints[2] = 0; - } else if (!ejdbsavebson(coll, bs, &oid)) { + oid.ints[2] = 0; + } else if (!ejdbsavebson2(coll, bs, &oid, cmdata->merge)) { task->cmd_ret = CMD_RET_ERROR; task->cmd_ret_msg = _jb_error_msg(); break; @@ -1145,6 +1151,7 @@ finish: sym_records = NODE_PSYMBOL("records"); sym_cachedrecords = NODE_PSYMBOL("cachedrecords"); sym_explain = NODE_PSYMBOL("$explain"); + sym_merge = NODE_PSYMBOL("$merge"); Local<FunctionTemplate> t = FunctionTemplate::New(s_new_object); @@ -1428,13 +1435,17 @@ finish: return; } TCLIST *res = cmdata->res; - cmdata->res = NULL; //res will be freed by NodeEJDBCursor instead of ~BSONQCmdData() argv[0] = Local<Primitive>::New(Null()); - Local<Value> cursorArgv[2]; - cursorArgv[0] = External::New(task->wrapped); - cursorArgv[1] = External::New(res); - Local<Object> cursor(NodeEJDBCursor::constructor_template->GetFunction()->NewInstance(2, cursorArgv)); - argv[1] = Local<Object>::New(cursor); + if (res) { + cmdata->res = NULL; //res will be freed by NodeEJDBCursor instead of ~BSONQCmdData() + Local<Value> cursorArgv[2]; + cursorArgv[0] = External::New(task->wrapped); + cursorArgv[1] = External::New(res); + Local<Value> cursor(NodeEJDBCursor::constructor_template->GetFunction()->NewInstance(2, cursorArgv)); + argv[1] = cursor; + } else { //this is update query so no result set + argv[1] = Local<Primitive>::New(Null()); + } argv[2] = Integer::New(cmdata->count); if (cmdata->log) { argv[3] = String::New((const char*) tcxstrptr(cmdata->log)); diff --git a/node/tests/t2.js b/node/tests/t2.js index b3e8728..8928317 100644 --- a/node/tests/t2.js +++ b/node/tests/t2.js @@ -252,7 +252,18 @@ module.exports.testUpdate1 = function(test) { test.ifError(err); test.ok(obj); test.equal(obj["name"], "Grenny"); - test.done(); + jb.save("parrots", {"_id" : obj["_id"], "extra1" : 1}, {"$merge" : true}, function(err, ids) { + test.ifError(err); + test.ok(ids); + test.equal(ids.length, 1); + jb.load("parrots", ids[0], function(err, obj) { + test.ifError(err); + test.ok(obj); + test.equal(obj["name"], "Grenny"); + test.equal(obj["extra1"], 1); + test.done(); + }); + }); }); }); }; |