summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbenoitc <benoitc@apache.org>2014-01-27 17:24:54 +0100
committerbenoitc <benoitc@apache.org>2014-01-27 17:24:54 +0100
commitc60c6b606dcde12dfff58405023be951b63f240f (patch)
tree50aeb59351f99b19633ce36c88b69b4b240ef5ac
parent6f173d5b394c39542571bf133b5b90d7f5b0651f (diff)
downloadcouchdb-c60c6b606dcde12dfff58405023be951b63f240f.tar.gz
couch_mrview: add view changes test
test view changes and fix errors.
-rw-r--r--apps/couch_mrview/src/couch_mrview_test_util.erl31
-rw-r--r--apps/couch_mrview/src/couch_mrview_updater.erl2
-rw-r--r--apps/couch_mrview/src/couch_mrview_util.erl34
-rw-r--r--apps/couch_mrview/test/08-changes_since.t123
4 files changed, 168 insertions, 22 deletions
diff --git a/apps/couch_mrview/src/couch_mrview_test_util.erl b/apps/couch_mrview/src/couch_mrview_test_util.erl
index adc2675bf..c67f24f1b 100644
--- a/apps/couch_mrview/src/couch_mrview_test_util.erl
+++ b/apps/couch_mrview/src/couch_mrview_test_util.erl
@@ -41,14 +41,31 @@ save_docs(Db, Docs) ->
make_docs(Count) ->
- make_docs(Count, []).
-
-make_docs(Count, Acc) when Count =< 0 ->
- Acc;
-make_docs(Count, Acc) ->
- make_docs(Count-1, [doc(Count) | Acc]).
-
+ [doc(I) || I <- lists:seq(1, Count)].
+ddoc(changes) ->
+ couch_doc:from_json_obj({[
+ {<<"_id">>, <<"_design/bar">>},
+ {<<"options">>, {[
+ {<<"seq_indexed">>, true}
+ ]}},
+ {<<"views">>, {[
+ {<<"baz">>, {[
+ {<<"map">>, <<"function(doc) {emit(doc.val, doc.val);}">>}
+ ]}},
+ {<<"bing">>, {[
+ {<<"map">>, <<"function(doc) {}">>}
+ ]}},
+ {<<"zing">>, {[
+ {<<"map">>, <<
+ "function(doc) {\n"
+ " if(doc.foo !== undefined)\n"
+ " emit(doc.foo, 0);\n"
+ "}"
+ >>}
+ ]}}
+ ]}}
+ ]});
ddoc(map) ->
couch_doc:from_json_obj({[
{<<"_id">>, <<"_design/bar">>},
diff --git a/apps/couch_mrview/src/couch_mrview_updater.erl b/apps/couch_mrview/src/couch_mrview_updater.erl
index 58ee9d2b3..be1055c71 100644
--- a/apps/couch_mrview/src/couch_mrview_updater.erl
+++ b/apps/couch_mrview/src/couch_mrview_updater.erl
@@ -280,7 +280,7 @@ write_kvs(State, UpdateSeq, ViewKVs, DocIdKeys, Log) ->
SToRem = couch_util:dict_find(ViewId, SeqsToRemove, []),
SToAdd = couch_util:dict_find(ViewId, SeqsToAdd, []),
RemSKs = [{Seq, Key} || {Key, Seq, _} <- SToRem],
- RemKSs = [{[Seq, Key], DocId} || {Key, Seq, DocId} <- SToRem],
+ RemKSs = [{[Key, Seq], DocId} || {Key, Seq, DocId} <- SToRem],
SKVs1 = SKVs ++ SToAdd,
{ok, SBt} = couch_btree:add_remove(View#mrview.seq_btree,
SKVs1, RemSKs),
diff --git a/apps/couch_mrview/src/couch_mrview_util.erl b/apps/couch_mrview/src/couch_mrview_util.erl
index 7c42de8ad..a98f042a7 100644
--- a/apps/couch_mrview/src/couch_mrview_util.erl
+++ b/apps/couch_mrview/src/couch_mrview_util.erl
@@ -229,13 +229,8 @@ init_state(Db, Fd, State, Header) ->
views=Views2
}.
-less_json_seqs({SeqA, JsonA}, {SeqB, JsonB}) ->
- case couch_ejson_compare:less(SeqA, SeqB) of
- 0 ->
- couch_ejson_compare:less_json(JsonA, JsonB);
- Result ->
- Result < 0
- end.
+less_json_seqs({SeqA, _JsonA}, {SeqB, _JsonB}) ->
+ couch_ejson_compare:less(SeqA, SeqB) < 0.
open_view(Db, Fd, Lang, {BTState, SeqBTState, KSeqBTState, USeq, PSeq}, View) ->
FunSrcs = [FunSrc || {_Name, FunSrc} <- View#mrview.reduce_funs],
@@ -354,12 +349,23 @@ fold_fun(Fun, [KV|Rest], {KVReds, Reds}, Acc) ->
{stop, Acc2}
end.
+
fold_changes(Bt, Fun, Acc, Opts) ->
WrapperFun = fun(KV, _Reds, Acc2) ->
- Fun(changes_expand_dups([KV], []), Acc2)
+ fold_changes_fun(Fun, changes_expand_dups([KV], []), Acc2)
end,
{ok, _LastRed, _Acc} = couch_btree:fold(Bt, WrapperFun, Acc, Opts).
+fold_changes_fun(_Fun, [], Acc) ->
+ {ok, Acc};
+fold_changes_fun(Fun, [KV|Rest], Acc) ->
+ case Fun(KV, Acc) of
+ {ok, Acc2} ->
+ fold_changes_fun(Fun, Rest, Acc2);
+ {stop, Acc2} ->
+ {stop, Acc2}
+ end.
+
fold_reduce({NthRed, Lang, View}, Fun, Acc, Options) ->
#mrview{
@@ -795,15 +801,15 @@ expand_dups([KV | Rest], Acc) ->
changes_expand_dups([], Acc) ->
lists:reverse(Acc);
changes_expand_dups([{{[Key, Seq], DocId}, {dups, Vals}} | Rest], Acc) ->
- Expanded = [{{Key, Seq, DocId}, Val} || Val <- Vals],
+ Expanded = [{{Seq, Key, DocId}, Val} || Val <- Vals],
changes_expand_dups(Rest, Expanded ++ Acc);
-changes_expand_dups([{{Key, Seq}, {DocId, {dups, Vals}}} | Rest], Acc) ->
- Expanded = [{{Key, Seq, DocId}, Val} || Val <- Vals],
+changes_expand_dups([{{Seq, Key}, {DocId, {dups, Vals}}} | Rest], Acc) ->
+ Expanded = [{{Seq, Key, DocId}, Val} || Val <- Vals],
changes_expand_dups(Rest, Expanded ++ Acc);
changes_expand_dups([{{[Key, Seq], DocId}, Val} | Rest], Acc) ->
- changes_expand_dups(Rest, [{{Key, Seq, DocId}, Val} | Acc]);
-changes_expand_dups([{{Key, Seq}, {DocId, Val}} | Rest], Acc) ->
- changes_expand_dups(Rest, [{{Key, Seq, DocId}, Val} | Acc]).
+ changes_expand_dups(Rest, [{{Seq, Key, DocId}, Val} | Acc]);
+changes_expand_dups([{{Seq, Key}, {DocId, Val}} | Rest], Acc) ->
+ changes_expand_dups(Rest, [{{Seq, Key, DocId}, Val} | Acc]).
maybe_load_doc(_Db, _DI, #mrargs{include_docs=false}) ->
[];
diff --git a/apps/couch_mrview/test/08-changes_since.t b/apps/couch_mrview/test/08-changes_since.t
new file mode 100644
index 000000000..3127cff41
--- /dev/null
+++ b/apps/couch_mrview/test/08-changes_since.t
@@ -0,0 +1,123 @@
+#!/usr/bin/env escript
+%% -*- erlang -*-
+%%! -pa ./deps/*/ebin -pa ./apps/*/ebin -pa ./test/etap
+
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+main(_) ->
+ etap:plan(10),
+ case (catch test()) of
+ ok ->
+ etap:end_tests();
+ Other ->
+ etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
+ etap:bail(Other)
+ end,
+ timer:sleep(300),
+ ok.
+
+test() ->
+ test_util:start_couch(),
+
+ {ok, Db} = couch_mrview_test_util:init_db(<<"foo">>, changes),
+
+ test_basic(Db),
+ test_range(Db),
+ test_basic_since(Db),
+ test_range_since(Db),
+ test_basic_count(Db),
+ test_range_count(Db),
+ test_basic_count_since(Db),
+ test_range_count_since(Db),
+ test_compact(Db),
+ test_util:stop_couch(),
+ ok.
+
+
+test_basic(Db) ->
+ Result = run_query(Db, 0, []),
+ Expect = {ok, [
+ {{2, 1, <<"1">>}, 1},
+ {{3, 10, <<"10">>}, 10},
+ {{4, 2, <<"2">>}, 2},
+ {{5, 3, <<"3">>}, 3},
+ {{6, 4, <<"4">>}, 4},
+ {{7, 5, <<"5">>}, 5},
+ {{8, 6, <<"6">>}, 6},
+ {{9, 7, <<"7">>}, 7},
+ {{10, 8, <<"8">>}, 8},
+ {{11, 9, <<"9">>}, 9}
+ ]},
+ etap:is(Result, Expect, "Simple view query worked.").
+
+
+test_range(Db) ->
+ Result = run_query(Db, 0, [{start_key, 3}, {end_key, 5}]),
+ Expect = {ok, [
+ {{5, 3, <<"3">>}, 3},
+ {{6, 4, <<"4">>}, 4},
+ {{7, 5, <<"5">>}, 5}
+ ]},
+ etap:is(Result, Expect, "Query with range works.").
+
+test_basic_since(Db) ->
+ Result = run_query(Db, 5, []),
+ Expect = {ok, [
+ {{6, 4, <<"4">>}, 4},
+ {{7, 5, <<"5">>}, 5},
+ {{8, 6, <<"6">>}, 6},
+ {{9, 7, <<"7">>}, 7},
+ {{10, 8, <<"8">>}, 8},
+ {{11, 9, <<"9">>}, 9}
+ ]},
+ etap:is(Result, Expect, "Simple view query since 5 worked.").
+
+test_range_since(Db) ->
+ Result = run_query(Db, 5, [{start_key, 3}, {end_key, 5}]),
+ Expect = {ok, [
+ {{6, 4, <<"4">>}, 4},
+ {{7, 5, <<"5">>}, 5}
+ ]},
+ etap:is(Result, Expect, "Query with range since 5 works.").
+
+test_basic_count(Db) ->
+ Result = run_count_query(Db, 0, []),
+ etap:is(Result, 10, "Simple view count worked.").
+
+test_range_count(Db) ->
+ Result = run_count_query(Db, 0, [{start_key, 3}, {end_key, 5}]),
+ etap:is(Result, 3, "Count with range works.").
+
+test_basic_count_since(Db) ->
+ Result = run_count_query(Db, 5, []),
+ etap:is(Result, 6, "Simple view count since 5 worked.").
+
+test_range_count_since(Db) ->
+ Result = run_count_query(Db, 5, [{start_key, 3}, {end_key, 5}]),
+ etap:is(Result, 2, "Count with range since 5 works.").
+
+test_compact(Db) ->
+ Result = couch_mrview:compact(Db, <<"_design/bar">>),
+ etap:is(Result, ok, "compact view is OK"),
+ Count = run_count_query(Db, 0, []),
+ etap:is(Count, 10, "compact view worked.").
+
+run_query(Db, Since, Opts) ->
+ Fun = fun(KV, Acc) -> {ok, [KV | Acc]} end,
+ {ok, R} = couch_mrview:view_changes_since(Db, <<"_design/bar">>, <<"baz">>,
+ Since, Fun, Opts, []),
+ {ok, lists:reverse(R)}.
+
+run_count_query(Db, Since, Opts) ->
+ couch_mrview:count_view_changes_since(Db, <<"_design/bar">>, <<"baz">>,
+ Since, Opts).