summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/couchdb/couch_db.hrl1
-rw-r--r--src/couchdb/couch_httpd_view.erl8
-rw-r--r--src/couchdb/couch_view.erl25
-rw-r--r--src/couchdb/couch_view_group.erl7
-rw-r--r--src/couchdb/couch_view_updater.erl27
5 files changed, 41 insertions, 27 deletions
diff --git a/src/couchdb/couch_db.hrl b/src/couchdb/couch_db.hrl
index eb449ab7..1afea912 100644
--- a/src/couchdb/couch_db.hrl
+++ b/src/couchdb/couch_db.hrl
@@ -174,6 +174,7 @@
fd=nil,
name,
def_lang,
+ design_options=[],
views,
id_btree=nil,
current_seq=0,
diff --git a/src/couchdb/couch_httpd_view.erl b/src/couchdb/couch_httpd_view.erl
index 0d5c0df4..fc3302d7 100644
--- a/src/couchdb/couch_httpd_view.erl
+++ b/src/couchdb/couch_httpd_view.erl
@@ -68,15 +68,17 @@ handle_temp_view_req(#httpd{method='POST'}=Req, Db) ->
end,
{Props} = couch_httpd:json_body(Req),
Language = proplists:get_value(<<"language">>, Props, <<"javascript">>),
+ {DesignOptions} = proplists:get_value(<<"options">>, Props, {[]}),
MapSrc = proplists:get_value(<<"map">>, Props),
Keys = proplists:get_value(<<"keys">>, Props, nil),
case proplists:get_value(<<"reduce">>, Props, null) of
null ->
- {ok, View} = couch_view:get_temp_map_view(Db, Language, MapSrc),
+ {ok, View} = couch_view:get_temp_map_view(Db, Language,
+ DesignOptions, MapSrc),
output_map_view(Req, View, Db, QueryArgs, Keys);
RedSrc ->
- {ok, View} = couch_view:get_temp_reduce_view(Db, Language, MapSrc,
- RedSrc),
+ {ok, View} = couch_view:get_temp_reduce_view(Db, Language,
+ DesignOptions, MapSrc, RedSrc),
output_reduce_view(Req, View, QueryArgs, Keys)
end;
diff --git a/src/couchdb/couch_view.erl b/src/couchdb/couch_view.erl
index 3faec4b9..e790efd3 100644
--- a/src/couchdb/couch_view.erl
+++ b/src/couchdb/couch_view.erl
@@ -15,7 +15,7 @@
-export([start_link/0,fold/4,fold/5,less_json/2,less_json_keys/2,expand_dups/2,
detuple_kvs/2,init/1,terminate/2,handle_call/3,handle_cast/2,handle_info/2,
- code_change/3,get_reduce_view/4,get_temp_reduce_view/4,get_temp_map_view/3,
+ code_change/3,get_reduce_view/4,get_temp_reduce_view/5,get_temp_map_view/4,
get_map_view/4,get_row_count/1,reduce_to_count/1,fold_reduce/7,
extract_map_view/1]).
@@ -28,9 +28,9 @@
start_link() ->
gen_server:start_link({local, couch_view}, couch_view, [], []).
-get_temp_updater(DbName, Type, MapSrc, RedSrc) ->
+get_temp_updater(DbName, Type, DesignOptions, MapSrc, RedSrc) ->
{ok, Pid} = gen_server:call(couch_view,
- {start_temp_updater, DbName, Type, MapSrc, RedSrc}),
+ {start_temp_updater, DbName, Type, DesignOptions, MapSrc, RedSrc}),
Pid.
get_group_server(DbName, GroupId) ->
@@ -51,17 +51,17 @@ get_group(Db, GroupId, Stale) ->
MinUpdateSeq).
-get_temp_group(Db, Type, MapSrc, RedSrc) ->
+get_temp_group(Db, Type, DesignOptions, MapSrc, RedSrc) ->
couch_view_group:request_group(
- get_temp_updater(couch_db:name(Db), Type, MapSrc, RedSrc),
+ get_temp_updater(couch_db:name(Db), Type, DesignOptions, MapSrc, RedSrc),
couch_db:get_update_seq(Db)).
get_row_count(#view{btree=Bt}) ->
{ok, {Count, _Reds}} = couch_btree:full_reduce(Bt),
{ok, Count}.
-get_temp_reduce_view(Db, Type, MapSrc, RedSrc) ->
- {ok, #group{views=[View]}} = get_temp_group(Db, Type, MapSrc, RedSrc),
+get_temp_reduce_view(Db, Type, DesignOptions, MapSrc, RedSrc) ->
+ {ok, #group{views=[View]}} = get_temp_group(Db, Type, DesignOptions, MapSrc, RedSrc),
{ok, {temp_reduce, View}}.
@@ -136,8 +136,8 @@ get_key_pos(Key, [_|Rest], N) ->
get_key_pos(Key, Rest, N+1).
-get_temp_map_view(Db, Type, Src) ->
- {ok, #group{views=[View]}} = get_temp_group(Db, Type, Src, []),
+get_temp_map_view(Db, Type, DesignOptions, Src) ->
+ {ok, #group{views=[View]}} = get_temp_group(Db, Type, DesignOptions, Src, []),
{ok, View}.
get_map_view(Db, GroupId, Name, Stale) ->
@@ -220,8 +220,9 @@ terminate(_Reason,_State) ->
ok.
-handle_call({start_temp_updater, DbName, Lang, MapSrc, RedSrc}, _From, #server{root_dir=Root}=Server) ->
- <<SigInt:128/integer>> = erlang:md5(term_to_binary({Lang, MapSrc, RedSrc})),
+handle_call({start_temp_updater, DbName, Lang, DesignOptions, MapSrc, RedSrc},
+ _From, #server{root_dir=Root}=Server) ->
+ <<SigInt:128/integer>> = erlang:md5(term_to_binary({Lang, DesignOptions, MapSrc, RedSrc})),
Name = lists:flatten(io_lib:format("_temp_~.36B",[SigInt])),
Pid =
case ets:lookup(group_servers_by_name, {DbName, Name}) of
@@ -235,7 +236,7 @@ handle_call({start_temp_updater, DbName, Lang, MapSrc, RedSrc}, _From, #server{r
ok
end,
?LOG_DEBUG("Spawning new temp update process for db ~s.", [DbName]),
- {ok, NewPid} = couch_view_group:start_link({slow_view, DbName, Fd, Lang, MapSrc, RedSrc}),
+ {ok, NewPid} = couch_view_group:start_link({slow_view, DbName, Fd, Lang, DesignOptions, MapSrc, RedSrc}),
true = ets:insert(couch_temp_group_fd_by_db, {DbName, Fd, Count + 1}),
add_to_ets(NewPid, DbName, Name),
NewPid;
diff --git a/src/couchdb/couch_view_group.erl b/src/couchdb/couch_view_group.erl
index 6d193516..4e7d7767 100644
--- a/src/couchdb/couch_view_group.erl
+++ b/src/couchdb/couch_view_group.erl
@@ -262,7 +262,7 @@ prepare_group({view, RootDir, DbName, GroupId}, ForceReset)->
catch delete_index_file(RootDir, DbName, GroupId),
Error
end;
-prepare_group({slow_view, DbName, Fd, Lang, MapSrc, RedSrc}, _ForceReset) ->
+prepare_group({slow_view, DbName, Fd, Lang, DesignOptions, MapSrc, RedSrc}, _ForceReset) ->
case couch_db:open(DbName, []) of
{ok, Db} ->
View = #view{map_names=[<<"_temp">>],
@@ -271,7 +271,7 @@ prepare_group({slow_view, DbName, Fd, Lang, MapSrc, RedSrc}, _ForceReset) ->
def=MapSrc,
reduce_funs= if RedSrc==[] -> []; true -> [{<<"_temp">>, RedSrc}] end},
{ok, init_group(Db, Fd, #group{type=slow_view, name= <<"_temp">>, db=Db,
- views=[View], def_lang=Lang}, nil)};
+ views=[View], def_lang=Lang, design_options=DesignOptions}, nil)};
Error ->
Error
end.
@@ -311,6 +311,7 @@ open_db_group(DbName, GroupId) ->
% maybe move to another module
design_doc_to_view_group(#doc{id=Id,body={Fields}}) ->
Language = proplists:get_value(<<"language">>, Fields, <<"javascript">>),
+ {DesignOptions} = proplists:get_value(<<"options">>, Fields, {[]}),
{RawViews} = proplists:get_value(<<"views">>, Fields, {[]}),
% add the views to a dictionary object, with the map source as the key
@@ -338,7 +339,7 @@ design_doc_to_view_group(#doc{id=Id,body={Fields}}) ->
{View#view{id_num=N},N+1}
end, 0, dict:to_list(DictBySrc)),
- Group = #group{name=Id, views=Views, def_lang=Language},
+ Group = #group{name=Id, views=Views, def_lang=Language, design_options=DesignOptions},
Group#group{sig=erlang:md5(term_to_binary(Group))}.
reset_group(#group{views=Views}=Group) ->
diff --git a/src/couchdb/couch_view_updater.erl b/src/couchdb/couch_view_updater.erl
index b6ae860f..956ac3f1 100644
--- a/src/couchdb/couch_view_updater.erl
+++ b/src/couchdb/couch_view_updater.erl
@@ -90,43 +90,52 @@ purge_index(#group{db=Db, views=Views, id_btree=IdBtree}=Group) ->
views=Views2,
purge_seq=couch_db:get_purge_seq(Db)}.
-process_doc(Db, DocInfo, {Docs, #group{sig=Sig,name=GroupId}=Group, ViewKVs,
+process_doc(Db, DocInfo, {Docs, #group{sig=Sig,name=GroupId,design_options=DesignOptions}=Group, ViewKVs,
DocIdViewIdKeys}) ->
% This fun computes once for each document
#doc_info{id=DocId, deleted=Deleted} = DocInfo,
- case DocId of
- GroupId ->
+ IncludeDesign = proplists:get_value(<<"include_design">>,
+ DesignOptions, false),
+ case {IncludeDesign, DocId} of
+ {_, GroupId} ->
% uh oh. this is the design doc with our definitions. See if
% anything in the definition changed.
- case couch_db:open_doc(Db, DocInfo) of
+ case couch_db:open_doc(Db, DocInfo, [conflicts, deleted_conflicts]) of
{ok, Doc} ->
case couch_view_group:design_doc_to_view_group(Doc) of
#group{sig=Sig} ->
% The same md5 signature, keep on computing
- {Docs, Group, ViewKVs, DocIdViewIdKeys};
+ case IncludeDesign of
+ true ->
+ {[Doc | Docs], Group, ViewKVs, DocIdViewIdKeys};
+ _ ->
+ {Docs, Group, ViewKVs, DocIdViewIdKeys}
+ end;
_ ->
exit(reset)
end;
{not_found, deleted} ->
exit(reset)
end;
- <<?DESIGN_DOC_PREFIX, _/binary>> -> % we skip design docs
+ {false, <<?DESIGN_DOC_PREFIX, _/binary>>} -> % we skip design docs
{Docs, Group, ViewKVs, DocIdViewIdKeys};
_ ->
{Docs2, DocIdViewIdKeys2} =
if Deleted ->
{Docs, [{DocId, []} | DocIdViewIdKeys]};
true ->
- {ok, Doc} = couch_db:open_doc(Db, DocInfo, [conflicts, deleted_conflicts]),
+ {ok, Doc} = couch_db:open_doc(Db, DocInfo,
+ [conflicts, deleted_conflicts]),
{[Doc | Docs], DocIdViewIdKeys}
end,
case couch_util:should_flush() of
true ->
{Group1, Results} = view_compute(Group, Docs2),
- {ViewKVs3, DocIdViewIdKeys3} = view_insert_query_results(Docs2, Results, ViewKVs, DocIdViewIdKeys2),
+ {ViewKVs3, DocIdViewIdKeys3} = view_insert_query_results(Docs2,
+ Results, ViewKVs, DocIdViewIdKeys2),
{ok, Group2} = write_changes(Group1, ViewKVs3, DocIdViewIdKeys3,
- DocInfo#doc_info.update_seq),
+ DocInfo#doc_info.update_seq),
garbage_collect(),
ViewEmptyKeyValues = [{View, []} || View <- Group2#group.views],
{[], Group2, ViewEmptyKeyValues, []};