From 4158b51580cb27cbe143384f1ca41ac18c9ea0cb Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Thu, 10 Feb 2011 08:11:01 +0000 Subject: Merged revision 1069262 from trunk More efficient _changes?include_docs=true and _all_docs?include_docs=true Closes COUCHDB-1061 git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1069264 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/couch_changes.erl | 23 ++++++++++++----------- src/couchdb/couch_httpd_db.erl | 37 +++++++++++++++++++++++++++++-------- src/couchdb/couch_httpd_view.erl | 8 ++++++++ 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/couchdb/couch_changes.erl b/src/couchdb/couch_changes.erl index 838f7e66..6baaf7ec 100644 --- a/src/couchdb/couch_changes.erl +++ b/src/couchdb/couch_changes.erl @@ -261,8 +261,7 @@ end_sending_changes(Callback, UserAcc, EndSeq, ResponseType) -> changes_enumerator(DocInfo, {Db, _, _, FilterFun, Callback, UserAcc, "continuous", Limit, IncludeDocs}) -> - #doc_info{id=Id, high_seq=Seq, - revs=[#rev_info{deleted=Del,rev=Rev}|_]} = DocInfo, + #doc_info{high_seq = Seq} = DocInfo, Results0 = FilterFun(DocInfo), Results = [Result || Result <- Results0, Result /= null], Go = if Limit =< 1 -> stop; true -> ok end, @@ -272,7 +271,7 @@ changes_enumerator(DocInfo, {Db, _, _, FilterFun, Callback, UserAcc, IncludeDocs} }; _ -> - ChangesRow = changes_row(Db, Seq, Id, Del, Results, Rev, IncludeDocs), + ChangesRow = changes_row(Db, Results, DocInfo, IncludeDocs), UserAcc2 = Callback({change, ChangesRow, <<>>}, "continuous", UserAcc), {Go, {Db, Seq, nil, FilterFun, Callback, UserAcc2, "continuous", Limit - 1, IncludeDocs} @@ -281,8 +280,7 @@ changes_enumerator(DocInfo, {Db, _, _, FilterFun, Callback, UserAcc, changes_enumerator(DocInfo, {Db, _, Prepend, FilterFun, Callback, UserAcc, ResponseType, Limit, IncludeDocs}) -> - #doc_info{id=Id, high_seq=Seq, revs=[#rev_info{deleted=Del,rev=Rev}|_]} - = DocInfo, + #doc_info{high_seq = Seq} = DocInfo, Results0 = FilterFun(DocInfo), Results = [Result || Result <- Results0, Result /= null], Go = if (Limit =< 1) andalso Results =/= [] -> stop; true -> ok end, @@ -292,7 +290,7 @@ changes_enumerator(DocInfo, {Db, _, Prepend, FilterFun, Callback, UserAcc, Limit, IncludeDocs} }; _ -> - ChangesRow = changes_row(Db, Seq, Id, Del, Results, Rev, IncludeDocs), + ChangesRow = changes_row(Db, Results, DocInfo, IncludeDocs), UserAcc2 = Callback({change, ChangesRow, Prepend}, ResponseType, UserAcc), {Go, {Db, Seq, <<",\n">>, FilterFun, Callback, UserAcc2, ResponseType, Limit - 1, IncludeDocs} @@ -300,12 +298,15 @@ changes_enumerator(DocInfo, {Db, _, Prepend, FilterFun, Callback, UserAcc, end. -changes_row(Db, Seq, Id, Del, Results, Rev, true) -> +changes_row(Db, Results, DocInfo, IncludeDoc) -> + #doc_info{ + id = Id, high_seq = Seq, revs = [#rev_info{deleted = Del} | _] + } = DocInfo, {[{<<"seq">>, Seq}, {<<"id">>, Id}, {<<"changes">>, Results}] ++ - deleted_item(Del) ++ couch_httpd_view:doc_member(Db, {Id, Rev})}; -changes_row(_, Seq, Id, Del, Results, _, false) -> - {[{<<"seq">>, Seq}, {<<"id">>, Id}, {<<"changes">>, Results}] ++ - deleted_item(Del)}. + deleted_item(Del) ++ case IncludeDoc of + true -> couch_httpd_view:doc_member(Db, DocInfo); + false -> [] + end}. deleted_item(true) -> [{<<"deleted">>, true}]; deleted_item(_) -> []. diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index a051402b..9aa91277 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -505,12 +505,13 @@ all_docs_view(Req, Db, Keys) -> nil -> FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, CurrentEtag, Db, UpdateSeq, TotalRowCount, #view_fold_helper_funs{ - reduce_count = fun couch_db:enum_docs_reduce_to_count/1 + reduce_count = fun couch_db:enum_docs_reduce_to_count/1, + send_row = fun all_docs_send_json_view_row/5 }), AdapterFun = fun(#full_doc_info{id=Id}=FullDocInfo, Offset, Acc) -> case couch_doc:to_doc_info(FullDocInfo) of - #doc_info{revs=[#rev_info{deleted=false, rev=Rev}|_]} -> - FoldlFun({{Id, Id}, {[{rev, couch_doc:rev_to_str(Rev)}]}}, Offset, Acc); + #doc_info{revs=[#rev_info{deleted=false}|_]} = DocInfo -> + FoldlFun({{Id, Id}, DocInfo}, Offset, Acc); #doc_info{revs=[#rev_info{deleted=true}|_]} -> {ok, Acc} end @@ -522,7 +523,8 @@ all_docs_view(Req, Db, Keys) -> _ -> FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, CurrentEtag, Db, UpdateSeq, TotalRowCount, #view_fold_helper_funs{ - reduce_count = fun(Offset) -> Offset end + reduce_count = fun(Offset) -> Offset end, + send_row = fun all_docs_send_json_view_row/5 }), KeyFoldFun = case Dir of fwd -> @@ -534,10 +536,8 @@ all_docs_view(Req, Db, Keys) -> fun(Key, FoldAcc) -> DocInfo = (catch couch_db:get_doc_info(Db, Key)), Doc = case DocInfo of - {ok, #doc_info{id=Id, revs=[#rev_info{deleted=false, rev=Rev}|_]}} -> - {{Id, Id}, {[{rev, couch_doc:rev_to_str(Rev)}]}}; - {ok, #doc_info{id=Id, revs=[#rev_info{deleted=true, rev=Rev}|_]}} -> - {{Id, Id}, {[{rev, couch_doc:rev_to_str(Rev)}, {deleted, true}]}}; + {ok, #doc_info{id = Id} = Di} -> + {{Id, Id}, Di}; not_found -> {{Key, error}, not_found}; _ -> @@ -551,6 +551,27 @@ all_docs_view(Req, Db, Keys) -> end end). +all_docs_send_json_view_row(Resp, Db, KV, IncludeDocs, RowFront) -> + JsonRow = all_docs_view_row_obj(Db, KV, IncludeDocs), + send_chunk(Resp, RowFront ++ ?JSON_ENCODE(JsonRow)), + {ok, ",\r\n"}. + +all_docs_view_row_obj(_Db, {{DocId, error}, Value}, _IncludeDocs) -> + {[{key, DocId}, {error, Value}]}; +all_docs_view_row_obj(Db, {_KeyDocId, DocInfo}, true) -> + {all_docs_row(DocInfo) ++ couch_httpd_view:doc_member(Db, DocInfo)}; +all_docs_view_row_obj(_Db, {_KeyDocId, DocInfo}, _IncludeDocs) -> + {all_docs_row(DocInfo)}. + +all_docs_row(#doc_info{id = Id, revs = [RevInfo | _]}) -> + #rev_info{rev = Rev, deleted = Del} = RevInfo, + [ {id, Id}, {key, Id}, + {value, {[{rev, couch_doc:rev_to_str(Rev)}] ++ case Del of + true -> [{deleted, true}]; + false -> [] + end}} ]. + + db_doc_req(#httpd{method='DELETE'}=Req, Db, DocId) -> % check for the existence of the doc to handle the 404 case. couch_doc_open(Db, DocId, nil, []), diff --git a/src/couchdb/couch_httpd_view.erl b/src/couchdb/couch_httpd_view.erl index 8656c43e..8906de70 100644 --- a/src/couchdb/couch_httpd_view.erl +++ b/src/couchdb/couch_httpd_view.erl @@ -660,6 +660,14 @@ view_row_obj(_Db, {{Key, DocId}, Value}, _IncludeDocs) -> view_row_with_doc(Db, {{Key, DocId}, Value}, IdRev) -> {[{id, DocId}, {key, Key}, {value, Value}] ++ doc_member(Db, IdRev)}. +doc_member(Db, #doc_info{id = Id, revs = [#rev_info{rev = Rev} | _]} = Info) -> + ?LOG_DEBUG("Include Doc: ~p ~p", [Id, Rev]), + case couch_db:open_doc(Db, Info, [deleted]) of + {ok, Doc} -> + [{doc, couch_doc:to_json_obj(Doc, [])}]; + _ -> + [{doc, null}] + end; doc_member(Db, {DocId, Rev}) -> ?LOG_DEBUG("Include Doc: ~p ~p", [DocId, Rev]), case (catch couch_httpd_db:couch_doc_open(Db, DocId, Rev, [])) of -- cgit v1.2.3