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,

Reply via email to