couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kocol...@apache.org
Subject svn commit: r808740 - in /couchdb/branches/0.10.x: ./ etc/default/couchdb share/www/script/test/changes.js src/couchdb/couch_httpd_db.erl
Date Fri, 28 Aug 2009 02:53:34 GMT
Author: kocolosk
Date: Fri Aug 28 02:53:33 2009
New Revision: 808740

URL: http://svn.apache.org/viewvc?rev=808740&view=rev
Log:
send deleted docs to changes filters and protect against missing filters

merges r808574,r808716 from trunk.  Thanks Jan for identifying the bugs and
writing the tests.

Modified:
    couchdb/branches/0.10.x/   (props changed)
    couchdb/branches/0.10.x/etc/default/couchdb   (props changed)
    couchdb/branches/0.10.x/share/www/script/test/changes.js
    couchdb/branches/0.10.x/src/couchdb/couch_httpd_db.erl

Propchange: couchdb/branches/0.10.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Aug 28 02:53:33 2009
@@ -3,4 +3,4 @@
 /couchdb/branches/form:729440-730015
 /couchdb/branches/list-iterator:782292-784593
 /couchdb/branches/tail_header:775760-778477
-/couchdb/trunk:807208-807478,807771,808632
+/couchdb/trunk:807208-807478,807771,808574,808632,808716

Propchange: couchdb/branches/0.10.x/etc/default/couchdb
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Aug 28 02:53:33 2009
@@ -3,5 +3,5 @@
 /couchdb/branches/form/etc/default/couchdb:729440-730015
 /couchdb/branches/list-iterator/etc/default/couchdb:782292-784593
 /couchdb/branches/tail_header/etc/default/couchdb:775760-778477
-/couchdb/trunk/etc/default/couchdb:807208-807478,807771,808632
+/couchdb/trunk/etc/default/couchdb:807208-807478,807771,808574,808632,808716
 /incubator/couchdb/trunk/etc/default/couchdb:642419-694440

Modified: couchdb/branches/0.10.x/share/www/script/test/changes.js
URL: http://svn.apache.org/viewvc/couchdb/branches/0.10.x/share/www/script/test/changes.js?rev=808740&r1=808739&r2=808740&view=diff
==============================================================================
--- couchdb/branches/0.10.x/share/www/script/test/changes.js (original)
+++ couchdb/branches/0.10.x/share/www/script/test/changes.js Fri Aug 28 02:53:33 2009
@@ -188,6 +188,33 @@
   req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/dynamic&field=bop");
   resp = JSON.parse(req.responseText);
   T(resp.results.length == 1);
+
+  // error conditions
+
+  // non-existing design doc
+  var req = CouchDB.request("GET", 
+    "/test_suite_db/_changes?filter=nothingtosee/bop");
+  TEquals(400, req.status, "should return 400 for non existant design doc");
+
+  // non-existing filter 
+  var req = CouchDB.request("GET", 
+    "/test_suite_db/_changes?filter=changes_filter/movealong");
+  TEquals(400, req.status, "should return 400 for non existant filter fun");
+
+  // both
+  var req = CouchDB.request("GET", 
+    "/test_suite_db/_changes?filter=nothingtosee/movealong");
+  TEquals(400, req.status, 
+    "should return 400 for non existant design doc and filter fun");
+
+  // changes get all_docs style with deleted docs
+  var doc = {a:1};
+  db.save(doc);
+  db.deleteDoc(doc);
+  var req = CouchDB.request("GET", 
+    "/test_suite_db/_changes?filter=changes_filter/bop&style=all_docs");
+  var resp = JSON.parse(req.responseText);
+  TEquals(1, resp.results.length, "should return one result row");
   
   // test for userCtx
   run_on_modified_server(

Modified: couchdb/branches/0.10.x/src/couchdb/couch_httpd_db.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/0.10.x/src/couchdb/couch_httpd_db.erl?rev=808740&r1=808739&r2=808740&view=diff
==============================================================================
--- couchdb/branches/0.10.x/src/couchdb/couch_httpd_db.erl (original)
+++ couchdb/branches/0.10.x/src/couchdb/couch_httpd_db.erl Fri Aug 28 02:53:33 2009
@@ -72,6 +72,7 @@
     send_chunk(Resp, "{\"results\":[\n").
 
 handle_changes_req(#httpd{method='GET',path_parts=[DbName|_]}=Req, Db) ->
+    {FilterFun, EndFilterFun} = make_filter_funs(Req, Db),
     StartSeq = list_to_integer(couch_httpd:qs_value(Req, "since", "0")),
     {ok, Resp} = start_json_response(Req, 200),
     ResponseType = couch_httpd:qs_value(Req, "feed", "normal"),
@@ -88,14 +89,16 @@
         couch_stats_collector:track_process_count(Self,
                             {httpd, clients_requesting_changes}),
         try
-            keep_sending_changes(Req, Resp, Db, StartSeq, <<"">>, Timeout, TimeoutFun,
ResponseType)
+            keep_sending_changes(Req, Resp, Db, StartSeq, <<"">>, Timeout,
+                TimeoutFun, ResponseType, FilterFun, EndFilterFun)
         after
             couch_db_update_notifier:stop(Notify),
             get_rest_db_updated() % clean out any remaining update messages
         end;
     true ->
         {ok, {LastSeq, _Prepend, _, _, _}} =
-                send_changes(Req, Resp, Db, StartSeq, <<"">>, "normal"),
+                send_changes(Req, Resp, Db, StartSeq, <<"">>, "normal",
+                    FilterFun, EndFilterFun),
         end_sending_changes(Resp, LastSeq, ResponseType)
     end;
 
@@ -125,9 +128,9 @@
     end_json_response(Resp).
 
 keep_sending_changes(#httpd{user_ctx=UserCtx,path_parts=[DbName|_]}=Req, Resp,
-        Db, StartSeq, Prepend, Timeout, TimeoutFun, ResponseType) ->
+        Db, StartSeq, Prepend, Timeout, TimeoutFun, ResponseType, Filter, End) ->
     {ok, {EndSeq, Prepend2, _, _, _}} = send_changes(Req, Resp, Db, StartSeq,
-        Prepend, ResponseType),
+        Prepend, ResponseType, Filter, End),
     couch_db:close(Db),
     if
     EndSeq > StartSeq, ResponseType == "longpoll" ->
@@ -136,7 +139,8 @@
         case wait_db_updated(Timeout, TimeoutFun) of
         updated ->
             {ok, Db2} = couch_db:open(DbName, [{user_ctx, UserCtx}]),
-            keep_sending_changes(Req, Resp, Db2, EndSeq, Prepend2, Timeout, TimeoutFun, ResponseType);
+            keep_sending_changes(Req, Resp, Db2, EndSeq, Prepend2, Timeout,
+                TimeoutFun, ResponseType, Filter, End);
         stop ->
             end_sending_changes(Resp, EndSeq, ResponseType)
         end
@@ -167,15 +171,14 @@
         {ok, {Seq, <<",\n">>, FilterFun, Resp, nil}}
     end.
 
-send_changes(Req, Resp, Db, StartSeq, Prepend, ResponseType) ->
+send_changes(Req, Resp, Db, StartSeq, Prepend, ResponseType, FilterFun, End) ->
     Style = list_to_existing_atom(
             couch_httpd:qs_value(Req, "style", "main_only")),
-    {FilterFun, EndFilterFun} = make_filter_funs(Req, Db),
     try
         couch_db:changes_since(Db, Style, StartSeq, fun changes_enumerator/2,
             {StartSeq, Prepend, FilterFun, Resp, ResponseType})
     after
-        EndFilterFun()
+        End()
     end.
 
 make_filter_funs(Req, Db) ->
@@ -189,24 +192,33 @@
         fun() -> ok end};
     [DName, FName] ->
         DesignId = <<"_design/", DName/binary>>,
-        #doc{body={Props}} = couch_httpd_db:couch_doc_open(Db, DesignId, nil, []),
-        Lang = proplists:get_value(<<"language">>, Props, <<"javascript">>),
-        FilterSrc = couch_util:get_nested_json_value({Props}, [<<"filters">>,
FName]),
-        {ok, Pid} = couch_query_servers:start_filter(Lang, FilterSrc),
-        FilterFun = fun(DInfo = #doc_info{revs=[#rev_info{rev=Rev}|_]}) ->
-            {ok, Doc} = couch_db:open_doc(Db, DInfo),
-            {ok, Pass} = couch_query_servers:filter_doc(Pid, Doc, Req, Db),
-            case Pass of
-            true ->
-                {[{rev, couch_doc:rev_to_str(Rev)}]};
-            false ->
-                null
-            end
-        end,
-        EndFilterFun = fun() ->
-            couch_query_servers:end_filter(Pid)
-        end,
-        {FilterFun, EndFilterFun};
+        case couch_db:open_doc(Db, DesignId) of
+        {ok, #doc{body={Props}}} ->
+            FilterSrc = try couch_util:get_nested_json_value({Props},
+                [<<"filters">>, FName])
+            catch
+            throw:{not_found, _} ->
+                throw({bad_request, "invalid filter function"})
+            end,
+            Lang = proplists:get_value(<<"language">>, Props, <<"javascript">>),
+            {ok, Pid} = couch_query_servers:start_filter(Lang, FilterSrc),
+            FilterFun = fun(DInfo = #doc_info{revs=[#rev_info{rev=Rev}|_]}) ->
+                {ok, Doc} = couch_db:open_doc(Db, DInfo, [deleted]),
+                {ok, Pass} = couch_query_servers:filter_doc(Pid, Doc, Req, Db),
+                case Pass of
+                true ->
+                    {[{rev, couch_doc:rev_to_str(Rev)}]};
+                false ->
+                    null
+                end
+            end,
+            EndFilterFun = fun() ->
+                couch_query_servers:end_filter(Pid)
+            end,
+            {FilterFun, EndFilterFun};
+        _Error ->
+            throw({bad_request, "invalid design doc"})
+        end;
     _Else ->
         throw({bad_request, 
             "filter parameter must be of the form `designname/filtername`"})



Mime
View raw message