You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2020/02/11 14:41:22 UTC
[couchdb] 01/01: Encode startkey/endkey for all_docs
This is an automated email from the ASF dual-hosted git repository.
garren pushed a commit to branch fdb-all-docs-encoding
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit cd1536474ff2beeea7347a823d72426ec4f6e47c
Author: Garren Smith <ga...@gmail.com>
AuthorDate: Tue Feb 11 16:40:18 2020 +0200
Encode startkey/endkey for all_docs
Encodes the startkey/endkey so that if a startkey is not binary it will return the expected results.
---
src/chttpd/src/chttpd_db.erl | 10 ++++----
src/fabric/src/fabric2_util.erl | 13 ++++++++++-
test/elixir/test/all_docs_test.exs | 48 ++++++++++++++++++++++++++++++++------
3 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl
index 108881f..d10017c 100644
--- a/src/chttpd/src/chttpd_db.erl
+++ b/src/chttpd/src/chttpd_db.erl
@@ -926,13 +926,13 @@ all_docs_view_opts(Args) ->
EKey -> EKey
end,
StartKeyOpts = case StartKey of
- <<_/binary>> -> [{start_key, StartKey}];
- undefined -> []
+ undefined -> [];
+ _ -> [{start_key, fabric2_util:all_docs_encode(StartKey)}]
end,
EndKeyOpts = case {EndKey, Args#mrargs.inclusive_end} of
- {<<_/binary>>, false} -> [{end_key_gt, EndKey}];
- {<<_/binary>>, true} -> [{end_key, EndKey}];
- {undefined, _} -> []
+ {undefined, _} -> [];
+ {_, false} -> [{end_key_gt, fabric2_util:all_docs_encode(EndKey)}];
+ {_, true} -> [{end_key, fabric2_util:all_docs_encode(EndKey)}]
end,
[
{dir, Args#mrargs.direction},
diff --git a/src/fabric/src/fabric2_util.erl b/src/fabric/src/fabric2_util.erl
index 4e2e2d7..973d169 100644
--- a/src/fabric/src/fabric2_util.erl
+++ b/src/fabric/src/fabric2_util.erl
@@ -33,7 +33,9 @@
get_value/3,
to_hex/1,
from_hex/1,
- uuid/0
+ uuid/0,
+
+ all_docs_encode/1
]).
@@ -235,3 +237,12 @@ hex_to_nibble(N) ->
uuid() ->
to_hex(crypto:strong_rand_bytes(16)).
+
+
+all_docs_encode(null) -> <<>>;
+all_docs_encode(true) -> <<>>;
+all_docs_encode(false) -> <<>>;
+all_docs_encode(N) when is_number(N) -> <<>>;
+all_docs_encode(B) when is_binary(B) -> B;
+all_docs_encode(L) when is_list(L) -> <<255>>;
+all_docs_encode({O}) when is_list(O) -> <<255>>.
diff --git a/test/elixir/test/all_docs_test.exs b/test/elixir/test/all_docs_test.exs
index 7e154eb..53f80ff 100644
--- a/test/elixir/test/all_docs_test.exs
+++ b/test/elixir/test/all_docs_test.exs
@@ -41,11 +41,9 @@ defmodule AllDocsTest do
assert resp["total_rows"] == length(rows)
# Check _all_docs offset
- retry_until(fn ->
resp = Couch.get("/#{db_name}/_all_docs", query: %{:startkey => "\"2\""}).body
assert resp["offset"] == :null
assert Enum.at(resp["rows"], 0)["key"] == "2"
- end)
# Confirm that queries may assume raw collation
resp =
@@ -73,11 +71,9 @@ defmodule AllDocsTest do
changes = Couch.get("/#{db_name}/_changes").body["results"]
assert length(changes) == 4
- retry_until(fn ->
- deleted = Enum.filter(changes, fn row -> row["deleted"] end)
- assert length(deleted) == 1
- assert hd(deleted)["id"] == "1"
- end)
+ deleted = Enum.filter(changes, fn row -> row["deleted"] end)
+ assert length(deleted) == 1
+ assert hd(deleted)["id"] == "1"
# (remember old seq)
orig_doc = Enum.find(changes, fn row -> row["id"] == "3" end)
@@ -187,4 +183,42 @@ defmodule AllDocsTest do
assert length(rows) == 1
end
+
+ @tag :with_db
+ test "all_docs ordering", context do
+ db_name = context[:db_name]
+ docs = [
+ %{:_id => "a"},
+ %{:_id => "m"},
+ %{:_id => "z"}
+ ]
+
+ resp = Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs})
+ Enum.each(resp.body, &assert(&1["ok"]))
+
+ resp = Couch.get("/#{db_name}/_all_docs", query: %{:startkey => false}).body
+ rows = resp["rows"]
+ assert length(rows) === 3
+ assert get_ids(resp) == ["a", "m", "z"]
+
+ resp = Couch.get("/#{db_name}/_all_docs", query: %{:startkey => 0}).body
+ rows = resp["rows"]
+ assert length(rows) === 3
+ assert get_ids(resp) == ["a", "m", "z"]
+
+ resp = Couch.get("/#{db_name}/_all_docs", query: %{:startkey => "[1,2]"}).body
+ rows = resp["rows"]
+ assert length(rows) === 0
+
+ resp = Couch.get("/#{db_name}/_all_docs", query: %{:end_key => 0}).body
+ rows = resp["rows"]
+ assert length(rows) === 0
+
+ end
+
+
+ defp get_ids(resp) do
+ %{"rows" => rows} = resp
+ Enum.map(rows, fn row -> row["id"] end)
+ end
end