diff options
author | Greg Studer <greg@10gen.com> | 2014-02-06 12:14:53 -0500 |
---|---|---|
committer | Greg Studer <greg@10gen.com> | 2014-02-10 12:14:34 -0500 |
commit | 5d94703d7dbbf99de25152e69aacf47b4d09c2d4 (patch) | |
tree | b6cc38cd351303f32a74336ef1434689eb84b98b | |
parent | 5999bc487e0b5a80c26676f396ba2544d9fadd5d (diff) | |
download | mongo-5d94703d7dbbf99de25152e69aacf47b4d09c2d4.tar.gz |
SERVER-12127 test of single write results, example of using new write command mode
-rw-r--r-- | jstests/core/write_result.js | 178 | ||||
-rw-r--r-- | src/mongo/shell/collection.js | 43 | ||||
-rw-r--r-- | src/mongo/shell/mongo.js | 4 |
3 files changed, 213 insertions, 12 deletions
diff --git a/jstests/core/write_result.js b/jstests/core/write_result.js new file mode 100644 index 00000000000..881b91d2694 --- /dev/null +++ b/jstests/core/write_result.js @@ -0,0 +1,178 @@ +// +// Tests the behavior of single writes using write commands +// + +var coll = db.write_result; +coll.drop(); + +assert(coll.getMongo().useWriteCommands()); + +var result = null; + +// +// Basic insert +coll.remove({}); +printjson( result = coll.insert({ foo : "bar" }) ); +assert.eq(result.nInserted, 1); +assert.eq(result.nUpserted, 0); +assert.eq(result.nUpdated, 0); +assert.eq(result.nModified, 0); +assert.eq(result.nRemoved, 0); +assert(!result.getWriteError()); +assert(!result.getWriteConcernError()); +assert(!result.getUpsertedId()); +assert.eq(coll.count(), 1); + +// +// Basic upsert (using save) +coll.remove({}); +var id = new ObjectId(); +printjson( result = coll.save({ _id : id, foo : "bar" }) ); +assert.eq(result.nInserted, 0); +assert.eq(result.nUpserted, 1); +assert.eq(result.nUpdated, 0); +assert.eq(result.nModified, 0); +assert.eq(result.nRemoved, 0); +assert(!result.getWriteError()); +assert(!result.getWriteConcernError()); +assert.eq(result.getUpsertedId()._id, id); +assert.eq(coll.count(), 1); + +// +// Basic update +coll.remove({}); +coll.insert({ foo : "bar" }); +printjson( result = coll.update({ foo : "bar" }, { $set : { foo : "baz" } }) ); +assert.eq(result.nInserted, 0); +assert.eq(result.nUpserted, 0); +assert.eq(result.nUpdated, 1); +assert.eq(result.nModified, 1); +assert.eq(result.nRemoved, 0); +assert(!result.getWriteError()); +assert(!result.getWriteConcernError()); +assert(!result.getUpsertedId()); +assert.eq(coll.count(), 1); + +// +// Basic multi-update +coll.remove({}); +coll.insert({ foo : "bar" }); +coll.insert({ foo : "bar", set : ['value'] }); +printjson( result = coll.update({ foo : "bar" }, + { $addToSet : { set : 'value' } }, + { multi : true }) ); +assert.eq(result.nInserted, 0); +assert.eq(result.nUpserted, 0); +assert.eq(result.nUpdated, 2); +assert.eq(result.nModified, 1); +assert.eq(result.nRemoved, 0); +assert(!result.getWriteError()); +assert(!result.getWriteConcernError()); +assert(!result.getUpsertedId()); +assert.eq(coll.count(), 2); + +// +// Basic remove +coll.remove({}); +coll.insert({ foo : "bar" }); +printjson( result = coll.remove({}) ); +assert.eq(result.nInserted, 0); +assert.eq(result.nUpserted, 0); +assert.eq(result.nUpdated, 0); +assert.eq(result.nModified, 0); +assert.eq(result.nRemoved, 1); +assert(!result.getWriteError()); +assert(!result.getWriteConcernError()); +assert(!result.getUpsertedId()); +assert.eq(coll.count(), 0); + +// +// Insert with error +coll.remove({}); +var id = new ObjectId(); +coll.insert({ _id : id, foo : "bar" }); +printjson( result = coll.insert({ _id : id, foo : "baz" }) ); +assert.eq(result.nInserted, 0); +assert(result.getWriteError()); +assert(result.getWriteError().errmsg); +assert(!result.getWriteConcernError()); +assert.eq(coll.count(), 1); + +// +// Update with error +coll.remove({}); +coll.insert({ foo : "bar" }); +printjson( result = coll.update({ foo : "bar" }, { $invalid : "expr" }) ); +assert.eq(result.nUpserted, 0); +assert.eq(result.nUpdated, 0); +assert.eq(result.nModified, 0); +assert(result.getWriteError()); +assert(result.getWriteError().errmsg); +assert(!result.getUpsertedId()); +assert.eq(coll.count(), 1); + +// +// Multi-update with error +coll.remove({}); +var id = new ObjectId(); +for (var i = 0; i < 10; ++i) coll.insert({ value : NumberInt(i) }); +coll.insert({ value : "not a number" }); +// $bit operator fails when the field is not integer +// Note that multi-updates do not currently report partial stats if they fail +printjson( result = coll.update({}, + { $bit : { value : { and : NumberInt(0) } } }, + { multi : true }) ); +assert.eq(result.nUpserted, 0); +assert.eq(result.nUpdated, 0); +assert.eq(result.nModified, 0); +assert(result.getWriteError()); +assert(result.getWriteError().errmsg); +assert(!result.getUpsertedId()); +assert.eq(coll.count(), 11); + +// +// Bulk insert +coll.remove({}); +printjson( result = coll.insert([{ foo : "bar" }, { foo : "baz" }]) ); +assert.eq(result.nInserted, 2); +assert(!result.getWriteError()); +assert(!result.getWriteConcernError()); +assert.eq(coll.count(), 2); + +// +// Bulk insert with error +coll.remove({}); +var id = new ObjectId(); +// Second insert fails with duplicate _id +printjson( result = coll.insert([{ _id : id, foo : "bar" }, + { _id : id, foo : "baz" }]) ); +assert.eq(result.nInserted, 1); +assert(result.getWriteError()); +assert(!result.getWriteConcernError()); +assert.eq(coll.count(), 1); + +// +// Custom write concern +// (More detailed write concern tests require custom/replicated servers) +coll.remove({}); +coll.setWriteConcern({ w : "majority" }); +printjson( result = coll.insert({ foo : "bar" }) ); +assert.eq(result.nInserted, 1); +assert(!result.getWriteError()); +assert(!result.getWriteConcernError()); +assert.eq(coll.count(), 1); +coll.unsetWriteConcern(); + +// +// Write concern error +// NOTE: Non-throwing write concern failures require replication to trigger +coll.remove({}); +coll.setWriteConcern({ w : 2 }); +assert.throws( function() { + printjson( coll.insert({ foo : "bar" }) ); +}); +assert.eq(coll.count(), 0); +coll.unsetWriteConcern(); + + + diff --git a/src/mongo/shell/collection.js b/src/mongo/shell/collection.js index 5a9b65de36d..bed1174b2ea 100644 --- a/src/mongo/shell/collection.js +++ b/src/mongo/shell/collection.js @@ -72,6 +72,8 @@ DBCollection.prototype.help = function () { print("\tdb." + shortName + ".getShardVersion() - only for use with sharding"); print("\tdb." + shortName + ".getShardDistribution() - prints statistics about data distribution in the cluster"); print("\tdb." + shortName + ".getSplitKeysForChunks( <maxChunkSize> ) - calculates split points over all chunks and returns splitter function"); + print("\tdb." + shortName + ".setWriteConcern( <write concern doc> ) - sets the write concern for writes to the collection"); + print("\tdb." + shortName + ".unsetWriteConcern( <write concern doc> ) - unsets the write concern for writes to the collection"); // print("\tdb." + shortName + ".getDiskStorageStats({...}) - prints a summary of disk usage statistics"); // print("\tdb." + shortName + ".getPagesInRAM({...}) - prints a summary of storage pages currently in physical memory"); return __magicNoPrint; @@ -211,9 +213,8 @@ DBCollection.prototype.insert = function( obj , options, _allow_dot ){ } var writeConcern = null; - if (this._mongo.getWriteConcern()) { - writeConcern = this._mongo.getWriteConcern().toJSON(); - } + if (this.getWriteConcern()) + writeConcern = this.getWriteConcern().toJSON(); result = batch.execute(writeConcern).toSingleResult(); } @@ -268,9 +269,8 @@ DBCollection.prototype.remove = function( t , justOne ){ } var writeConcern = null; - if (this._mongo.getWriteConcern()) { - writeConcern = this._mongo.getWriteConcern().toJSON(); - } + if (this.getWriteConcern()) + writeConcern = this.getWriteConcern().toJSON(); result = batch.execute(writeConcern).toSingleResult(); } @@ -332,9 +332,8 @@ DBCollection.prototype.update = function( query , obj , upsert , multi ){ } var writeConcern = null; - if (this._mongo.getWriteConcern()) { - writeConcern = this._mongo.getWriteConcern().toJSON(); - } + if (this.getWriteConcern()) + writeConcern = this.getWriteConcern().toJSON(); result = batch.execute(writeConcern).toSingleResult(); } @@ -1366,7 +1365,31 @@ DBCollection.prototype.getPlanCache = function() { return new PlanCache( this ); } -// plan cache commands +// Overrides connection-level settings. +// + +DBCollection.prototype.setWriteConcern = function( wc ) { + if ( wc instanceof WriteConcern ) { + this._writeConcern = wc; + } + else { + this._writeConcern = new WriteConcern( wc ); + } +}; + +DBCollection.prototype.getWriteConcern = function() { + if (this._writeConcern) + return this._writeConcern; + + if (this._mongo.getWriteConcern()) + return this._mongo.getWriteConcern(); + + return null; +}; + +DBCollection.prototype.unsetWriteConcern = function() { + delete this._writeConcern; +}; /** * PlanCache diff --git a/src/mongo/shell/mongo.js b/src/mongo/shell/mongo.js index 05969828bab..6dc3d9da064 100644 --- a/src/mongo/shell/mongo.js +++ b/src/mongo/shell/mongo.js @@ -181,8 +181,8 @@ Mongo.prototype.useWriteCommands = function() { }; // -// Write Concern can be set at the connection level, and is used for all write operations -// TODO: (unless overridden) +// Write Concern can be set at the connection level, and is used for all write operations unless +// overridden at the collection level. // Mongo.prototype.setWriteConcern = function( wc ) { |