diff options
Diffstat (limited to 'src/couchdb')
-rw-r--r-- | src/couchdb/couch_httpd_db.erl | 4 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_show.erl | 18 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_view.erl | 33 |
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); |