This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a commit to branch 3.x
in repository https://gitbox.apache.org/repos/asf/couchdb.git
The following commit(s) were added to refs/heads/3.x by this push:
new 8d9ce55 Fix skip and limit parameters
8d9ce55 is described below
commit 8d9ce558cd1189ce15b0e9c677f56325db88310b
Author: jiahuili <[email protected]>
AuthorDate: Thu Mar 24 23:55:47 2022 -0500
Fix skip and limit parameters
---
src/chttpd/src/chttpd_misc.erl | 41 ++++++++----------
src/chttpd/test/eunit/chttpd_dbs_info_test.erl | 58 ++++++++++++++++++++++++++
src/couch_mrview/src/couch_mrview.erl | 10 ++++-
src/fabric/src/fabric_view_all_docs.erl | 1 +
4 files changed, 85 insertions(+), 25 deletions(-)
diff --git a/src/chttpd/src/chttpd_misc.erl b/src/chttpd/src/chttpd_misc.erl
index 492706f..0aa8594 100644
--- a/src/chttpd/src/chttpd_misc.erl
+++ b/src/chttpd/src/chttpd_misc.erl
@@ -120,7 +120,8 @@ handle_all_dbs_req(Req) ->
send_method_not_allowed(Req, "GET,HEAD").
handle_all_dbs_info_req(Req) ->
- Args = couch_mrview_http:parse_params(Req, undefined),
+ Args0 = couch_mrview_http:parse_params(Req, undefined),
+ Args1 = couch_mrview_util:set_extra(Args0, namespace, <<"_non_design">>),
ShardDbName = config:get("mem3", "shards_db", "_dbs"),
%% shard_db is not sharded but mem3:shards treats it as an edge case
%% so it can be pushed thru fabric
@@ -130,7 +131,7 @@ handle_all_dbs_info_req(Req) ->
{ok, Resp} = chttpd:etag_respond(Req, Etag, fun() ->
{ok, Resp} = chttpd:start_delayed_json_response(Req, 200, [{"ETag",
Etag}]),
VAcc = #vacc{req = Req, resp = Resp},
- fabric:all_docs(ShardDbName, Options, fun all_dbs_info_callback/2,
VAcc, Args)
+ fabric:all_docs(ShardDbName, Options, fun all_dbs_info_callback/2,
VAcc, Args1)
end),
case is_record(Resp, vacc) of
true -> {ok, Resp#vacc.resp};
@@ -144,32 +145,24 @@ all_dbs_info_callback({row, Row}, #vacc{resp = Resp0} =
Acc) when
Acc#vacc.req#httpd.path_parts =:= [<<"_all_dbs">>]
->
Prepend = couch_mrview_http:prepend_val(Acc),
- case couch_util:get_value(id, Row) of
- <<"_design", _/binary>> ->
- {ok, Acc};
- DbName ->
- {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, [Prepend,
?JSON_ENCODE(DbName)]),
- {ok, Acc#vacc{prepend = ",", resp = Resp1}}
- end;
+ DbName = couch_util:get_value(id, Row),
+ {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, [Prepend,
?JSON_ENCODE(DbName)]),
+ {ok, Acc#vacc{prepend = ",", resp = Resp1}};
all_dbs_info_callback({row, Row}, #vacc{resp = Resp0} = Acc) when
Acc#vacc.req#httpd.path_parts =:= [<<"_dbs_info">>]
->
Prepend = couch_mrview_http:prepend_val(Acc),
- case couch_util:get_value(id, Row) of
- <<"_design", _/binary>> ->
- {ok, Acc};
- DbName ->
- case chttpd_util:get_db_info(DbName) of
- {ok, DbInfo} ->
- Chunk = [Prepend, ?JSON_ENCODE({[{key, DbName}, {info,
{DbInfo}}]})],
- {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, Chunk),
- {ok, Acc#vacc{prepend = ",", resp = Resp1}};
- {error, database_does_not_exist} ->
- {ok, Acc#vacc{resp = Resp0}};
- {error, Reason} ->
- {ok, Resp1} = chttpd:send_delayed_error(Resp0, Reason),
- {stop, Acc#vacc{resp = Resp1}}
- end
+ DbName = couch_util:get_value(id, Row),
+ case chttpd_util:get_db_info(DbName) of
+ {ok, DbInfo} ->
+ Chunk = [Prepend, ?JSON_ENCODE({[{key, DbName}, {info,
{DbInfo}}]})],
+ {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, Chunk),
+ {ok, Acc#vacc{prepend = ",", resp = Resp1}};
+ {error, database_does_not_exist} ->
+ {ok, Acc#vacc{resp = Resp0}};
+ {error, Reason} ->
+ {ok, Resp1} = chttpd:send_delayed_error(Resp0, Reason),
+ {stop, Acc#vacc{resp = Resp1}}
end;
all_dbs_info_callback(complete, #vacc{resp = Resp0} = Acc) ->
{ok, Resp1} = chttpd:send_delayed_chunk(Resp0, "]"),
diff --git a/src/chttpd/test/eunit/chttpd_dbs_info_test.erl
b/src/chttpd/test/eunit/chttpd_dbs_info_test.erl
index 3467087..cb386d6 100644
--- a/src/chttpd/test/eunit/chttpd_dbs_info_test.erl
+++ b/src/chttpd/test/eunit/chttpd_dbs_info_test.erl
@@ -51,6 +51,14 @@ teardown({_, Db1, Db2}) ->
delete_db(base_url(Db2)),
ok = config:delete("admins", ?USER, _Persist = false).
+setup_with_shards_db_ddoc() ->
+ {Suffix, Db1, Db2} = setup(),
+ {Suffix, Db1, Db2, create_shards_db_ddoc(Suffix)}.
+
+teardown_with_shards_db_ddoc({Suffix, Db1, Db2, UrlDDoc}) ->
+ ok = delete_shards_db_ddoc(UrlDDoc),
+ teardown({Suffix, Db1, Db2}).
+
dbs_info_test_() ->
{
"chttpd dbs info tests",
@@ -85,6 +93,25 @@ dbs_info_test_() ->
}
}.
+skip_limit_test_() ->
+ {
+ "chttpd skip limit tests",
+ {
+ setup,
+ fun start/0,
+ fun stop/1,
+ {
+ foreach,
+ fun setup_with_shards_db_ddoc/0,
+ fun teardown_with_shards_db_ddoc/1,
+ [
+ ?TDEF_FE(t_dbs_info_when_shards_db_design_doc_exist),
+ ?TDEF_FE(t_all_dbs_when_shards_db_design_doc_exist)
+ ]
+ }
+ }
+ }.
+
get_db_info_should_return_db_info({_, Db1, _}) ->
DbInfo = fabric:get_db_info(Db1),
?assertEqual(DbInfo, chttpd_util:get_db_info(Db1)).
@@ -225,6 +252,19 @@ should_return_dbs_info_for_dbs_with_mixed_state({_, Db1,
_}) ->
?assertEqual(<<"noexisteddb">>, couch_util:get_value(<<"key">>, Db2Data)),
?assertEqual(undefined, couch_util:get_value(<<"info">>, Db2Data)).
+t_dbs_info_when_shards_db_design_doc_exist({Suffix, _, Db2, _}) ->
+ {ok, _, _, ResultBody} = test_request:get(
+ dbs_info_url("limit=1&skip=1"), [?CONTENT_JSON, ?AUTH]
+ ),
+ FilteredDbs = filter_dbs(Suffix, ResultBody),
+ ?assertEqual([Db2], FilteredDbs).
+
+t_all_dbs_when_shards_db_design_doc_exist({_, _, Db2, _}) ->
+ {ok, _, _, ResultBody} = test_request:get(
+ base_url("_all_dbs?limit=1&skip=1"), [?CONTENT_JSON, ?AUTH]
+ ),
+ ?assertEqual([?l2b(Db2)], jiffy:decode(ResultBody)).
+
%% Utility functions
testdb(Name, Suffix) ->
Name ++ "-" ++ Suffix.
@@ -263,6 +303,24 @@ mock_db_not_exist() ->
fun(_) -> {error, database_does_not_exist} end
).
+create_shards_db_ddoc(Suffix) ->
+ DDocId = ?l2b("_design/ddoc-" ++ Suffix),
+ DDoc = #{<<"_id">> => DDocId},
+ ShardsDb = "_node/_local/" ++ ?b2l(mem3_sync:shards_db()),
+ {ok, Code, _, Resp} = test_request:post(
+ base_url(ShardsDb), [?CONTENT_JSON, ?AUTH], jiffy:encode(DDoc)
+ ),
+ RespBody = jiffy:decode(Resp, [return_maps]),
+ #{<<"rev">> := Rev} = RespBody,
+ UrlDDoc = base_url(ShardsDb) ++ "/" ++ ?b2l(DDocId) ++ "?rev=" ++
?b2l(Rev),
+ ?assert(lists:member(Code, [200, 201])),
+ UrlDDoc.
+
+delete_shards_db_ddoc(UrlDDoc) ->
+ {ok, Code, _, _} = test_request:delete(UrlDDoc, [?AUTH]),
+ ?assertEqual(Code, 200),
+ ok.
+
filter_dbs(Suffix, ResultBody) ->
Dbs = jiffy:decode(ResultBody, [return_maps]),
SuffixBin = ?l2b(Suffix),
diff --git a/src/couch_mrview/src/couch_mrview.erl
b/src/couch_mrview/src/couch_mrview.erl
index 798b939..d8640c9 100644
--- a/src/couch_mrview/src/couch_mrview.erl
+++ b/src/couch_mrview/src/couch_mrview.erl
@@ -480,7 +480,11 @@ map_fold(#full_doc_info{} = FullDocInfo, OffsetReds, Acc)
->
case couch_doc:to_doc_info(FullDocInfo) of
#doc_info{id = Id, revs = [#rev_info{deleted = false, rev = Rev} | _]}
= DI ->
Value = {[{rev, couch_doc:rev_to_str(Rev)}]},
- map_fold({{Id, Id}, Value}, OffsetReds, Acc#mracc{doc_info = DI});
+ NS = couch_util:get_value(namespace, Acc#mracc.args#mrargs.extra),
+ case Id of
+ <<?DESIGN_DOC_PREFIX, _/binary>> when NS =:= <<"_non_design">>
-> {ok, Acc};
+ _ -> map_fold({{Id, Id}, Value}, OffsetReds,
Acc#mracc{doc_info = DI})
+ end;
#doc_info{revs = [#rev_info{deleted = true} | _]} ->
{ok, Acc}
end;
@@ -699,6 +703,10 @@ get_total_rows(Db, #mrargs{extra = Extra}) ->
<<"_design">> ->
{ok, N} = couch_db:get_design_doc_count(Db),
N;
+ <<"_non_design">> ->
+ {ok, N} = couch_db:get_design_doc_count(Db),
+ {ok, Info} = couch_db:get_db_info(Db),
+ couch_util:get_value(doc_count, Info) - N;
_ ->
{ok, Info} = couch_db:get_db_info(Db),
couch_util:get_value(doc_count, Info)
diff --git a/src/fabric/src/fabric_view_all_docs.erl
b/src/fabric/src/fabric_view_all_docs.erl
index 4bd8e95..0a637a7 100644
--- a/src/fabric/src/fabric_view_all_docs.erl
+++ b/src/fabric/src/fabric_view_all_docs.erl
@@ -93,6 +93,7 @@ go(DbName, Options, QueryArgs, Callback, Acc0) ->
case couch_util:get_value(namespace, Extra) of
<<"_all_docs">> -> <<"_all_docs">>;
<<"_design">> -> <<"_design">>;
+ <<"_non_design">> -> <<"_non_design">>;
<<"_local">> -> <<"_local">>;
_ -> <<"_all_docs">>
end,