Support raw collation in map results
COUCHDB-2900
diff --git a/src/fabric.erl b/src/fabric.erl
index 07c4c9c..97f766b 100644
--- a/src/fabric.erl
+++ b/src/fabric.erl
@@ -346,7 +346,15 @@
VInfo
);
false ->
- fabric_view_map:go(Db, DDoc, View, QueryArgs2, Callback, Acc0)
+ fabric_view_map:go(
+ Db,
+ DDoc,
+ View,
+ QueryArgs2,
+ Callback,
+ Acc0,
+ VInfo
+ )
end.
%% @doc retrieve info about a view group, disk size, language, whether compaction
diff --git a/src/fabric_view_map.erl b/src/fabric_view_map.erl
index 1977888..3853d3e 100644
--- a/src/fabric_view_map.erl
+++ b/src/fabric_view_map.erl
@@ -12,18 +12,18 @@
-module(fabric_view_map).
--export([go/6]).
+-export([go/7]).
-include_lib("fabric/include/fabric.hrl").
-include_lib("mem3/include/mem3.hrl").
-include_lib("couch/include/couch_db.hrl").
-include_lib("couch_mrview/include/couch_mrview.hrl").
-go(DbName, GroupId, View, Args, Callback, Acc0) when is_binary(GroupId) ->
+go(DbName, GroupId, View, Args, Callback, Acc, VInfo) when is_binary(GroupId) ->
{ok, DDoc} = fabric:open_doc(DbName, <<"_design/", GroupId/binary>>, []),
- go(DbName, DDoc, View, Args, Callback, Acc0);
+ go(DbName, DDoc, View, Args, Callback, Acc, VInfo);
-go(DbName, DDoc, View, Args, Callback, Acc) ->
+go(DbName, DDoc, View, Args, Callback, Acc, VInfo) ->
Shards = fabric_view:get_shards(DbName, Args),
Repls = fabric_view:get_shard_replacements(DbName, Shards),
RPCArgs = [fabric_util:doc_id_and_rev(DDoc), View, Args],
@@ -36,7 +36,7 @@
case fabric_util:stream_start(Workers0, #shard.ref, StartFun, Repls) of
{ok, Workers} ->
try
- go(DbName, Workers, Args, Callback, Acc)
+ go(DbName, Workers, VInfo, Args, Callback, Acc)
after
fabric_util:cleanup(Workers)
end;
@@ -57,8 +57,9 @@
rexi_monitor:stop(RexiMon)
end.
-go(DbName, Workers, Args, Callback, Acc0) ->
+go(DbName, Workers, {map, View, _}, Args, Callback, Acc0) ->
#mrargs{limit = Limit, skip = Skip, keys = Keys} = Args,
+ Collation = couch_util:get_value(<<"collation">>, View#mrview.options),
State = #collector{
db_name=DbName,
query_args = Args,
@@ -68,6 +69,7 @@
limit = Limit,
keys = fabric_view:keydict(Keys),
sorted = Args#mrargs.sorted,
+ collation = Collation,
user_acc = Acc0
},
case rexi_utils:recv(Workers, #shard.ref, fun handle_message/3,
@@ -135,12 +137,19 @@
handle_message(#view_row{} = Row, {Worker, From}, State) ->
#collector{
- query_args = #mrargs{direction=Dir},
+ query_args = #mrargs{direction = Dir},
counters = Counters0,
rows = Rows0,
- keys = KeyDict
+ keys = KeyDict,
+ collation = Collation
} = State,
- Rows = merge_row(Dir, KeyDict, Row#view_row{worker={Worker, From}}, Rows0),
+ Rows = merge_row(
+ Dir,
+ Collation,
+ KeyDict,
+ Row#view_row{worker={Worker, From}},
+ Rows0
+ ),
Counters1 = fabric_dict:update_counter(Worker, 1, Counters0),
State1 = State#collector{rows=Rows, counters=Counters1},
fabric_view:maybe_send_row(State1);
@@ -149,17 +158,19 @@
Counters = fabric_dict:update_counter(Worker, 1, State#collector.counters),
fabric_view:maybe_send_row(State#collector{counters = Counters}).
-merge_row(fwd, undefined, Row, Rows) ->
+merge_row(Dir, Collation, undefined, Row, Rows) ->
lists:merge(fun(#view_row{key=KeyA, id=IdA}, #view_row{key=KeyB, id=IdB}) ->
- couch_ejson_compare:less_json_ids({KeyA, IdA}, {KeyB, IdB})
+ compare(Dir, Collation, {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_ejson_compare:less_json_ids({KeyB, IdB}, {KeyA, IdA})
- end, [Row], Rows);
-merge_row(_, KeyDict, Row, Rows) ->
+merge_row(_, _, KeyDict, Row, Rows) ->
lists:merge(fun(#view_row{key=A, id=IdA}, #view_row{key=B, id=IdB}) ->
if A =:= B -> IdA < IdB; true ->
dict:fetch(A, KeyDict) < dict:fetch(B, KeyDict)
end
end, [Row], Rows).
+
+compare(_, _, A, A) -> true;
+compare(fwd, <<"raw">>, A, B) -> A < B;
+compare(rev, <<"raw">>, A, B) -> B < A;
+compare(fwd, _, A, B) -> couch_ejson_compare:less_json_ids(A, B);
+compare(rev, _, A, B) -> couch_ejson_compare:less_json_ids(B, A).