You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2009/11/23 21:41:11 UTC

svn commit: r883494 - in /couchdb/trunk: share/www/script/test/recreate_doc.js src/couchdb/couch_db.erl src/couchdb/couch_db_updater.erl

Author: damien
Date: Mon Nov 23 20:41:06 2009
New Revision: 883494

URL: http://svn.apache.org/viewvc?rev=883494&view=rev
Log:
Fix and tests for COUCHDB-292

Modified:
    couchdb/trunk/share/www/script/test/recreate_doc.js
    couchdb/trunk/src/couchdb/couch_db.erl
    couchdb/trunk/src/couchdb/couch_db_updater.erl

Modified: couchdb/trunk/share/www/script/test/recreate_doc.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/recreate_doc.js?rev=883494&r1=883493&r2=883494&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/recreate_doc.js (original)
+++ couchdb/trunk/share/www/script/test/recreate_doc.js Mon Nov 23 20:41:06 2009
@@ -18,12 +18,12 @@
 
   // First create a new document with the ID "foo", and delete it again
   var doc = {_id: "foo", a: "bar", b: 42};
-  T(db.save(doc).ok);
+  var result = db.save(doc);
+  T(result.ok);
+  var firstRev = result.rev;
   T(db.deleteDoc(doc).ok);
 
   // Now create a new document with the same ID, save it, and then modify it
-  // This should work fine, but currently results in a conflict error, at
-  // least "sometimes"
   for (var i = 0; i < 10; i++) {
     doc = {_id: "foo"};
     T(db.save(doc).ok);
@@ -32,4 +32,49 @@
     T(db.save(doc).ok);
     T(db.deleteDoc(doc).rev != undefined);
   }
+
+  try {
+    // COUCHDB-292 now attempt to save the document with a prev that's since
+    // been deleted and this should generate a conflict exception
+    db.save({_id:"foo", _rev:firstRev, bar:1});
+    T("no save conflict 1" && false); // we shouldn't hit here
+  } catch (e) {
+    T(e.error == "conflict");
+  }
+  
+  var binAttDoc = {
+    _id: "foo",
+    _rev:firstRev,
+    _attachments:{
+      "foo.txt": {
+        content_type:"text/plain",
+        data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
+      }
+    }
+  }
+  try {
+    // same as before, but with binary
+    db.save(binAttDoc);
+    T("no save conflict 2" && false); // we shouldn't hit here
+  } catch (e) {
+    T(e.error == "conflict");
+  }
+
+
+  try {
+    // random non-existant prev rev
+    db.save({_id:"foo", _rev:"1-asfafasdf", bar:1});
+    T("no save conflict 3" && false); // we shouldn't hit here
+  } catch (e) {
+    T(e.error == "conflict");
+  }
+  
+  try {
+    // random non-existant prev rev with bin
+    binAttDoc._rev = "1-aasasfasdf";
+    db.save(binAttDoc);
+    T("no save conflict 4" && false); // we shouldn't hit here
+  } catch (e) {
+    T(e.error == "conflict");
+  }
 };

Modified: couchdb/trunk/src/couchdb/couch_db.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_db.erl?rev=883494&r1=883493&r2=883494&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_db.erl (original)
+++ couchdb/trunk/src/couchdb/couch_db.erl Mon Nov 23 20:41:06 2009
@@ -331,6 +331,8 @@
                 {validate_doc_update(Db, Doc, LoadDiskDoc), Doc}
             end;
         error when AllowConflict ->
+            couch_doc:merge_stubs(Doc, #doc{}), % will generate error if
+                                                        % there are stubs
             {validate_doc_update(Db, Doc, fun() -> nil end), Doc};
         error ->
             {conflict, Doc}
@@ -396,7 +398,8 @@
             end
         end,
         {[], AccErrors}, DocBucket),
-    prep_and_validate_updates(Db, RestBuckets, RestLookups, AllowConflict, [PreppedBucket | AccPrepped], AccErrors3).
+    prep_and_validate_updates(Db, RestBuckets, RestLookups, AllowConflict, 
+            [PreppedBucket | AccPrepped], AccErrors3).
 
 
 update_docs(#db{update_pid=UpdatePid}=Db, Docs, Options) ->

Modified: couchdb/trunk/src/couchdb/couch_db_updater.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_db_updater.erl?rev=883494&r1=883493&r2=883494&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_db_updater.erl (original)
+++ couchdb/trunk/src/couchdb/couch_db_updater.erl Mon Nov 23 20:41:06 2009
@@ -465,6 +465,19 @@
                 {_NewTree, conflicts} when (not OldDeleted) ->
                     send_result(Client, Id, {Pos-1,PrevRevs}, conflict),
                     AccTree;
+                {NewTree, conflicts} when PrevRevs /= [] ->
+                    % Check to be sure if prev revision was specified, it's
+                    % a leaf node in the tree
+                    Leafs = couch_key_tree:get_all_leafs(AccTree),
+                    IsPrevLeaf = lists:any(fun({_, {LeafPos, [LeafRevId|_]}}) ->
+                            {LeafPos, LeafRevId} == {Pos-1, hd(PrevRevs)}
+                        end, Leafs),
+                    if IsPrevLeaf ->
+                        NewTree;
+                    true ->
+                        send_result(Client, Id, {Pos-1,PrevRevs}, conflict),
+                        AccTree
+                    end;
                 {NewTree, no_conflicts} when  AccTree == NewTree ->
                     % the tree didn't change at all
                     % meaning we are saving a rev that's already