summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/couchdb/couch_httpd_db.erl4
-rw-r--r--src/couchdb/couch_httpd_show.erl18
-rw-r--r--src/couchdb/couch_httpd_view.erl33
3 files changed, 37 insertions, 18 deletions
diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl
index c00fd873..f5bebc20 100644
--- a/src/couchdb/couch_httpd_db.erl
+++ b/src/couchdb/couch_httpd_db.erl
@@ -407,7 +407,7 @@ db_req(#httpd{method='GET',path_parts=[_,<<"_all_docs_by_seq">>]}=Req, Db) ->
end
},
FoldlFun({{Seq, Id}, Json}, Offset, Acc)
- end, {Limit, SkipCount, undefined, []}),
+ end, {Limit, SkipCount, undefined, [], nil}),
couch_httpd_view:finish_view_fold(Req, TotalRowCount, {ok, FoldResult})
end);
@@ -489,7 +489,7 @@ all_docs_view(Req, Db, Keys) ->
StartId = if is_binary(StartKey) -> StartKey;
true -> StartDocId
end,
- FoldAccInit = {Limit, SkipCount, undefined, []},
+ FoldAccInit = {Limit, SkipCount, undefined, [], nil},
case Keys of
nil ->
diff --git a/src/couchdb/couch_httpd_show.erl b/src/couchdb/couch_httpd_show.erl
index 854b3d80..c29d89c5 100644
--- a/src/couchdb/couch_httpd_show.erl
+++ b/src/couchdb/couch_httpd_show.erl
@@ -146,7 +146,7 @@ output_map_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, Quer
start_response = StartListRespFun,
send_row = SendListRowFun
}),
- FoldAccInit = {Limit, SkipCount, undefined, []},
+ FoldAccInit = {Limit, SkipCount, undefined, [], nil},
{ok, FoldResult} = couch_view:fold(View, Start, Dir, FoldlFun, FoldAccInit),
finish_list(Req, QueryServer, CurrentEtag, FoldResult, StartListRespFun, RowCount)
end);
@@ -171,7 +171,7 @@ output_map_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, Quer
StartListRespFun = make_map_start_resp_fun(QueryServer, Db),
SendListRowFun = make_map_send_row_fun(QueryServer),
- FoldAccInit = {Limit, SkipCount, undefined, []},
+ FoldAccInit = {Limit, SkipCount, undefined, [], nil},
{ok, FoldResult} = lists:foldl(
fun(Key, {ok, FoldAcc}) ->
FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs#view_query_args{
@@ -317,16 +317,22 @@ output_reduce_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, Q
end).
finish_list(Req, QueryServer, Etag, FoldResult, StartFun, TotalRows) ->
- case FoldResult of
- {_, _, undefined, _} ->
+ FoldResult2 = case FoldResult of
+ {Limit, SkipCount, Response, RowAcc} ->
+ {Limit, SkipCount, Response, RowAcc, nil};
+ Else ->
+ Else
+ end,
+ case FoldResult2 of
+ {_, _, undefined, _, _} ->
{ok, Resp, BeginBody} =
render_head_for_empty_list(StartFun, Req, Etag, TotalRows),
[<<"end">>, Chunks] = couch_query_servers:render_list_tail(QueryServer),
Chunk = BeginBody ++ ?b2l(?l2b(Chunks)),
send_non_empty_chunk(Resp, Chunk);
- {_, _, Resp, stop} ->
+ {_, _, Resp, stop, _} ->
ok;
- {_, _, Resp, _} ->
+ {_, _, Resp, _, _} ->
[<<"end">>, Chunks] = couch_query_servers:render_list_tail(QueryServer),
send_non_empty_chunk(Resp, ?b2l(?l2b(Chunks)))
end,
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);