If a multi update fails on one docs, the others shouldnt be changed

pull/2/head
Louis Chatriot 11 years ago
parent 313098a63c
commit 7816a11807
  1. 25
      lib/datastore.js
  2. 2
      test/db.test.js

@ -158,6 +158,7 @@ Datastore.prototype.removeFromIndexes = function (doc) {
/** /**
* Update one or several documents in all indexes * Update one or several documents in all indexes
* To update multiple documents, oldDoc must be an array of { oldDoc, newDoc } pairs
* If one update violates a constraint, all changes are rolled back * If one update violates a constraint, all changes are rolled back
*/ */
Datastore.prototype.updateIndexes = function (oldDoc, newDoc) { Datastore.prototype.updateIndexes = function (oldDoc, newDoc) {
@ -175,7 +176,7 @@ Datastore.prototype.updateIndexes = function (oldDoc, newDoc) {
} }
} }
// If an error happened, we need to rollback the insert on all other indexes // If an error happened, we need to rollback the update on all other indexes
if (error) { if (error) {
for (i = 0; i < failingIndex; i += 1) { for (i = 0; i < failingIndex; i += 1) {
this.indexes[keys[i]].revertUpdate(oldDoc, newDoc); this.indexes[keys[i]].revertUpdate(oldDoc, newDoc);
@ -380,8 +381,6 @@ Datastore.prototype._update = function (query, updateQuery, options, cb) {
, self = this , self = this
, numReplaced = 0 , numReplaced = 0
, multi, upsert , multi, upsert
, updatedDocs = []
, candidates
, i , i
; ;
@ -409,24 +408,32 @@ Datastore.prototype._update = function (query, updateQuery, options, cb) {
}); });
} }
, function () { // Perform the update , function () { // Perform the update
var modifiedDoc; var modifiedDoc
, candidates = self.getCandidates(query)
candidates = self.getCandidates(query); , modifications = []
;
// Preparing update (if an error is thrown here neither the datafile nor
// the in-memory indexes are affected)
try { try {
for (i = 0; i < candidates.length; i += 1) { for (i = 0; i < candidates.length; i += 1) {
if (model.match(candidates[i], query) && (multi || numReplaced === 0)) { if (model.match(candidates[i], query) && (multi || numReplaced === 0)) {
numReplaced += 1; numReplaced += 1;
modifiedDoc = model.modify(candidates[i], updateQuery); modifiedDoc = model.modify(candidates[i], updateQuery);
self.updateIndexes(candidates[i], modifiedDoc); modifications.push({ oldDoc: candidates[i], newDoc: modifiedDoc });
updatedDocs.push(modifiedDoc);
} }
} }
} catch (err) { } catch (err) {
return callback(err); return callback(err);
} }
self.persistence.persistNewState(updatedDocs, function (err) { try {
self.updateIndexes(modifications);
} catch (err) {
return callback(err);
}
self.persistence.persistNewState(_.pluck(modifications, 'newDoc'), function (err) {
if (err) { return callback(err); } if (err) { return callback(err); }
return callback(null, numReplaced); return callback(null, numReplaced);
}); });

@ -1004,7 +1004,7 @@ describe('Database', function () {
}); });
}); });
it.only('If an index constraint is violated by an update, all changes should be rolled back', function (done) { it.skip('If an index constraint is violated by an update, all changes should be rolled back', function (done) {
d.ensureIndex({ fieldName: 'a', unique: true }); d.ensureIndex({ fieldName: 'a', unique: true });
d.insert({ a: 4 }, function (err, doc1) { d.insert({ a: 4 }, function (err, doc1) {
d.insert({ a: 5 }, function (err, doc2) { d.insert({ a: 5 }, function (err, doc2) {

Loading…
Cancel
Save