summaryrefslogtreecommitdiff
path: root/src/couchdb/couch_httpd_view.erl
diff options
context:
space:
mode:
authorJohn Christopher Anderson <jchris@apache.org>2009-01-23 00:53:05 +0000
committerJohn Christopher Anderson <jchris@apache.org>2009-01-23 00:53:05 +0000
commit0a46c330072a3811d98a5c989d4c6486cff83df2 (patch)
treec3eaab8bc703fd0b4c375d70efb1eea42d68a1ed /src/couchdb/couch_httpd_view.erl
parent3e12deff5c0f87eefcd3de8dbf93a9724e98258e (diff)
View list functions can stream views in any format. See list_views test for details.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@736876 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/couchdb/couch_httpd_view.erl')
-rw-r--r--src/couchdb/couch_httpd_view.erl100
1 files changed, 74 insertions, 26 deletions
diff --git a/src/couchdb/couch_httpd_view.erl b/src/couchdb/couch_httpd_view.erl
index dca1e6e3..06d89a59 100644
--- a/src/couchdb/couch_httpd_view.erl
+++ b/src/couchdb/couch_httpd_view.erl
@@ -15,7 +15,8 @@
-export([handle_view_req/2,handle_slow_view_req/2]).
--export([parse_view_query/1,parse_view_query/2,make_view_fold_fun/5, make_view_fold_fun/6,finish_view_fold/3]).
+-export([parse_view_query/1,parse_view_query/2,make_view_fold_fun/5,
+ finish_view_fold/3, view_row_obj/3]).
-import(couch_httpd,
[send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,
@@ -92,8 +93,7 @@ output_map_view(Req, View, Db, QueryArgs, nil) ->
} = QueryArgs,
{ok, RowCount} = couch_view:get_row_count(View),
Start = {StartKey, StartDocId},
- FoldlFun = make_view_fold_fun(Req, QueryArgs, Db, RowCount,
- fun couch_view:reduce_to_count/1),
+ FoldlFun = make_view_fold_fun(Req, QueryArgs, Db, RowCount, #view_fold_helper_funs{reduce_count=fun couch_view:reduce_to_count/1}),
FoldAccInit = {Limit, SkipCount, undefined, []},
FoldResult = couch_view:fold(View, Start, Dir, FoldlFun, FoldAccInit),
finish_view_fold(Req, RowCount, FoldResult);
@@ -114,7 +114,10 @@ output_map_view(Req, View, Db, QueryArgs, Keys) ->
QueryArgs#view_query_args{
start_key = Key,
end_key = Key
- }, Db, RowCount, fun couch_view:reduce_to_count/1),
+ }, Db, RowCount,
+ #view_fold_helper_funs{
+ reduce_count = fun couch_view:reduce_to_count/1
+ }),
couch_view:fold(View, Start, Dir, FoldlFun, FoldAcc)
end, {ok, FoldAccInit}, Keys),
finish_view_fold(Req, RowCount, FoldResult).
@@ -362,28 +365,21 @@ parse_view_query(Req, Keys, IsReduce) ->
end
end.
-
make_view_fold_fun(Req, QueryArgs, Db,
- TotalViewCount, ReduceCountFun) ->
+ TotalViewCount, HelperFuns) ->
#view_query_args{
end_key = EndKey,
end_docid = EndDocId,
direction = Dir
} = QueryArgs,
- PassedEndFun =
- case Dir of
- fwd ->
- fun(ViewKey, ViewId) ->
- couch_view:less_json([EndKey, EndDocId], [ViewKey, ViewId])
- end;
- rev->
- fun(ViewKey, ViewId) ->
- couch_view:less_json([ViewKey, ViewId], [EndKey, EndDocId])
- end
- end,
- make_view_fold_fun(Req, QueryArgs, Db, TotalViewCount, ReduceCountFun, PassedEndFun).
+
+ #view_fold_helper_funs{
+ passed_end = PassedEndFun,
+ start_response = StartRespFun,
+ send_row = SendRowFun,
+ reduce_count = ReduceCountFun
+ } = apply_default_helper_funs(HelperFuns, {Dir, EndKey, EndDocId}),
-make_view_fold_fun(Req, QueryArgs, Db, TotalViewCount, ReduceCountFun, PassedEndFun) ->
#view_query_args{
include_docs = IncludeDocs
} = QueryArgs,
@@ -401,20 +397,72 @@ make_view_fold_fun(Req, QueryArgs, Db, TotalViewCount, ReduceCountFun, PassedEnd
{_, _, AccSkip, _} when AccSkip > 0 ->
{ok, {AccLimit, AccSkip - 1, Resp, AccRevRows}};
{_, _, _, undefined} ->
- {ok, Resp2} = start_json_response(Req, 200),
Offset = ReduceCountFun(OffsetReds),
- JsonBegin = io_lib:format("{\"total_rows\":~w,\"offset\":~w,\"rows\":[\r\n",
- [TotalViewCount, Offset]),
- JsonObj = view_row_obj(Db, {{Key, DocId}, Value}, IncludeDocs),
- send_chunk(Resp2, JsonBegin ++ ?JSON_ENCODE(JsonObj)),
+ {ok, Resp2, BeginBody} = StartRespFun(Req, 200,
+ TotalViewCount, Offset),
+ SendRowFun(Resp2, Db,
+ {{Key, DocId}, Value}, BeginBody, IncludeDocs),
{ok, {AccLimit - 1, 0, Resp2, AccRevRows}};
{_, AccLimit, _, Resp} when (AccLimit > 0) ->
- JsonObj = view_row_obj(Db, {{Key, DocId}, Value}, IncludeDocs),
- send_chunk(Resp, ",\r\n" ++ ?JSON_ENCODE(JsonObj)),
+ SendRowFun(Resp, Db,
+ {{Key, DocId}, Value}, nil, IncludeDocs),
{ok, {AccLimit - 1, 0, Resp, AccRevRows}}
end
end.
+apply_default_helper_funs(#view_fold_helper_funs{
+ passed_end = PassedEnd,
+ start_response = StartResp,
+ send_row = SendRow
+}=Helpers, {Dir, EndKey, EndDocId}) ->
+ PassedEnd2 = case PassedEnd of
+ undefined -> make_passed_end_fun(Dir, EndKey, EndDocId);
+ _ -> PassedEnd
+ end,
+
+ StartResp2 = case StartResp of
+ undefined -> fun json_view_start_resp/4;
+ _ -> StartResp
+ end,
+
+ SendRow2 = case SendRow of
+ undefined -> fun send_json_view_row/5;
+ _ -> SendRow
+ end,
+
+ Helpers#view_fold_helper_funs{
+ passed_end = PassedEnd2,
+ start_response = StartResp2,
+ send_row = SendRow2
+ }.
+
+make_passed_end_fun(Dir, EndKey, EndDocId) ->
+ case Dir of
+ fwd ->
+ fun(ViewKey, ViewId) ->
+ couch_view:less_json([EndKey, EndDocId], [ViewKey, ViewId])
+ end;
+ rev->
+ fun(ViewKey, ViewId) ->
+ couch_view:less_json([ViewKey, ViewId], [EndKey, EndDocId])
+ end
+ end.
+
+json_view_start_resp(Req, Code, TotalViewCount, Offset) ->
+ {ok, Resp} = couch_httpd:start_json_response(Req, Code),
+ BeginBody = io_lib:format("{\"total_rows\":~w,\"offset\":~w,\"rows\":[\r\n",
+ [TotalViewCount, Offset]),
+ {ok, Resp, BeginBody}.
+
+send_json_view_row(Resp, Db, {{Key, DocId}, Value}, RowFront, IncludeDocs) ->
+ JsonObj = view_row_obj(Db, {{Key, DocId}, Value}, IncludeDocs),
+ RowFront2 = case RowFront of
+ nil -> ",\r\n";
+ _ -> RowFront
+ end,
+ send_chunk(Resp, RowFront2 ++ ?JSON_ENCODE(JsonObj)).
+
+
view_row_obj(Db, {{Key, DocId}, Value}, IncludeDocs) ->
case DocId of
error ->