Add support for index pagination
We add limit and skip parameters to GET so that the dashboard
can utilize these parameters for pagination.
Fixes:COUCHDB-2652
diff --git a/src/mango_error.erl b/src/mango_error.erl
index 6dcf7c8..dfd4bd7 100644
--- a/src/mango_error.erl
+++ b/src/mango_error.erl
@@ -77,6 +77,12 @@
<<"error_saving_ddoc">>,
fmt("Unknown error while saving the design document: ~s", [Reason])
};
+info(mango_httpd, invalid_list_index_params) ->
+ {
+ 500,
+ <<"invalid_list_index_params">>,
+ <<"Index parameter ranges: limit > 1, skip > 0" >>
+ };
info(mango_idx, {invalid_index_type, BadType}) ->
{
diff --git a/src/mango_httpd.erl b/src/mango_httpd.erl
index 671ffd2..d3fde9c 100644
--- a/src/mango_httpd.erl
+++ b/src/mango_httpd.erl
@@ -50,9 +50,27 @@
handle_index_req(#httpd{method='GET', path_parts=[_, _]}=Req, Db) ->
+ Params = lists:flatmap(fun({K, V}) -> parse_index_param(K, V) end,
+ chttpd:qs(Req)),
Idxs = lists:sort(mango_idx:list(Db)),
- JsonIdxs = lists:map(fun mango_idx:to_json/1, Idxs),
- chttpd:send_json(Req, {[{indexes, JsonIdxs}]});
+ JsonIdxs0 = lists:map(fun mango_idx:to_json/1, Idxs),
+ TotalRows = length(JsonIdxs0),
+ Limit = case couch_util:get_value(limit, Params, TotalRows) of
+ Limit0 when Limit0 < 1 ->
+ ?MANGO_ERROR(invalid_list_index_params);
+ Limit0 ->
+ Limit0
+ end,
+ Skip = case couch_util:get_value(skip, Params, 0) of
+ Skip0 when Skip0 < 0 ->
+ ?MANGO_ERROR(invalid_list_index_params);
+ Skip0 when Skip0 > TotalRows ->
+ TotalRows;
+ Skip0 ->
+ Skip0
+ end,
+ JsonIdxs = lists:sublist(JsonIdxs0, Skip+1, Limit),
+ chttpd:send_json(Req, {[{total_rows, TotalRows}, {indexes, JsonIdxs}]});
handle_index_req(#httpd{method='POST', path_parts=[_, _]}=Req, Db) ->
{ok, Opts} = mango_opts:validate_idx_create(chttpd:json_body_obj(Req)),
@@ -217,3 +235,19 @@
Chunk = [Prepend, ?JSON_ENCODE(Doc)],
{ok, Resp1} = chttpd:send_delayed_chunk(Resp0, Chunk),
{ok, {Resp1, ",\r\n", KVs}}.
+
+
+parse_index_param("limit", Value) ->
+ [{limit, parse_val(Value)}];
+parse_index_param("skip", Value) ->
+ [{skip, parse_val(Value)}];
+parse_index_param(_Key, _Value) ->
+ [].
+
+parse_val(Value) ->
+ case (catch list_to_integer(Value)) of
+ IntVal when is_integer(IntVal) ->
+ IntVal;
+ _ ->
+ ?MANGO_ERROR(invalid_list_index_params)
+ end.
diff --git a/test/01-index-crud-test.py b/test/01-index-crud-test.py
index a44376c..d83e97f 100644
--- a/test/01-index-crud-test.py
+++ b/test/01-index-crud-test.py
@@ -222,3 +222,33 @@
assert e.response.status_code == 404
else:
raise AssertionError("bad index delete")
+
+ def test_limit_skip_index(self):
+ fields = ["field1"]
+ ret = self.db.create_index(fields, name="idx_01")
+ assert ret is True
+
+ fields = ["field2"]
+ ret = self.db.create_index(fields, name="idx_02")
+ assert ret is True
+
+ fields = ["field3"]
+ ret = self.db.create_index(fields, name="idx_03")
+ assert ret is True
+
+ assert len(self.db.list_indexes(limit=2)) == 2
+ assert len(self.db.list_indexes(limit=5,skip=4)) == 2
+ assert len(self.db.list_indexes(skip=5)) == 1
+ assert len(self.db.list_indexes(skip=6)) == 0
+ assert len(self.db.list_indexes(skip=100)) == 0
+ assert len(self.db.list_indexes(limit=10000000)) == 6
+
+ try:
+ self.db.list_indexes(skip=-1)
+ except Exception, e:
+ assert e.response.status_code == 500
+
+ try:
+ self.db.list_indexes(limit=0)
+ except Exception, e:
+ assert e.response.status_code == 500
diff --git a/test/mango.py b/test/mango.py
index b39c916..bde9323 100644
--- a/test/mango.py
+++ b/test/mango.py
@@ -125,8 +125,12 @@
r.raise_for_status()
return r.json()["result"] == "created"
- def list_indexes(self):
- r = self.sess.get(self.path("_index"))
+ def list_indexes(self, limit="", skip=""):
+ if limit != "":
+ limit = "limit=" + str(limit)
+ if skip != "":
+ skip = "skip=" + str(skip)
+ r = self.sess.get(self.path("_index?"+limit+";"+skip))
r.raise_for_status()
return r.json()["indexes"]