From 2ceb29752aa4cf638d947ffab3eb5759d306afa4 Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Wed, 12 Aug 2009 20:07:06 +0000 Subject: rollback _conflicts view patch git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@803690 13f79535-47bb-0310-9956-ffa450edef68 --- share/www/script/couch.js | 12 +- share/www/script/couch_tests.js | 1 - share/www/script/test/view_builtin.js | 74 ------------ src/couchdb/couch_db.hrl | 3 +- src/couchdb/couch_httpd_db.erl | 211 ++++++++++------------------------ src/couchdb/couch_httpd_view.erl | 6 +- 6 files changed, 65 insertions(+), 242 deletions(-) delete mode 100644 share/www/script/test/view_builtin.js diff --git a/share/www/script/couch.js b/share/www/script/couch.js index eba60ad5..e902a730 100644 --- a/share/www/script/couch.js +++ b/share/www/script/couch.js @@ -191,18 +191,10 @@ function CouchDB(name, httpHeaders) { } this.allDocs = function(options,keys) { - return this.builtinView("_all_docs", options, keys) - } - - this.conflicts = function(options,keys) { - return this.builtinView("_conflicts", options, keys) - } - - this.builtinView = function(name, options, keys) { if(!keys) { - this.last_req = this.request("GET", this.uri + name + encodeOptions(options)); + this.last_req = this.request("GET", this.uri + "_all_docs" + encodeOptions(options)); } else { - this.last_req = this.request("POST", this.uri + name + encodeOptions(options), { + this.last_req = this.request("POST", this.uri + "_all_docs" + encodeOptions(options), { headers: {"Content-Type": "application/json"}, body: JSON.stringify({keys:keys}) }); diff --git a/share/www/script/couch_tests.js b/share/www/script/couch_tests.js index 7ddfa312..802db6f8 100644 --- a/share/www/script/couch_tests.js +++ b/share/www/script/couch_tests.js @@ -51,7 +51,6 @@ loadTest("design_paths.js"); loadTest("content_negotiation.js"); loadTest("design_docs.js"); loadTest("invalid_docids.js"); -loadTest("view_builtin.js"); loadTest("view_collation.js"); loadTest("view_conflicts.js"); loadTest("view_errors.js"); diff --git a/share/www/script/test/view_builtin.js b/share/www/script/test/view_builtin.js deleted file mode 100644 index c0f7b2e5..00000000 --- a/share/www/script/test/view_builtin.js +++ /dev/null @@ -1,74 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -couchTests.view_builtin = function(debug) { - var db = new CouchDB("test_suite_db"); - db.deleteDb(); - db.createDb(); - if (debug) debugger; - - // test _conflicts view - - // no rows - var result = db.conflicts(); - TEquals(0, result.rows.length, "should return 0 conflicts"); - - // one doc with a conflict - var doc_a = db.save({_id:"a", a:1}); - - // create conflict - var bulk_result = db.bulkSave([{_id:"a",a:2}], {all_or_nothing:true}); - var result = db.conflicts(); - TEquals(1, result.rows.length, "should return 1 conflicts"); - TEquals("a", result.rows[0].id, "should return row id 'a'"); - TEquals("a", result.rows[0].key, "should return row key 'a'"); - TEquals(bulk_result[0].rev, result.rows[0].rev, - "should return row key 'a'"); - - // multiple docs with conflicts - var doc_b = db.save({_id:"b", a:3}); - var bulk_result = db.bulkSave([{_id:"b",a:4}], {all_or_nothing:true}); - var result = db.conflicts(); - TEquals(2, result.rows.length, "should return 2 conflicts"); - - // key, startkey, endkey, skip & count - var result = db.conflicts({key:"b"}); - TEquals(1, result.rows.length, "should return 1 conflicts"); - - var result = db.conflicts({startkey:"b"}); - TEquals(1, result.rows.length, "should return 1 conflicts"); - - var result = db.conflicts({startkey:"a", endkey:"b"}); - TEquals(2, result.rows.length, "should return 2 conflicts"); - - var result = db.conflicts({startkey:"c"}); - TEquals(0, result.rows.length, "should return 0 conflicts"); - - var result = db.conflicts({limit:1}); - TEquals(1, result.rows.length, "should return 1 conflicts"); - - var result = db.conflicts({skip:1}); - TEquals(1, result.rows.length, "should return 1 conflicts"); - TEquals("b", result.rows[0].key, "should return row key 'b'"); - - // POST is not allowed yet - try { - var result = db.conflicts({}, ["a"]); - } catch (e) { - TEquals("method_not_allowed", e.error, "should not allow POST requests"); - } - - // multi key get - // var result = db.conflicts({}, ["a"]); - // TEquals(1, result.rows.length, "should return 1 conflicts"); - // TEquals("a", result.rows[0].key, "should return row key 'a'"); -}; diff --git a/src/couchdb/couch_db.hrl b/src/couchdb/couch_db.hrl index 46725ed1..a487300f 100644 --- a/src/couchdb/couch_db.hrl +++ b/src/couchdb/couch_db.hrl @@ -175,8 +175,7 @@ stale = false, multi_get = false, callback = nil, - list = nil, - deleted = false + list = nil }). -record(view_fold_helper_funs, { diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index c93c736d..159bcbe8 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -383,21 +383,74 @@ db_req(#httpd{method='GET',path_parts=[_,<<"_all_docs">>]}=Req, Db) -> all_docs_view(Req, Db, nil); db_req(#httpd{method='POST',path_parts=[_,<<"_all_docs">>]}=Req, Db) -> - post_keys_to_view(Req, Db, fun all_docs_view/3); + {Fields} = couch_httpd:json_body_obj(Req), + case proplists:get_value(<<"keys">>, Fields, nil) of + nil -> + ?LOG_DEBUG("POST to _all_docs with no keys member.", []), + all_docs_view(Req, Db, nil); + Keys when is_list(Keys) -> + all_docs_view(Req, Db, Keys); + _ -> + throw({bad_request, "`keys` member must be a array."}) + end; db_req(#httpd{path_parts=[_,<<"_all_docs">>]}=Req, _Db) -> send_method_not_allowed(Req, "GET,HEAD,POST"); db_req(#httpd{method='GET',path_parts=[_,<<"_all_docs_by_seq">>]}=Req, Db) -> - all_docs_by_seq_view(Req, Db); - -db_req(#httpd{path_parts=[_,<<"_all_docs_by_seq">>]}=Req, _Db) -> - send_method_not_allowed(Req, "GET,HEAD"); + #view_query_args{ + start_key = StartKey, + limit = Limit, + skip = SkipCount, + direction = Dir + } = QueryArgs = couch_httpd_view:parse_view_params(Req, nil, map), -db_req(#httpd{method='GET',path_parts=[_,<<"_conflicts">>]}=Req, Db) -> - conflicts_view(Req, Db, nil); + {ok, Info} = couch_db:get_db_info(Db), + CurrentEtag = couch_httpd:make_etag(Info), + couch_httpd:etag_respond(Req, CurrentEtag, fun() -> + TotalRowCount = proplists:get_value(doc_count, Info), + FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, CurrentEtag, Db, + TotalRowCount, #view_fold_helper_funs{ + reduce_count = fun couch_db:enum_docs_since_reduce_to_count/1 + }), + StartKey2 = case StartKey of + nil -> 0; + <<>> -> 100000000000; + {} -> 100000000000; + StartKey when is_integer(StartKey) -> StartKey + end, + {ok, FoldResult} = couch_db:enum_docs_since(Db, StartKey2, Dir, + fun(DocInfo, Offset, Acc) -> + #doc_info{ + id=Id, + high_seq=Seq, + revs=[#rev_info{rev=Rev,deleted=Deleted} | RestInfo] + } = DocInfo, + ConflictRevs = couch_doc:rev_to_strs( + [Rev1 || #rev_info{deleted=false, rev=Rev1} <- RestInfo]), + DelConflictRevs = couch_doc:rev_to_strs( + [Rev1 || #rev_info{deleted=true, rev=Rev1} <- RestInfo]), + Json = { + [{<<"rev">>, couch_doc:rev_to_str(Rev)}] ++ + case ConflictRevs of + [] -> []; + _ -> [{<<"conflicts">>, ConflictRevs}] + end ++ + case DelConflictRevs of + [] -> []; + _ -> [{<<"deleted_conflicts">>, DelConflictRevs}] + end ++ + case Deleted of + true -> [{<<"deleted">>, true}]; + false -> [] + end + }, + FoldlFun({{Seq, Id}, Json}, Offset, Acc) + end, {Limit, SkipCount, undefined, [], nil}), + couch_httpd_view:finish_view_fold(Req, TotalRowCount, {ok, FoldResult}) + end); -db_req(#httpd{path_parts=[_,<<"_conflicts">>]}=Req, _Db) -> +db_req(#httpd{path_parts=[_,<<"_all_docs_by_seq">>]}=Req, _Db) -> send_method_not_allowed(Req, "GET,HEAD"); db_req(#httpd{method='POST',path_parts=[_,<<"_missing_revs">>]}=Req, Db) -> @@ -458,18 +511,6 @@ db_req(#httpd{path_parts=[_, DocId]}=Req, Db) -> db_req(#httpd{path_parts=[_, DocId | FileNameParts]}=Req, Db) -> db_attachment_req(Req, Db, DocId, FileNameParts). -post_keys_to_view(Req, Db, ViewFun) -> - {Fields} = couch_httpd:json_body_obj(Req), - case proplists:get_value(<<"keys">>, Fields, nil) of - nil -> - ?LOG_DEBUG("POST to view with no keys member.", []), - ViewFun(Req, Db, nil); - Keys when is_list(Keys) -> - ViewFun(Req, Db, Keys); - _ -> - throw({bad_request, "`keys` member must be a array."}) - end. - all_docs_view(Req, Db, Keys) -> #view_query_args{ start_key = StartKey, @@ -556,136 +597,6 @@ all_docs_view(Req, Db, Keys) -> end end). -all_docs_by_seq_view(Req, Db) -> - #view_query_args{ - start_key = StartKey, - limit = Limit, - skip = SkipCount, - direction = Dir - } = QueryArgs = couch_httpd_view:parse_view_params(Req, nil, map), - - {ok, Info} = couch_db:get_db_info(Db), - CurrentEtag = couch_httpd:make_etag(Info), - couch_httpd:etag_respond(Req, CurrentEtag, fun() -> - TotalRowCount = proplists:get_value(doc_count, Info), - FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, CurrentEtag, Db, - TotalRowCount, #view_fold_helper_funs{ - reduce_count = fun couch_db:enum_docs_since_reduce_to_count/1 - }), - StartKey2 = case StartKey of - nil -> 0; - <<>> -> 100000000000; - {} -> 100000000000; - StartKey when is_integer(StartKey) -> StartKey - end, - {ok, FoldResult} = couch_db:enum_docs_since(Db, StartKey2, Dir, - fun(DocInfo, Offset, Acc) -> - #doc_info{ - id=Id, - high_seq=Seq, - revs=[#rev_info{rev=Rev,deleted=Deleted} | RestInfo] - } = DocInfo, - ConflictRevs = couch_doc:rev_to_strs( - [Rev1 || #rev_info{deleted=false, rev=Rev1} <- RestInfo]), - DelConflictRevs = couch_doc:rev_to_strs( - [Rev1 || #rev_info{deleted=true, rev=Rev1} <- RestInfo]), - Json = { - [{<<"rev">>, couch_doc:rev_to_str(Rev)}] ++ - case ConflictRevs of - [] -> []; - _ -> [{<<"conflicts">>, ConflictRevs}] - end ++ - case DelConflictRevs of - [] -> []; - _ -> [{<<"deleted_conflicts">>, DelConflictRevs}] - end ++ - case Deleted of - true -> [{<<"deleted">>, true}]; - false -> [] - end - }, - FoldlFun({{Seq, Id}, Json}, Offset, Acc) - end, {Limit, SkipCount, undefined, [], nil}), - couch_httpd_view:finish_view_fold(Req, TotalRowCount, {ok, FoldResult}) - end). - -conflicts_view(Req, Db, nil) -> - #view_query_args{ - start_key = StartKey, - limit = Limit, - skip = SkipCount, - direction = Dir, - deleted = ShowDeletedConflicts - } = QueryArgs = couch_httpd_view:parse_view_params(Req, nil, map), - - StartResp = fun(Req2, Etag, _TotalViewCount, _Offset, _Acc) -> - {ok, Resp} = couch_httpd:start_json_response(Req2, 200, [{"Etag",Etag}]), - {ok, Resp, "{\"rows\":[\r\n"} - end, - - SendRow = fun(Resp, _Db, {{Id,Rev}, Value}, _IncludeDocs, RowFront) -> - {IsDeleted, Conflicts, DelConflicts} = Value, - JsonProps = lists:flatten([{key, Id},{id, Id}, {rev, Rev}, - case IsDeleted of true -> {deleted, true}; _ -> [] end, - case Conflicts of [] -> []; _ -> {conflicts, Conflicts} end, - case DelConflicts of - [] -> []; - _ -> {deleted_conflicts, DelConflicts} - end - ]), - send_chunk(Resp, RowFront ++ ?JSON_ENCODE({JsonProps})), - {ok, ",\r\n"} - end, - - CurrentEtag = couch_httpd:make_etag(couch_db:get_update_seq(Db)), - couch_httpd:etag_respond(Req, CurrentEtag, fun() -> - HelperFuns = #view_fold_helper_funs{ - start_response = StartResp, - send_row = SendRow, - reduce_count = fun couch_db:enum_docs_reduce_to_count/1 - }, - FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, - CurrentEtag, Db, 0, HelperFuns), - - EnumFun = fun(FullDocInfo, Offset, Acc) -> - IsDeleted = FullDocInfo#full_doc_info.deleted, - #doc_info{ - id = Id, - revs = [RevInfo | ConflictInfo] - } = couch_doc:to_doc_info(FullDocInfo), - RevStr = couch_doc:rev_to_str(RevInfo#rev_info.rev), - Conflicts = couch_doc:rev_to_strs( - [Rev || #rev_info{deleted=false, rev=Rev} <- ConflictInfo]), - DelConflicts = couch_doc:rev_to_strs( - [Rev || #rev_info{deleted=true, rev=Rev} <- ConflictInfo]), - case {ShowDeletedConflicts, Conflicts, DelConflicts} of - {_, [], []} -> - {ok, Acc}; - {false, [], _} -> - {ok, Acc}; - {true, _, _} -> - Value = {IsDeleted, Conflicts, DelConflicts}, - FoldlFun({{Id,RevStr}, Value}, Offset, Acc); - {false, _, _} -> - Value = {IsDeleted, Conflicts, []}, - FoldlFun({{Id,RevStr}, Value}, Offset, Acc) - end - end, - - Acc0 = {Limit, SkipCount, undefined, [], nil}, - case couch_db:enum_docs(Db, StartKey, Dir, EnumFun, Acc0) of - {ok, {_, _, undefined, _, _}} -> - % nothing found in the view, send empty view - send_json(Req, 200, {[{rows, []}]}); - {ok, {_, _, Resp, _, _}} -> - % end the view - send_chunk(Resp, "\r\n]}"), - end_json_response(Resp); - Error -> - throw(Error) - end - 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 da9d478d..8264186b 100644 --- a/src/couchdb/couch_httpd_view.erl +++ b/src/couchdb/couch_httpd_view.erl @@ -314,8 +314,6 @@ parse_view_param("include_docs", Value) -> [{include_docs, parse_bool_param(Value)}]; parse_view_param("list", Value) -> [{list, ?l2b(Value)}]; -parse_view_param("deleted", Value) -> - [{deleted, parse_bool_param(Value)}]; parse_view_param("callback", _) -> []; % Verified in the JSON response functions parse_view_param(Key, Value) -> @@ -400,9 +398,7 @@ validate_view_query(include_docs, true, Args) -> validate_view_query(include_docs, _Value, Args) -> Args; validate_view_query(extra, _Value, Args) -> - Args; -validate_view_query(deleted, Value, Args) -> - Args#view_query_args{deleted = Value}. + Args. make_view_fold_fun(Req, QueryArgs, Etag, Db, TotalViewCount, HelperFuns) -> #view_query_args{ -- cgit v1.2.3