summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/ejdb.js12
-rw-r--r--node/ejdb_native.cc33
-rw-r--r--node/tests/t2.js13
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();
+ });
+ });
});
});
};