diff options
author | Robert Newson <rnewson@apache.org> | 2018-08-09 13:43:17 +0100 |
---|---|---|
committer | Robert Newson <rnewson@apache.org> | 2018-09-05 11:51:31 +0100 |
commit | 22b53d80c5831f0122ffe36956b96f061cf2668e (patch) | |
tree | f1ece4b66c9dabf224b243ce15fdd16212d12a1d | |
parent | 6fb13e50b3d6843abbf6529fabd5e18cc4eeca53 (diff) | |
download | couchdb-22b53d80c5831f0122ffe36956b96f061cf2668e.tar.gz |
Implement _all_docs and _find support
Co-authored-by: Garren Smith <garren.smith@gmail.com>
Co-authored-by: Robert Newson <rnewson@apache.org>
-rw-r--r-- | src/chttpd/src/chttpd_db.erl | 7 | ||||
-rw-r--r-- | src/couch_mrview/src/couch_mrview.erl | 7 | ||||
-rw-r--r-- | src/couch_mrview/src/couch_mrview_updater.erl | 4 | ||||
-rw-r--r-- | src/couch_mrview/src/couch_mrview_util.erl | 75 | ||||
-rw-r--r-- | src/fabric/src/fabric_view.erl | 2 | ||||
-rw-r--r-- | src/fabric/src/fabric_view_all_docs.erl | 2 | ||||
-rw-r--r-- | src/mango/src/mango_cursor_view.erl | 29 | ||||
-rw-r--r-- | src/mango/src/mango_opts.erl | 6 | ||||
-rw-r--r-- | src/mem3/src/mem3.erl | 5 |
9 files changed, 111 insertions, 26 deletions
diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl index c8a10d322..d1f0b811d 100644 --- a/src/chttpd/src/chttpd_db.erl +++ b/src/chttpd/src/chttpd_db.erl @@ -684,12 +684,13 @@ multi_all_docs_view(Req, Db, OP, Queries) -> all_docs_view(Req, Db, Keys, OP) -> Args0 = couch_mrview_http:parse_params(Req, Keys), Args1 = Args0#mrargs{view_type=map}, - Args2 = couch_mrview_util:validate_args(Args1), - Args3 = set_namespace(OP, Args2), + Args2 = couch_mrview_util:set_extra(Args1, style, all_docs), + Args3 = couch_mrview_util:validate_args(Args2), + Args4 = set_namespace(OP, Args3), Options = [{user_ctx, Req#httpd.user_ctx}], Max = chttpd:chunked_response_buffer_size(), VAcc = #vacc{db=Db, req=Req, threshold=Max}, - {ok, Resp} = fabric:all_docs(Db, Options, fun couch_mrview_http:view_cb/2, VAcc, Args3), + {ok, Resp} = fabric:all_docs(Db, Options, fun couch_mrview_http:view_cb/2, VAcc, Args4), {ok, Resp#vacc.resp}. db_doc_req(#httpd{method='DELETE'}=Req, Db, DocId) -> diff --git a/src/couch_mrview/src/couch_mrview.erl b/src/couch_mrview/src/couch_mrview.erl index 09945f555..f5963e70f 100644 --- a/src/couch_mrview/src/couch_mrview.erl +++ b/src/couch_mrview/src/couch_mrview.erl @@ -228,12 +228,13 @@ query_all_docs(Db, Args0, Callback, Acc) -> couch_index_util:hexsig(couch_hash:md5_hash(term_to_binary(Info))) end), Args1 = Args0#mrargs{view_type=map}, - Args2 = couch_mrview_util:validate_args(Args1), - {ok, Acc1} = case Args2#mrargs.preflight_fun of + Args2 = couch_mrview_util:set_extra(Args1, style, all_docs), + Args3 = couch_mrview_util:validate_args(Args2), + {ok, Acc1} = case Args3#mrargs.preflight_fun of PFFun when is_function(PFFun, 2) -> PFFun(Sig, Acc); _ -> {ok, Acc} end, - all_docs_fold(Db, Args2, Callback, Acc1). + all_docs_fold(Db, Args3, Callback, Acc1). query_view(Db, DDoc, VName) -> diff --git a/src/couch_mrview/src/couch_mrview_updater.erl b/src/couch_mrview/src/couch_mrview_updater.erl index 2b69eee0f..0c1a17c26 100644 --- a/src/couch_mrview/src/couch_mrview_updater.erl +++ b/src/couch_mrview/src/couch_mrview_updater.erl @@ -315,7 +315,9 @@ write_kvs(State, UpdateSeq, ViewKVs, DocIdKeys, Seqs, Log0) -> design_opts=DesignOpts } = State, - Partitioned = couch_util:get_value(<<"partitioned">>, DesignOpts, false), + DbPartitioned = mem3:is_partitioned(State#mrst.db_name), + Partitioned = couch_util:get_value(<<"partitioned">>, DesignOpts, DbPartitioned), + Revs = dict:from_list(dict:fetch_keys(Log0)), Log = dict:fold(fun({Id, _Rev}, DIKeys, Acc) -> diff --git a/src/couch_mrview/src/couch_mrview_util.erl b/src/couch_mrview/src/couch_mrview_util.erl index 574aac70e..02e695dd0 100644 --- a/src/couch_mrview/src/couch_mrview_util.erl +++ b/src/couch_mrview/src/couch_mrview_util.erl @@ -39,8 +39,11 @@ -define(GET_VIEW_RETRY_COUNT, 1). -define(GET_VIEW_RETRY_DELAY, 50). -define(LOWEST_KEY, null). --define(HIGHEST_KEY, {[{<<239, 191, 176>>, null}]}). % is {"\ufff0": null} - +-define(HIGHEST_KEY, {<<255, 255, 255, 255>>}). +-define(PARTITION_START(P), <<P/binary, $:>>). +-define(PARTITION_END(P), <<P/binary, $;>>). +-define(LOWEST(A, B), (if A < B -> A; true -> B end)). +-define(HIGHEST(A, B), (if A > B -> A; true -> B end)). -include_lib("couch/include/couch_db.hrl"). -include_lib("couch_mrview/include/couch_mrview.hrl"). @@ -583,20 +586,38 @@ validate_args(Args) -> _ -> mrverror(<<"Invalid value for `sorted`.">>) end, - case {get_extra(Args, partitioned, false), get_extra(Args, partition)} of - {true, undefined} -> + Style = get_extra(Args, style, normal), + Partitioned = get_extra(Args, partitioned, false), + Partition = get_extra(Args, partition), + + case {Style, Partitioned, Partition} of + {all_docs, true, _} -> + ok; % _all_docs can be called with or without partition parameter. + {all_docs, false, undefined} -> + ok; + {all_docs, false, _Partition} -> + mrverror(<<"`partition` parameter is not supported in this db.">>); + {normal, true, undefined} -> mrverror(<<"`partition` parameter is mandatory for queries to this view.">>); - {true, _Partition} -> + {normal, true, _Partition} -> ok; - {false, undefined} -> + {normal, false, undefined} -> ok; - {false, _Partition} -> + {normal, false, _Partition} -> mrverror(<<"`partition` parameter is not supported in this view.">>) end, - Args1 = case get_extra(Args, partitioned, false) of - true -> apply_partition(Args); - false -> Args + Args1 = case {Style, Partitioned, Partition} of + {all_docs, true, undefined} -> + Args; + {all_docs, true, Partition} -> + apply_partition(Args, all_docs); + {all_docs, false, _} -> + Args; + {normal, true, _} -> + apply_partition(Args, normal); + {normal, false, _} -> + Args end, Args1#mrargs{ @@ -617,9 +638,12 @@ determine_group_level(#mrargs{group=true, group_level=undefined}) -> determine_group_level(#mrargs{group_level=GroupLevel}) -> GroupLevel. -apply_partition(#mrargs{} = Args0) -> +apply_partition(#mrargs{} = Args0, Style) -> Partition = get_extra(Args0, partition), - apply_partition(Partition, Args0). + case Style of + normal -> apply_partition(Partition, Args0); + all_docs -> apply_all_docs_partition(Partition, Args0) + end; apply_partition(_Partition, #mrargs{keys=[{p, _, _} | _]} = Args) -> Args; % already applied @@ -650,6 +674,33 @@ apply_partition(Partition, Args) -> end_key = {p, Partition, EK0} }. +%% all_docs is special as it's not really a view and is already +%% effectively partitioned as the partition is a prefix of all keys. +apply_all_docs_partition(Partition, #mrargs{direction=fwd, start_key=undefined, end_key=undefined} = Args) -> + Args#mrargs{start_key = ?PARTITION_START(Partition), end_key = ?PARTITION_END(Partition)}; + +apply_all_docs_partition(Partition, #mrargs{direction=rev, start_key=undefined, end_key=undefined} = Args) -> + Args#mrargs{start_key = ?PARTITION_END(Partition), end_key = ?PARTITION_START(Partition)}; + +apply_all_docs_partition(Partition, #mrargs{direction=fwd, start_key=SK, end_key=undefined} = Args) -> + Args#mrargs{start_key = ?HIGHEST(?PARTITION_START(Partition), SK), end_key = ?PARTITION_END(Partition)}; + +apply_all_docs_partition(Partition, #mrargs{direction=rev, start_key=SK, end_key=undefined} = Args) -> + Args#mrargs{start_key = ?LOWEST(?PARTITION_END(Partition), SK), end_key = ?PARTITION_START(Partition)}; + +apply_all_docs_partition(Partition, #mrargs{direction=fwd, start_key=undefined, end_key=EK} = Args) -> + Args#mrargs{start_key = ?PARTITION_START(Partition), end_key = ?LOWEST(?PARTITION_END(Partition), EK)}; + +apply_all_docs_partition(Partition, #mrargs{direction=rev, start_key=undefined, end_key=EK} = Args) -> + Args#mrargs{start_key = ?PARTITION_END(Partition), end_key = ?HIGHEST(?PARTITION_START(Partition), EK)}; + +apply_all_docs_partition(Partition, #mrargs{direction=fwd, start_key=SK, end_key=EK} = Args) -> + Args#mrargs{start_key = ?HIGHEST(?PARTITION_START(Partition), SK), end_key = ?LOWEST(?PARTITION_END(Partition), EK)}; + +apply_all_docs_partition(Partition, #mrargs{direction=rev, start_key=SK, end_key=EK} = Args) -> + Args#mrargs{start_key = ?LOWEST(?PARTITION_END(Partition), SK), end_key = ?HIGHEST(?PARTITION_START(Partition), EK)}. + + check_range(#mrargs{start_key=undefined}, _Cmp) -> ok; check_range(#mrargs{end_key=undefined}, _Cmp) -> diff --git a/src/fabric/src/fabric_view.erl b/src/fabric/src/fabric_view.erl index 844b44dfd..c0e29740d 100644 --- a/src/fabric/src/fabric_view.erl +++ b/src/fabric/src/fabric_view.erl @@ -122,7 +122,7 @@ maybe_send_row(State) -> user_acc = AccIn, query_args = QueryArgs } = State, - Partitioned = couch_mrview_util:get_extra(QueryArgs, partitioned, false), + Partitioned = couch_mrview_util:get_extra(QueryArgs, partitioned), case fabric_dict:any(0, Counters) of true -> {ok, State}; diff --git a/src/fabric/src/fabric_view_all_docs.erl b/src/fabric/src/fabric_view_all_docs.erl index ac16dac52..d515ab830 100644 --- a/src/fabric/src/fabric_view_all_docs.erl +++ b/src/fabric/src/fabric_view_all_docs.erl @@ -118,7 +118,7 @@ go(DbName, _Options, Workers, QueryArgs, Callback, Acc0) -> #mrargs{limit = Limit, skip = Skip, update_seq = UpdateSeq} = QueryArgs, State = #collector{ db_name = DbName, - query_args = QueryArgs, + query_args = couch_mrview_util:set_extra(QueryArgs, style, all_docs), callback = Callback, counters = fabric_dict:init(Workers, 0), skip = Skip, diff --git a/src/mango/src/mango_cursor_view.erl b/src/mango/src/mango_cursor_view.erl index dbea36e77..708a73e13 100644 --- a/src/mango/src/mango_cursor_view.erl +++ b/src/mango/src/mango_cursor_view.erl @@ -29,6 +29,7 @@ -include_lib("couch/include/couch_db.hrl"). -include_lib("couch_mrview/include/couch_mrview.hrl"). -include("mango_cursor.hrl"). +-include("mango_idx.hrl"). -include("mango_idx_view.hrl"). create(Db, Indexes, Selector, Opts) -> @@ -71,7 +72,8 @@ explain(Cursor) -> {direction, Args#mrargs.direction}, {stable, Args#mrargs.stable}, {update, Args#mrargs.update}, - {conflicts, Args#mrargs.conflicts} + {conflicts, Args#mrargs.conflicts}, + {extra, {Args#mrargs.extra}} ]}}]. @@ -93,14 +95,33 @@ maybe_replace_max_json([H | T] = EndKey) when is_list(EndKey) -> maybe_replace_max_json(EndKey) -> EndKey. -base_args(#cursor{index = Idx} = Cursor) -> - #mrargs{ +base_args(#cursor{index = Idx, opts = Opts} = Cursor) -> + Args1 = #mrargs{ view_type = map, reduce = false, start_key = mango_idx:start_key(Idx, Cursor#cursor.ranges), end_key = mango_idx:end_key(Idx, Cursor#cursor.ranges), include_docs = true - }. + }, + Args2 = case mem3:is_partitioned(Idx#idx.dbname) of + true -> + Partition = couch_util:get_value(partition, Opts), + add_partition_opts(Args1, Partition); + false -> + Args1 + end, + add_style(Idx, Args2). + +add_partition_opts(#mrargs{} = Args, <<>>) -> + Args; +add_partition_opts(#mrargs{} = Args, Partition) -> + Args1 = couch_mrview_util:set_extra(Args, partitioned, true), + couch_mrview_util:set_extra(Args1, partition, Partition). + +add_style(#idx{def = all_docs}, Args) -> + couch_mrview_util:set_extra(Args, style, all_docs); +add_style(_, Args) -> + Args. execute(#cursor{db = Db, index = Idx, execution_stats = Stats} = Cursor0, UserFun, UserAcc) -> diff --git a/src/mango/src/mango_opts.erl b/src/mango/src/mango_opts.erl index 7bae9c90d..87d876a3c 100644 --- a/src/mango/src/mango_opts.erl +++ b/src/mango/src/mango_opts.erl @@ -81,6 +81,12 @@ validate_find({Props}) -> {tag, selector}, {validator, fun validate_selector/1} ]}, + {<<"partition">>, [ + {tag, partition}, + {optional, true}, + {default, <<>>}, + {validator, fun is_string/1} + ]}, {<<"use_index">>, [ {tag, use_index}, {optional, true}, diff --git a/src/mem3/src/mem3.erl b/src/mem3/src/mem3.erl index bafb22765..e3cd388ba 100644 --- a/src/mem3/src/mem3.erl +++ b/src/mem3/src/mem3.erl @@ -348,7 +348,10 @@ is_partitioned(DbName0) when is_binary(DbName0) -> false end; -is_partitioned(Shards) when is_list(Shards) -> +is_partitioned([#shard{} | _] = Shards) -> + lists:all(fun is_partitioned/1, Shards); + +is_partitioned([#ordered_shard{} | _] = Shards) -> lists:all(fun is_partitioned/1, Shards); is_partitioned(#shard{opts=Opts}) -> |