From e818a3d03b78f8a9e64d5111ed469ed45b5d000b Mon Sep 17 00:00:00 2001 From: Nick Vatamaniuc Date: Thu, 23 Sep 2021 18:43:14 -0400 Subject: Make view merge row aggregation in fabric stable We do that by matching the comparator function behavior used during row merging [1] in with the comparison function used when sorting the rows on view shards [2]. This goes along with the constraint in the lists:merge/3 docs which indicates that the input lists should be sorted according to the same comparator [3] as the one passed to the lists:merge/3 call. The stability of returned rows results from the case when both keys match as equal. Now `lists:merge/3` will favor the element in the existing rows list instead of always replacing [4] the older matching row with the last arriving row, since now `less(A, A)` will be `false`, while previously it was `true`. The fix was found by Adam when discussing issue #3750 https://github.com/apache/couchdb/issues/3750#issuecomment-920947424 Co-author: Adam Kocoloski [1] https://github.com/apache/couchdb/blob/3.x/src/fabric/src/fabric_view_map.erl#L244-L248 [2] https://github.com/apache/couchdb/blob/3.x/src/couch_mrview/src/couch_mrview_util.erl#L1103-L1107 [3] https://erlang.org/doc/man/lists.html#merge-3 [4] https://github.com/erlang/otp/blob/master/lib/stdlib/src/lists.erl#L2668-L2675 --- src/fabric/src/fabric_view.erl | 1 - src/fabric/src/fabric_view_map.erl | 1 - 2 files changed, 2 deletions(-) diff --git a/src/fabric/src/fabric_view.erl b/src/fabric/src/fabric_view.erl index 425f864c4..bd5e42f09 100644 --- a/src/fabric/src/fabric_view.erl +++ b/src/fabric/src/fabric_view.erl @@ -298,7 +298,6 @@ transform_row(#view_row{key=Key, id=_Id, value=_Value, doc={error,Reason}}) -> transform_row(#view_row{key=Key, id=Id, value=Value, doc=Doc}) -> {row, [{id,Id}, {key,Key}, {value,Value}, {doc,Doc}]}. -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(A, B); diff --git a/src/fabric/src/fabric_view_map.erl b/src/fabric/src/fabric_view_map.erl index 8ab808314..adfe7d648 100644 --- a/src/fabric/src/fabric_view_map.erl +++ b/src/fabric/src/fabric_view_map.erl @@ -241,7 +241,6 @@ merge_row(Dir, Collation, KeyDict0, Row, Rows0) -> {Rows1, KeyDict1} end. -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); -- cgit v1.2.1