Switch to using couch_mrview data structures and utility functions
This updates the data structures expected for view callbacks, mainly
switching total_and_offset to the new meta response, and also slight
modifications to the expected row format.
Additionally this removes view logic from fabric that is better
handled in couch_mrview.
diff --git a/src/fabric.erl b/src/fabric.erl
index 1f05ed6..5be6f49 100644
--- a/src/fabric.erl
+++ b/src/fabric.erl
@@ -278,15 +278,31 @@
-spec query_view(dbname(), #doc{} | binary(), iodata(), callback(), any(),
#mrargs{}) ->
any().
-query_view(DbName, Design, ViewName, Callback, Acc0, QueryArgs) ->
+query_view(DbName, GroupId, ViewName, Callback, Acc0, QueryArgs)
+ when is_binary(GroupId) ->
+ {ok, DDoc} = ddoc_cache:open(DbName, <<"_design/", GroupId/binary>>),
+ query_view(DbName, DDoc, ViewName, Callback, Acc0, QueryArgs);
+query_view(DbName, DDoc, ViewName, Callback, Acc0, QueryArgs0) ->
Db = dbname(DbName), View = name(ViewName),
- case is_reduce_view(Db, Design, View, QueryArgs) of
- true ->
- Mod = fabric_view_reduce;
- false ->
- Mod = fabric_view_map
- end,
- Mod:go(Db, Design, View, QueryArgs, Callback, Acc0).
+ {ok, #mrst{views=Views, language=Lang}} =
+ couch_mrview_util:ddoc_to_mrst(Db, DDoc),
+ QueryArgs1 = couch_mrview_util:set_view_type(QueryArgs0, View, Views),
+ QueryArgs2 = couch_mrview_util:validate_args(QueryArgs1),
+ VInfo = couch_mrview_util:extract_view(Lang, QueryArgs2, View, Views),
+ case is_reduce_view(QueryArgs2) of
+ true ->
+ fabric_view_reduce:go(
+ Db,
+ DDoc,
+ View,
+ QueryArgs2,
+ Callback,
+ Acc0,
+ VInfo
+ );
+ false ->
+ fabric_view_map:go(Db, DDoc, View, QueryArgs2, Callback, Acc0)
+ end.
%% @doc retrieve info about a view group, disk size, language, whether compaction
%% is running and so forth
@@ -313,9 +329,9 @@
end_key = <<"_design0">>,
include_docs=true
},
- Callback = fun({total_and_offset, _, _}, []) ->
+ Callback = fun({meta, _}, []) ->
{ok, []};
- ({row, {Props}}, Acc) ->
+ ({row, Props}, Acc) ->
case couch_util:get_value(id, Props) of
<<"_design/", _/binary>> ->
{ok, [couch_util:get_value(doc, Props) | Acc]};
@@ -437,8 +453,10 @@
default_callback(Row, Acc) ->
{ok, [Row | Acc]}.
-is_reduce_view(_, _, _, #mrargs{view_type=Reduce}) ->
- Reduce =:= reduce.
+is_reduce_view(#mrargs{view_type=ViewType}) ->
+ ViewType =:= red;
+is_reduce_view({Reduce, _, _}) ->
+ Reduce =:= red.
%% @doc convenience method for use in the shell, converts a keylist
%% to a `changes_args' record
diff --git a/src/fabric_group_info.erl b/src/fabric_group_info.erl
index 135090f..5325f76 100644
--- a/src/fabric_group_info.erl
+++ b/src/fabric_group_info.erl
@@ -22,10 +22,9 @@
{ok, DDoc} = fabric:open_doc(DbName, GroupId, []),
go(DbName, DDoc);
-go(DbName, #doc{} = DDoc) ->
- Group = couch_view_group:design_doc_to_view_group(DDoc),
+go(DbName, #doc{id=DDocId}) ->
Shards = mem3:shards(DbName),
- Workers = fabric_util:submit_jobs(Shards, group_info, [Group]),
+ Workers = fabric_util:submit_jobs(Shards, group_info, [DDocId]),
RexiMon = fabric_util:create_monitors(Shards),
Acc0 = {fabric_dict:init(Workers, nil), []},
try
diff --git a/src/fabric_rpc.erl b/src/fabric_rpc.erl
index 3f4f8d2..cee3c55 100644
--- a/src/fabric_rpc.erl
+++ b/src/fabric_rpc.erl
@@ -24,18 +24,6 @@
-include_lib("couch/include/couch_db.hrl").
-include_lib("couch_mrview/include/couch_mrview.hrl").
--record (view_acc, {
- db,
- limit,
- include_docs,
- conflicts,
- doc_info = nil,
- offset = nil,
- total_rows,
- reduce_fun = fun couch_db:enum_docs_reduce_to_count/1,
- group_level = 0
-}).
-
%% rpc endpoints
%% call to with_db will supply your M:F with a #db{} and then remaining args
diff --git a/src/fabric_view.erl b/src/fabric_view.erl
index d0c6e45..31c25d9 100644
--- a/src/fabric_view.erl
+++ b/src/fabric_view.erl
@@ -224,7 +224,10 @@
Counters1 = fabric_dict:update_counter(Worker, -1, Counters0),
{Row, State#collector{rows = Rest, counters=Counters1}}.
+%% TODO: rectify nil <-> undefined discrepancies
find_next_key(nil, Dir, RowDict) ->
+ find_next_key(undefined, Dir, RowDict);
+find_next_key(undefined, Dir, RowDict) ->
case lists:sort(sort_fun(Dir), dict:fetch_keys(RowDict)) of
[] ->
throw(complete);
@@ -237,21 +240,21 @@
{Key, Rest}.
transform_row(#view_row{key=Key, id=reduced, value=Value}) ->
- {row, {[{key,Key}, {value,Value}]}};
+ {row, [{key,Key}, {value,Value}]};
transform_row(#view_row{key=Key, id=undefined}) ->
- {row, {[{key,Key}, {error,not_found}]}};
+ {row, [{key,Key}, {id,error}, {value,not_found}]};
transform_row(#view_row{key=Key, id=Id, value=Value, doc=undefined}) ->
- {row, {[{id,Id}, {key,Key}, {value,Value}]}};
-transform_row(#view_row{key=Key, id=Id, value=Value, doc={error,Reason}}) ->
- {row, {[{id,Id}, {key,Key}, {value,Value}, {error,Reason}]}};
+ {row, [{id,Id}, {key,Key}, {value,Value}]};
+transform_row(#view_row{key=Key, id=_Id, value=_Value, doc={error,Reason}}) ->
+ {row, [{id,error}, {key,Key}, {value,Reason}]};
transform_row(#view_row{key=Key, id=Id, value=Value, doc=Doc}) ->
- {row, {[{id,Id}, {key,Key}, {value,Value}, {doc,Doc}]}}.
+ {row, [{id,Id}, {key,Key}, {value,Value}, {doc,Doc}]}.
sort_fun(fwd) ->
- fun(A,A) -> true; (A,B) -> couch_view:less_json(A,B) end;
+ fun(A,A) -> true; (A,B) -> couch_ejson_compare:less_json(A,B) end;
sort_fun(rev) ->
- fun(A,A) -> true; (A,B) -> couch_view:less_json(B,A) end.
+ fun(A,A) -> true; (A,B) -> couch_ejson_compare:less_json(B,A) end.
extract_view(Pid, ViewName, [], _ViewType) ->
couch_log:error("missing_named_view ~p", [ViewName]),
diff --git a/src/fabric_view_all_docs.erl b/src/fabric_view_all_docs.erl
index 1415c82..701afa7 100644
--- a/src/fabric_view_all_docs.erl
+++ b/src/fabric_view_all_docs.erl
@@ -72,7 +72,7 @@
false -> Keys2
end,
receive {'DOWN', Ref0, _, _, {ok, TotalRows}} ->
- {ok, Acc1} = Callback({total_and_offset, TotalRows, 0}, Acc0),
+ {ok, Acc1} = Callback({meta, [{total, TotalRows}]}, Acc0),
{ok, Acc2} = doc_receive_loop(
Keys3, queue:new(), SpawnFun, MaxJobs, Callback, Acc1
),
@@ -95,7 +95,9 @@
{error, Resp}
end;
-handle_message({total_and_offset, Tot, Off}, {Worker, From}, State) ->
+handle_message({meta, Meta0}, {Worker, From}, State) ->
+ Tot = couch_util:get_value(total, Meta0, 0),
+ Off = couch_util:get_value(offset, Meta0, 0),
#collector{
callback = Callback,
counters = Counters0,
@@ -123,7 +125,8 @@
}};
false ->
FinalOffset = erlang:min(Total, Offset+State#collector.skip),
- {Go, Acc} = Callback({total_and_offset, Total, FinalOffset}, AccIn),
+ Meta = [{total, Total}, {offset, FinalOffset}],
+ {Go, Acc} = Callback({meta, Meta}, AccIn),
{Go, State#collector{
counters = fabric_dict:decrement_all(Counters2),
total_rows = Total,
diff --git a/src/fabric_view_map.erl b/src/fabric_view_map.erl
index 9e41c11..eb30179 100644
--- a/src/fabric_view_map.erl
+++ b/src/fabric_view_map.erl
@@ -66,7 +66,9 @@
{error, Resp}
end;
-handle_message({total_and_offset, Tot, Off}, {Worker, From}, State) ->
+handle_message({meta, Meta0}, {Worker, From}, State) ->
+ Tot = couch_util:get_value(total, Meta0, 0),
+ Off = couch_util:get_value(offset, Meta0, 0),
#collector{
callback = Callback,
counters = Counters0,
@@ -94,7 +96,8 @@
}};
false ->
FinalOffset = erlang:min(Total, Offset+State#collector.skip),
- {Go, Acc} = Callback({total_and_offset, Total, FinalOffset}, AccIn),
+ Meta = [{total, Total}, {offset, FinalOffset}],
+ {Go, Acc} = Callback({meta, Meta}, AccIn),
{Go, State#collector{
counters = fabric_dict:decrement_all(Counters2),
total_rows = Total,
@@ -133,11 +136,11 @@
merge_row(fwd, undefined, Row, Rows) ->
lists:merge(fun(#view_row{key=KeyA, id=IdA}, #view_row{key=KeyB, id=IdB}) ->
- couch_view:less_json([KeyA, IdA], [KeyB, IdB])
+ couch_ejson_compare:less_json_ids({KeyA, IdA}, {KeyB, IdB})
end, [Row], Rows);
merge_row(rev, undefined, Row, Rows) ->
lists:merge(fun(#view_row{key=KeyA, id=IdA}, #view_row{key=KeyB, id=IdB}) ->
- couch_view:less_json([KeyB, IdB], [KeyA, IdA])
+ couch_ejson_compare:less_json_ids({KeyB, IdB}, {KeyA, IdA})
end, [Row], Rows);
merge_row(_, KeyDict, Row, Rows) ->
lists:merge(fun(#view_row{key=A, id=IdA}, #view_row{key=B, id=IdB}) ->