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/08/05 07:25:40 UTC

[couchdb] branch prototype/fdb-layer updated: add local_seq option to views (#3043)

This is an automated email from the ASF dual-hosted git repository.

garren pushed a commit to branch prototype/fdb-layer
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/prototype/fdb-layer by this push:
     new 282e858  add local_seq option to views (#3043)
282e858 is described below

commit 282e85814b7025da76e88e8cfc2413aacd6808b8
Author: garren smith <ga...@gmail.com>
AuthorDate: Wed Aug 5 09:25:29 2020 +0200

    add local_seq option to views (#3043)
    
     add local_seq option to views
---
 src/couch_views/src/couch_views_indexer.erl   | 29 ++++++++++-----
 src/couch_views/test/couch_views_map_test.erl | 51 ++++++++++++++++++++++++++-
 test/elixir/test/map_test.exs                 | 27 ++++++++++++++
 3 files changed, 97 insertions(+), 10 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl b/src/couch_views/src/couch_views_indexer.erl
index 9183d98..9c8be6f 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -195,9 +195,10 @@ do_update(Db, Mrst0, State0) ->
             limit := Limit,
             limiter := Limiter,
             view_vs := ViewVS,
-            changes_done := ChangesDone0
+            changes_done := ChangesDone0,
+            design_opts := DesignOpts
         } = State2,
-        DocAcc1 = fetch_docs(TxDb, DocAcc),
+        DocAcc1 = fetch_docs(TxDb, DesignOpts, DocAcc),
         couch_rate:in(Limiter, Count),
 
         {Mrst1, MappedDocs} = map_docs(Mrst0, DocAcc1),
@@ -379,7 +380,7 @@ write_docs(TxDb, Mrst, Docs, State) ->
     DocsNumber.
 
 
-fetch_docs(Db, Changes) ->
+fetch_docs(Db, DesignOpts, Changes) ->
     {Deleted, NotDeleted} = lists:partition(fun(Doc) ->
         #{deleted := Deleted} = Doc,
         Deleted
@@ -407,17 +408,27 @@ fetch_docs(Db, Changes) ->
         }
     end, #{}, erlfdb:wait_for_all(RevFutures)),
 
+    AddLocalSeq = fabric2_util:get_value(<<"local_seq">>, DesignOpts, false),
+
     BodyFutures = maps:keys(BodyState),
     ChangesWithDocs = lists:map(fun (BodyFuture) ->
         {Id, RevInfo, Change} = maps:get(BodyFuture, BodyState),
         Doc = fabric2_fdb:get_doc_body_wait(Db, Id, RevInfo, BodyFuture),
 
-        BranchCount = maps:get(branch_count, RevInfo, 1),
-        Doc1 = if BranchCount == 1 -> Doc; true ->
-            RevConflicts = fabric2_fdb:get_all_revs(Db, Id),
-            {ok, DocWithConflicts} = fabric2_db:apply_open_doc_opts(Doc,
-                RevConflicts, [conflicts]),
-            DocWithConflicts
+        Doc1 = case maps:get(branch_count, RevInfo, 1) of
+            1 when AddLocalSeq ->
+                {ok, DocWithLocalSeq} = fabric2_db:apply_open_doc_opts(Doc,
+                    [RevInfo], [local_seq]),
+                DocWithLocalSeq;
+            1 ->
+                Doc;
+            _ ->
+                RevConflicts = fabric2_fdb:get_all_revs(Db, Id),
+                DocOpts = if not AddLocalSeq -> []; true -> [local_seq] end,
+
+                {ok, DocWithConflicts} = fabric2_db:apply_open_doc_opts(Doc,
+                    RevConflicts, [conflicts | DocOpts]),
+                DocWithConflicts
         end,
         Change#{doc => Doc1}
     end, erlfdb:wait_for_all(BodyFutures)),
diff --git a/src/couch_views/test/couch_views_map_test.erl b/src/couch_views/test/couch_views_map_test.erl
index 2b679f0..c419546 100644
--- a/src/couch_views/test/couch_views_map_test.erl
+++ b/src/couch_views/test/couch_views_map_test.erl
@@ -58,7 +58,8 @@ map_views_test_() ->
                 ?TDEF(should_map_with_doc_emit),
                 ?TDEF(should_map_update_is_false),
                 ?TDEF(should_map_update_is_lazy),
-                ?TDEF(should_map_wait_for_interactive)
+                ?TDEF(should_map_wait_for_interactive),
+                ?TDEF(should_map_local_seq)
                 % fun should_give_ext_size_seq_indexed_test/1
             ]
         }
@@ -440,6 +441,36 @@ should_map_wait_for_interactive() ->
     ]}, Result).
 
 
+should_map_local_seq() ->
+    ExpectedTrue = [
+        {row, [{id, <<"1">>}, {key, 1}, {value, 1}]},
+        {row, [{id, <<"2">>}, {key, 2}, {value, 2}]},
+        {row, [{id, <<"3">>}, {key, 3}, {value, 3}]}
+    ],
+    check_local_seq(true, ExpectedTrue),
+
+    ExpectedFalse = [],
+    check_local_seq(false, ExpectedFalse),
+
+    Error = {bad_request,invalid_design_doc,
+        <<"`options.local_seq` field must have boolean type">>},
+    ?assertThrow(Error, check_local_seq(something_else, null)).
+
+
+check_local_seq(Val, Expected) ->
+    DbName = ?tempdb(),
+    {ok, Db} = fabric2_db:create(DbName, [{user_ctx, ?ADMIN_USER}]),
+
+    DDoc = create_local_seq_ddoc(Val),
+    Docs = make_docs(5),
+    fabric2_db:update_docs(Db, [DDoc | Docs]),
+
+    {ok, Result} = couch_views:query(Db, DDoc, <<"idx_01">>, fun default_cb/2, [],
+        #{limit => 3}),
+
+    ?assertEqual(Expected, Result).
+
+
 % should_give_ext_size_seq_indexed_test(Db) ->
 %     DDoc = couch_doc:from_json_obj({[
 %         {<<"_id">>, <<"_design/seqdoc">>},
@@ -550,6 +581,24 @@ create_interactive_ddoc() ->
     ]}).
 
 
+create_local_seq_ddoc(Val) ->
+    couch_doc:from_json_obj({[
+        {<<"_id">>, <<"_design/ddoc_local_seq">>},
+        {<<"options">>, {[{<<"local_seq">>, Val}]}},
+        {<<"language">>, <<"javascript">>},
+        {<<"views">>, {[
+            {<<"idx_01">>, {[
+                {<<"map">>, <<
+                    "function(doc) {"
+                        "if (doc._local_seq) {"
+                            "emit(doc.val, doc.val);"
+                        "}"
+                    "}">>}
+            ]}}
+        ]}}
+    ]}).
+
+
 make_docs(Count) ->
     [doc(I) || I <- lists:seq(1, Count)].
 
diff --git a/test/elixir/test/map_test.exs b/test/elixir/test/map_test.exs
index 8432565..9254cc4 100644
--- a/test/elixir/test/map_test.exs
+++ b/test/elixir/test/map_test.exs
@@ -586,6 +586,33 @@ defmodule ViewMapTest do
     assert get_ids(resp) == ["doc-id-1"]
   end
 
+  test "_local_seq is supported", context do
+    db_name = context[:db_name]
+    ddoc =  %{
+      _id: "_design/local_seq",
+      views: %{
+        view: %{
+          map: """
+              function (doc) {
+                emit(doc._local_seq, doc._id);
+              }
+          """
+        }
+      },
+      options: %{
+        local_seq: true
+      }
+    }
+
+    resp = Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => [ddoc]})
+    assert resp.status_code == 201
+
+    url = "/#{db_name}/_design/local_seq/_view/view"
+    resp = Couch.get(url, query: %{limit: 1})
+    key = Enum.at(resp.body["rows"], 0)["key"]
+    assert key != :null
+  end
+
   def update_doc_value(db_name, id, value) do
     resp = Couch.get("/#{db_name}/#{id}")
     doc = convert(resp.body)