summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Kocoloski <adam@cloudant.com>2010-06-25 21:24:24 -0400
committerAdam Kocoloski <adam@cloudant.com>2010-08-12 11:18:46 -0400
commitde56d07198d5b52c461a0eef4c91c9a02d433310 (patch)
treef3bfe23a1e6dbab19a8e0128ee61fc2ebc024fff
parentf1e8fb2466468f6a3d8508de536fbb5a2760b411 (diff)
basic support for filtered _changes
-rw-r--r--src/chttpd_db.erl31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/chttpd_db.erl b/src/chttpd_db.erl
index 211eed2d..8a152372 100644
--- a/src/chttpd_db.erl
+++ b/src/chttpd_db.erl
@@ -47,7 +47,8 @@ handle_request(#httpd{path_parts=[DbName|RestParts],method=Method,
end.
handle_changes_req(#httpd{method='GET'}=Req, Db) ->
- ChangesArgs = parse_changes_query(Req),
+ #changes_args{filter=Filter} = Args0 = parse_changes_query(Req),
+ ChangesArgs = Args0#changes_args{filter=make_filter_fun(Filter, Req, Db)},
case ChangesArgs#changes_args.feed of
"normal" ->
T0 = now(),
@@ -799,6 +800,34 @@ parse_changes_query(Req) ->
end
end, #changes_args{}, chttpd:qs(Req)).
+make_filter_fun(Filter, _, _) when is_function(Filter, 1) ->
+ Filter;
+make_filter_fun(FilterName, Req, Db) ->
+ case [?l2b(chttpd:unquote(X)) || X <- string:tokens(FilterName, "/")] of
+ [DName, FName] ->
+ case fabric:open_doc(Db, <<"_design/", DName/binary>>, []) of
+ {ok, #doc{body={Props}} = DDoc} ->
+ couch_util:get_nested_json_value({Props}, [<<"filters">>, FName]),
+ JsonReq = chttpd_external:json_req_obj(Req, Db),
+ fun(DocInfos) ->
+ Docs = [Doc || {ok, Doc} <- [
+ {ok, _Doc} = fabric:open_doc(Db, Id, [deleted, conflicts])
+ || #doc_info{id=Id} <- DocInfos]],
+ {ok, Passes} = couch_query_servers:filter_docs(
+ {json_req,JsonReq}, Db, DDoc, FName, Docs
+ ),
+ [{[{<<"rev">>, couch_doc:rev_to_str(Rev)}]}
+ || #doc_info{revs=[#rev_info{rev=Rev}|_]} <- DocInfos,
+ Pass <- Passes, Pass == true]
+ end;
+ Error ->
+ throw(Error)
+ end;
+ _Else ->
+ throw({bad_request,
+ "filter parameter must be of the form `designname/filtername`"})
+ end.
+
extract_header_rev(Req, ExplicitRev) when is_binary(ExplicitRev) or is_list(ExplicitRev)->
extract_header_rev(Req, couch_doc:parse_rev(ExplicitRev));
extract_header_rev(Req, ExplicitRev) ->