summaryrefslogtreecommitdiff
path: root/src/couchdb/couch_httpd_view.erl
diff options
context:
space:
mode:
authorPaul Joseph Davis <davisp@apache.org>2009-07-08 01:33:00 +0000
committerPaul Joseph Davis <davisp@apache.org>2009-07-08 01:33:00 +0000
commit02cb712e18ee5647517fc38b6aa0c188af090894 (patch)
tree952b52231a0266bbe9db53a3043fd2adcc68e0da /src/couchdb/couch_httpd_view.erl
parent6012a3374081d92eaade74b15f1c072aaa6ec09f (diff)
Fixes COUCHDB-389
Provide an offset calculation for all view responses. Thanks Brad Anderson. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@792013 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/couchdb/couch_httpd_view.erl')
-rw-r--r--src/couchdb/couch_httpd_view.erl33
1 files changed, 23 insertions, 10 deletions
diff --git a/src/couchdb/couch_httpd_view.erl b/src/couchdb/couch_httpd_view.erl
index c0d7be7f..2028840c 100644
--- a/src/couchdb/couch_httpd_view.erl
+++ b/src/couchdb/couch_httpd_view.erl
@@ -109,7 +109,7 @@ output_map_view(Req, View, Group, Db, QueryArgs, nil) ->
{ok, RowCount} = couch_view:get_row_count(View),
Start = {StartKey, StartDocId},
FoldlFun = make_view_fold_fun(Req, QueryArgs, CurrentEtag, Db, RowCount, #view_fold_helper_funs{reduce_count=fun couch_view:reduce_to_count/1}),
- FoldAccInit = {Limit, SkipCount, undefined, []},
+ FoldAccInit = {Limit, SkipCount, undefined, [], nil},
FoldResult = couch_view:fold(View, Start, Dir, FoldlFun, FoldAccInit),
finish_view_fold(Req, RowCount, FoldResult)
end);
@@ -124,7 +124,7 @@ output_map_view(Req, View, Group, Db, QueryArgs, Keys) ->
CurrentEtag = view_group_etag(Group, Keys),
couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
{ok, RowCount} = couch_view:get_row_count(View),
- FoldAccInit = {Limit, SkipCount, undefined, []},
+ FoldAccInit = {Limit, SkipCount, undefined, [], nil},
FoldResult = lists:foldl(
fun(Key, {ok, FoldAcc}) ->
Start = {Key, StartDocId},
@@ -373,18 +373,26 @@ make_view_fold_fun(Req, QueryArgs, Etag, Db, TotalViewCount, HelperFuns) ->
include_docs = IncludeDocs
} = QueryArgs,
- fun({{Key, DocId}, Value}, OffsetReds, {AccLimit, AccSkip, Resp, RowFunAcc}) ->
+ fun({{Key, DocId}, Value}, OffsetReds, {AccLimit, AccSkip, Resp, RowFunAcc,
+ OffsetAcc}) ->
PassedEnd = PassedEndFun(Key, DocId),
case {PassedEnd, AccLimit, AccSkip, Resp} of
{true, _, _, _} ->
% The stop key has been passed, stop looping.
- {stop, {AccLimit, AccSkip, Resp, RowFunAcc}};
+ % We may need offset so calcluate it here.
+ % Checking Resp is an optimization that tells
+ % us its already been calculated (and sent).
+ NewOffset = case Resp of
+ undefined -> ReduceCountFun(OffsetReds);
+ _ -> nil
+ end,
+ {stop, {AccLimit, AccSkip, Resp, RowFunAcc, NewOffset}};
{_, 0, _, _} ->
% we've done "limit" rows, stop foldling
- {stop, {0, 0, Resp, RowFunAcc}};
+ {stop, {0, 0, Resp, RowFunAcc, OffsetAcc}};
{_, _, AccSkip, _} when AccSkip > 0 ->
% just keep skipping
- {ok, {AccLimit, AccSkip - 1, Resp, RowFunAcc}};
+ {ok, {AccLimit, AccSkip - 1, Resp, RowFunAcc, OffsetAcc}};
{_, _, _, undefined} ->
% rendering the first row, first we start the response
Offset = ReduceCountFun(OffsetReds),
@@ -392,12 +400,12 @@ make_view_fold_fun(Req, QueryArgs, Etag, Db, TotalViewCount, HelperFuns) ->
TotalViewCount, Offset, RowFunAcc),
{Go, RowFunAcc2} = SendRowFun(Resp2, Db, {{Key, DocId}, Value},
IncludeDocs, RowFunAcc0),
- {Go, {AccLimit - 1, 0, Resp2, RowFunAcc2}};
+ {Go, {AccLimit - 1, 0, Resp2, RowFunAcc2, Offset}};
{_, AccLimit, _, Resp} when (AccLimit > 0) ->
% rendering all other rows
{Go, RowFunAcc2} = SendRowFun(Resp, Db, {{Key, DocId}, Value},
IncludeDocs, RowFunAcc),
- {Go, {AccLimit - 1, 0, Resp, RowFunAcc2}}
+ {Go, {AccLimit - 1, 0, Resp, RowFunAcc2, OffsetAcc}}
end
end.
@@ -597,14 +605,19 @@ view_row_with_doc(Db, {{Key, DocId}, Value}, Rev) ->
finish_view_fold(Req, TotalRows, FoldResult) ->
case FoldResult of
- {ok, {_, _, undefined, _}} ->
+ {ok, {_, _, undefined, _, Offset}} ->
% nothing found in the view, nothing has been returned
% send empty view
+ NewOffset = case Offset of
+ nil -> TotalRows;
+ _ -> Offset
+ end,
send_json(Req, 200, {[
{total_rows, TotalRows},
+ {offset, NewOffset},
{rows, []}
]});
- {ok, {_, _, Resp, _}} ->
+ {ok, {_, _, Resp, _, _}} ->
% end the view
send_chunk(Resp, "\r\n]}"),
end_json_response(Resp);