Skip to content

Commit

Permalink
CommonJS support in map functions
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1001895 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
jchris committed Sep 27, 2010
1 parent 6c6db01 commit 7665e44
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 26 deletions.
1 change: 1 addition & 0 deletions share/server/loop.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ var Loop = function() {
// "view" : Views.handler,
"reset" : State.reset,
"add_fun" : State.addFun,
"add_lib" : State.addLib,
"map_doc" : Views.mapDoc,
"reduce" : Views.reduce,
"rereduce" : Views.rereduce
Expand Down
7 changes: 6 additions & 1 deletion share/server/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ var State = {
reset : function(config) {
// clear the globals and run gc
State.funs = [];
State.lib = null;
State.query_config = config || {};
init_sandbox();
gc();
print("true"); // indicates success
},
addFun : function(newFun) {
// Compile to a function and add it to funs array
State.funs.push(Couch.compileFunction(newFun));
State.funs.push(Couch.compileFunction(newFun, {views : {lib : State.lib}}));
print("true");
},
addLib : function(lib) {
State.lib = lib;
print("true");
}
}
19 changes: 17 additions & 2 deletions share/www/script/test/design_docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,18 @@ function() {
summate2: {map:"function (doc) {emit(doc.integer, doc.integer)};",
reduce:"function (keys, values) { return sum(values); };"},
huge_src_and_results: {map: "function(doc) { if (doc._id == \"1\") { emit(\"" + makebigstring(16) + "\", null) }}",
reduce:"function (keys, values) { return \"" + makebigstring(16) + "\"; };"}
reduce:"function (keys, values) { return \"" + makebigstring(16) + "\"; };"},
lib : {
baz : "exports.baz = 'bam';",
foo : {
foo : "exports.foo = 'bar';",
boom : "exports.boom = 'ok';",
zoom : "exports.zoom = 'yeah';"
}
},
commonjs : {
map : "function(doc) { emit(null, require('views/lib/foo/boom').boom)}"
}
},
shows: {
simple: "function() {return 'ok'};",
Expand Down Expand Up @@ -99,10 +110,14 @@ function() {
var vinfo = dinfo.view_index;
TEquals(51, vinfo.disk_size);
TEquals(false, vinfo.compact_running);
TEquals("3f88e53b303e2342e49a66c538c30679", vinfo.signature);
TEquals("dc3264b45b74cc6d94666e3043e07154", vinfo.signature, 'ddoc sig');

db.bulkSave(makeDocs(1, numDocs + 1));

// test commonjs in map functions
resp = db.view("test/commonjs", {limit:1});
T(resp.rows[0].value == 'ok');

// test that the _all_docs view returns correctly with keys
var results = db.allDocs({startkey:"_design", endkey:"_design0"});
T(results.rows.length == 1);
Expand Down
1 change: 1 addition & 0 deletions src/couchdb/couch_db.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@
def_lang,
design_options=[],
views,
lib,
id_btree=nil,
current_seq=0,
purge_seq=0,
Expand Down
9 changes: 7 additions & 2 deletions src/couchdb/couch_query_servers.erl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
-export([start_link/0]).

-export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2,code_change/3]).
-export([start_doc_map/2, map_docs/2, stop_doc_map/1]).
-export([start_doc_map/3, map_docs/2, stop_doc_map/1]).
-export([reduce/3, rereduce/3,validate_doc_update/5]).
-export([filter_docs/5]).

Expand Down Expand Up @@ -47,8 +47,13 @@
start_link() ->
gen_server:start_link({local, couch_query_servers}, couch_query_servers, [], []).

start_doc_map(Lang, Functions) ->
start_doc_map(Lang, Functions, Lib) ->
Proc = get_os_process(Lang),
case Lib of
{[]} -> ok;
Lib ->
true = proc_prompt(Proc, [<<"add_lib">>, Lib])
end,
lists:foreach(fun(FunctionSource) ->
true = proc_prompt(Proc, [<<"add_fun">>, FunctionSource])
end, Functions),
Expand Down
58 changes: 39 additions & 19 deletions src/couchdb/couch_view_group.erl
Original file line number Diff line number Diff line change
Expand Up @@ -446,17 +446,34 @@ open_temp_group(DbName, Language, DesignOptions, MapSrc, RedSrc) ->
reduce_funs= if RedSrc==[] -> []; true -> [{<<"_temp">>, RedSrc}] end,
options=DesignOptions},

{ok, Db, set_view_sig(#group{name = <<"_temp">>, db=Db, views=[View],
{ok, Db, set_view_sig(#group{name = <<"_temp">>,lib={[]}, db=Db, views=[View],
def_lang=Language, design_options=DesignOptions})};
Error ->
Error
end.

set_view_sig(#group{
views=Views,
lib={[]},
def_lang=Language,
design_options=DesignOptions}=G) ->
G#group{sig=couch_util:md5(term_to_binary({Views, Language, DesignOptions}))}.
G#group{sig=couch_util:md5(term_to_binary({Views, Language, DesignOptions}))};
set_view_sig(#group{
views=Views,
lib=Lib,
def_lang=Language,
design_options=DesignOptions}=G) ->
G#group{sig=couch_util:md5(term_to_binary({Views, Language, DesignOptions, sort_lib(Lib)}))}.

sort_lib({Lib}) ->
sort_lib(Lib, []).
sort_lib([], LAcc) ->
lists:keysort(1, LAcc);
sort_lib([{LName, {LObj}}|Rest], LAcc) ->
LSorted = sort_lib(LObj, []), % descend into nested object
sort_lib(Rest, [{LName, LSorted}|LAcc]);
sort_lib([{LName, LCode}|Rest], LAcc) ->
sort_lib(Rest, [{LName, LCode}|LAcc]).

open_db_group(DbName, GroupId) ->
case couch_db:open_int(DbName, []) of
Expand Down Expand Up @@ -505,33 +522,36 @@ design_doc_to_view_group(#doc{id=Id,body={Fields}}) ->
Language = ?getv(<<"language">>, Fields, <<"javascript">>),
{DesignOptions} = ?getv(<<"options">>, Fields, {[]}),
{RawViews} = ?getv(<<"views">>, Fields, {[]}),
Lib = ?getv(<<"lib">>, RawViews, {[]}),
% add the views to a dictionary object, with the map source as the key
DictBySrc =
lists:foldl(
fun({Name, {MRFuns}}, DictBySrcAcc) ->
MapSrc = ?getv(<<"map">>, MRFuns),
RedSrc = ?getv(<<"reduce">>, MRFuns, null),
{ViewOptions} = ?getv(<<"options">>, MRFuns, {[]}),
View =
case dict:find({MapSrc, ViewOptions}, DictBySrcAcc) of
{ok, View0} -> View0;
error -> #view{def=MapSrc, options=ViewOptions} % create new view object
end,
View2 =
if RedSrc == null ->
View#view{map_names=[Name|View#view.map_names]};
true ->
View#view{reduce_funs=[{Name,RedSrc}|View#view.reduce_funs]}
end,
dict:store({MapSrc, ViewOptions}, View2, DictBySrcAcc)
case ?getv(<<"map">>, MRFuns) of
undefined -> DictBySrcAcc;
MapSrc ->
RedSrc = ?getv(<<"reduce">>, MRFuns, null),
{ViewOptions} = ?getv(<<"options">>, MRFuns, {[]}),
View =
case dict:find({MapSrc, ViewOptions}, DictBySrcAcc) of
{ok, View0} -> View0;
error -> #view{def=MapSrc, options=ViewOptions} % create new view object
end,
View2 =
if RedSrc == null ->
View#view{map_names=[Name|View#view.map_names]};
true ->
View#view{reduce_funs=[{Name,RedSrc}|View#view.reduce_funs]}
end,
dict:store({MapSrc, ViewOptions}, View2, DictBySrcAcc)
end
end, dict:new(), RawViews),
% number the views
{Views, _N} = lists:mapfoldl(
fun({_Src, View}, N) ->
{View#view{id_num=N},N+1}
end, 0, lists:sort(dict:to_list(DictBySrc))),

set_view_sig(#group{name=Id, views=Views, def_lang=Language, design_options=DesignOptions}).
set_view_sig(#group{name=Id, lib=Lib, views=Views, def_lang=Language, design_options=DesignOptions}).

reset_group(#group{views=Views}=Group) ->
Views2 = [View#view{btree=nil} || View <- Views],
Expand Down
4 changes: 2 additions & 2 deletions src/couchdb/couch_view_updater.erl
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,12 @@ view_insert_doc_query_results(#doc{id=DocId}=Doc, [ResultKVs|RestResults], [{Vie

view_compute(Group, []) ->
{Group, []};
view_compute(#group{def_lang=DefLang, query_server=QueryServerIn}=Group, Docs) ->
view_compute(#group{def_lang=DefLang, lib=Lib, query_server=QueryServerIn}=Group, Docs) ->
{ok, QueryServer} =
case QueryServerIn of
nil -> % doc map not started
Definitions = [View#view.def || View <- Group#group.views],
couch_query_servers:start_doc_map(DefLang, Definitions);
couch_query_servers:start_doc_map(DefLang, Definitions, Lib);
_ ->
{ok, QueryServerIn}
end,
Expand Down

0 comments on commit 7665e44

Please sign in to comment.