You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by fd...@apache.org on 2010/09/29 14:06:35 UTC

svn commit: r1002587 - in /couchdb/branches/new_replicator: share/www/script/test/new_replication.js src/couchdb/couch_replicator_utils.erl

Author: fdmanana
Date: Wed Sep 29 12:06:34 2010
New Revision: 1002587

URL: http://svn.apache.org/viewvc?rev=1002587&view=rev
Log:
Backporting fix for COUCHDB-892 from trunk revision 1002259:

Replicator fix: for a filtered replication, the replication ID should take into account the filter function's code and not only its name.


Modified:
    couchdb/branches/new_replicator/share/www/script/test/new_replication.js
    couchdb/branches/new_replicator/src/couchdb/couch_replicator_utils.erl

Modified: couchdb/branches/new_replicator/share/www/script/test/new_replication.js
URL: http://svn.apache.org/viewvc/couchdb/branches/new_replicator/share/www/script/test/new_replication.js?rev=1002587&r1=1002586&r2=1002587&view=diff
==============================================================================
--- couchdb/branches/new_replicator/share/www/script/test/new_replication.js (original)
+++ couchdb/branches/new_replicator/share/www/script/test/new_replication.js Wed Sep 29 12:06:34 2010
@@ -528,6 +528,118 @@ couchTests.new_replication = function(de
   }
 
 
+  // test filtered replication works as expected after changing the filter's
+  // code (ticket COUCHDB-892)
+  var filterFun1 = (function(doc, req) {
+    if (doc.value < Number(req.query.maxvalue)) {
+      return true;
+    } else {
+      return false;
+    }
+  }).toString();
+
+  var filterFun2 = (function(doc, req) {
+    return true;
+  }).toString();
+
+  for (i = 0; i < dbPairs.length; i++) {
+    populateDb(targetDb, []);
+    populateDb(sourceDb, []);
+
+    T(sourceDb.save({_id: "foo1", value: 1}).ok);
+    T(sourceDb.save({_id: "foo2", value: 2}).ok);
+    T(sourceDb.save({_id: "foo3", value: 3}).ok);
+    T(sourceDb.save({_id: "foo4", value: 4}).ok);
+
+    var ddoc = {
+      "_id": "_design/mydesign",
+      "language": "javascript",
+      "filters": {
+        "myfilter": filterFun1
+      }
+    };
+
+    T(sourceDb.save(ddoc).ok);
+
+    repResult = CouchDB.new_replicate(
+      dbPairs[i].source,
+      dbPairs[i].target,
+      {
+        body: {
+          filter: "mydesign/myfilter",
+          query_params : {
+            maxvalue: "3"
+          }
+        }
+      }
+    );
+
+    T(repResult.ok === true);
+    T(repResult.history instanceof Array);
+    T(repResult.history.length === 1);
+    T(repResult.history[0].docs_written === 2);
+    T(repResult.history[0].docs_read === 2);
+    T(repResult.history[0].doc_write_failures === 0);
+
+    var docFoo1 = targetDb.open("foo1");
+    T(docFoo1 !== null);
+    T(docFoo1.value === 1);
+
+    var docFoo2 = targetDb.open("foo2");
+    T(docFoo2 !== null);
+    T(docFoo2.value === 2);
+
+    var docFoo3 = targetDb.open("foo3");
+    T(docFoo3 === null);
+
+    var docFoo4 = targetDb.open("foo4");
+    T(docFoo4 === null);
+
+    // replication should start from scratch after the filter's code changed
+
+    ddoc.filters.myfilter = filterFun2;
+    T(sourceDb.save(ddoc).ok);
+
+    repResult = CouchDB.new_replicate(
+      dbPairs[i].source,
+      dbPairs[i].target,
+      {
+        body: {
+          filter: "mydesign/myfilter",
+          query_params : {
+            maxvalue: "3"
+          }
+        }
+      }
+    );
+
+    T(repResult.ok === true);
+    T(repResult.history instanceof Array);
+    T(repResult.history.length === 1);
+    T(repResult.history[0].docs_written === 3);
+    T(repResult.history[0].docs_read === 3);
+    T(repResult.history[0].doc_write_failures === 0);
+
+    docFoo1 = targetDb.open("foo1");
+    T(docFoo1 !== null);
+    T(docFoo1.value === 1);
+
+    docFoo2 = targetDb.open("foo2");
+    T(docFoo2 !== null);
+    T(docFoo2.value === 2);
+
+    docFoo3 = targetDb.open("foo3");
+    T(docFoo3 !== null);
+    T(docFoo3.value === 3);
+
+    docFoo4 = targetDb.open("foo4");
+    T(docFoo4 !== null);
+    T(docFoo4.value === 4);
+
+    T(targetDb.open("_design/mydesign") !== null);
+  }
+
+
   // test replication by doc IDs
   docs = makeDocs(1, 11);
   docs.push({

Modified: couchdb/branches/new_replicator/src/couchdb/couch_replicator_utils.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/new_replicator/src/couchdb/couch_replicator_utils.erl?rev=1002587&r1=1002586&r2=1002587&view=diff
==============================================================================
--- couchdb/branches/new_replicator/src/couchdb/couch_replicator_utils.erl (original)
+++ couchdb/branches/new_replicator/src/couchdb/couch_replicator_utils.erl Wed Sep 29 12:06:34 2010
@@ -50,12 +50,23 @@ make_replication_id(Source, Target, User
                 [DocIds]
             end;
         Filter ->
-            [Filter, ?getv(query_params, Options, {[]})]
+            [filter_code(Filter, Source, UserCtx),
+                ?getv(query_params, Options, {[]})]
         end,
     Extension = maybe_append_options([continuous, create_target], Options),
     {couch_util:to_hex(couch_util:md5(term_to_binary(Base))), Extension}.
 
 
+filter_code(Filter, Source, UserCtx) ->
+    {match, [DDocName, FilterName]} =
+        re:run(Filter, "(.*?)/(.*)", [{capture, [1, 2], binary}]),
+    {ok, Db} = couch_api_wrap:db_open(Source, [{user_ctx, UserCtx}]),
+    {ok, #doc{body = Body}} =
+        couch_api_wrap:open_doc(Db, <<"_design/", DDocName/binary>>, []),
+    Code = couch_util:get_nested_json_value(Body, [<<"filters">>, FilterName]),
+    re:replace(Code, "^\s*(.*?)\s*$", "\\1", [{return, binary}]).
+
+
 maybe_append_options(Options, RepOptions) ->
     lists:foldl(fun(Option, Acc) ->
         Acc ++