paginate all_dbs simple way to paginate results by skipping first results and limit the number of results returned.
fix #COUCHDB-1960 Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/f2b2f794 Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/f2b2f794 Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/f2b2f794 Branch: refs/heads/1960-paginate-all_dbs Commit: f2b2f794c03aeacfad032bc0e6cb7f98b122df17 Parents: 9068db2 Author: Benoit Chesneau <[email protected]> Authored: Sat Dec 14 16:08:13 2013 +0100 Committer: Benoit Chesneau <[email protected]> Committed: Sun Jan 5 09:54:15 2014 +0100 ---------------------------------------------------------------------- src/couchdb/couch_httpd_misc_handlers.erl | 21 +++++- test/etap/071-all_dbs.t | 94 ++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb/blob/f2b2f794/src/couchdb/couch_httpd_misc_handlers.erl ---------------------------------------------------------------------- diff --git a/src/couchdb/couch_httpd_misc_handlers.erl b/src/couchdb/couch_httpd_misc_handlers.erl index 96a05c6..0d7fb2b 100644 --- a/src/couchdb/couch_httpd_misc_handlers.erl +++ b/src/couchdb/couch_httpd_misc_handlers.erl @@ -27,6 +27,9 @@ start_json_response/2,send_chunk/2,last_chunk/1,end_json_response/1, start_chunked_response/3, send_error/4]). + +-define(DEFAULT_LIMIT, 16#10000000). + % httpd global handlers handle_welcome_req(#httpd{method='GET'}=Req, WelcomeMessage) -> @@ -80,12 +83,26 @@ handle_utils_dir_req(Req, _) -> send_method_not_allowed(Req, "GET,HEAD"). handle_all_dbs_req(#httpd{method='GET'}=Req) -> - {ok, DbNames} = couch_server:all_databases(), - send_json(Req, DbNames); + Limit0 = couch_util:to_integer(couch_httpd:qs_value(Req, "limit", + ?DEFAULT_LIMIT)), + Skip0 = couch_util:to_integer(couch_httpd:qs_value(Req, "skip", -1)), + {ok, {DbNames, _, _}} = couch_server:all_databases(fun all_dbs_fun/2, + {[], Skip0, Limit0}), + send_json(Req, lists:usort(DbNames)); handle_all_dbs_req(Req) -> send_method_not_allowed(Req, "GET,HEAD"). +all_dbs_fun(DbName, {Acc, Skip, 0}) -> + {stop, {Acc, Skip, 0}}; +all_dbs_fun(DbName, {Acc, 0, Limit}) -> + {ok, {[DbName | Acc], 0, Limit - 1}}; +all_dbs_fun(_DbName, {Acc, Skip, Limit}) when Skip > 0 -> + {ok, {Acc, Skip - 1, Limit}}; +all_dbs_fun (DbName, {Acc, Skip, Limit}) -> + {ok, {[DbName | Acc], Skip, Limit - 1}}. + + handle_task_status_req(#httpd{method='GET'}=Req) -> ok = couch_httpd:verify_is_server_admin(Req), % convert the list of prop lists to a list of json objects http://git-wip-us.apache.org/repos/asf/couchdb/blob/f2b2f794/test/etap/071-all_dbs.t ---------------------------------------------------------------------- diff --git a/test/etap/071-all_dbs.t b/test/etap/071-all_dbs.t new file mode 100644 index 0000000..d98aeff --- /dev/null +++ b/test/etap/071-all_dbs.t @@ -0,0 +1,94 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +% 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. + +main(_) -> + test_util:init_code_path(), + + couch_server_sup:start_link(test_util:config_files()), + + delete_dbs(), + init_dbs(), + + etap:plan(8), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + + delete_dbs(), + + ok. + +init_dbs() -> + %% init databases + [couch_db:create(iolist_to_binary([<<"etap-test-db">>, + integer_to_list(I)]), []) + || I <- lists:seq(0, 10)]. + + +delete_dbs() -> + {ok, AllDbs} = couch_server:all_databases(), + %% delete all created dbs + lists:foreach(fun(DbName) -> + couch_server:delete(DbName, []) + end, AllDbs). + + +server() -> + lists:concat([ + "http://127.0.0.1:", + mochiweb_socket_server:get(couch_httpd, port), + "/" + ]). + + +test() -> + {ok, AllDbs} = couch_server:all_databases(), + etap:is(12, length(AllDbs), "11 databases was created."), + + Url = server() ++ "_all_dbs", + {ok, _, _, Body} = ibrowse:send_req(Url, [], get, []), + AllDbs1 = ejson:decode(Body), + etap:is(12, length(AllDbs1), "11 databases listed"), + + + Url1 = server() ++ "_all_dbs?limit=4", + {ok, _, _, Body1} = ibrowse:send_req(Url1, [], get, []), + AllDbs2 = ejson:decode(Body1), + etap:is(4, length(AllDbs2), "4 databases listed"), + + Url2 = server() ++ "_all_dbs?skip=4&limit=4", + {ok, _, _, Body2} = ibrowse:send_req(Url2, [], get, []), + AllDbs3 = ejson:decode(Body2), + etap:is(4, length(AllDbs3), "4 databases listed"), + + etap:is(true, lists:member(<<"etap-test-db2">>, AllDbs3), + "etap-test-db2 in list"), + + etap:is(true, lists:member(<<"etap-test-db5">>, AllDbs3), + "etap-test-db5 in list"), + + + etap:is(false, lists:member(<<"etap-test-db10">>, AllDbs3), + "etap-test-db10 in list"), + + etap:is(false, lists:member(<<"etap-test-db6">>, AllDbs3), + "etap-test-db6 in list"), + + + ok.
