diff options
-rw-r--r-- | share/server/loop.js | 1 | ||||
-rw-r--r-- | share/server/state.js | 7 | ||||
-rw-r--r-- | share/www/script/test/design_docs.js | 19 | ||||
-rw-r--r-- | src/couchdb/couch_db.hrl | 1 | ||||
-rw-r--r-- | src/couchdb/couch_query_servers.erl | 9 | ||||
-rw-r--r-- | src/couchdb/couch_view_group.erl | 58 | ||||
-rw-r--r-- | src/couchdb/couch_view_updater.erl | 4 |
7 files changed, 73 insertions, 26 deletions
diff --git a/share/server/loop.js b/share/server/loop.js index 300151e9..d5bbd977 100644 --- a/share/server/loop.js +++ b/share/server/loop.js @@ -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 diff --git a/share/server/state.js b/share/server/state.js index 9af9e475..e6416382 100644 --- a/share/server/state.js +++ b/share/server/state.js @@ -14,6 +14,7 @@ var State = { reset : function(config) { // clear the globals and run gc State.funs = []; + State.lib = null; State.query_config = config || {}; init_sandbox(); gc(); @@ -21,7 +22,11 @@ var State = { }, 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"); } } diff --git a/share/www/script/test/design_docs.js b/share/www/script/test/design_docs.js index 8864225c..62606341 100644 --- a/share/www/script/test/design_docs.js +++ b/share/www/script/test/design_docs.js @@ -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'};", @@ -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); diff --git a/src/couchdb/couch_db.hrl b/src/couchdb/couch_db.hrl index a557ceeb..0b250ef4 100644 --- a/src/couchdb/couch_db.hrl +++ b/src/couchdb/couch_db.hrl @@ -231,6 +231,7 @@ def_lang, design_options=[], views, + lib, id_btree=nil, current_seq=0, purge_seq=0, diff --git a/src/couchdb/couch_query_servers.erl b/src/couchdb/couch_query_servers.erl index 341f7204..85470a95 100644 --- a/src/couchdb/couch_query_servers.erl +++ b/src/couchdb/couch_query_servers.erl @@ -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]). @@ -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), diff --git a/src/couchdb/couch_view_group.erl b/src/couchdb/couch_view_group.erl index f3d48d1d..86e41b89 100644 --- a/src/couchdb/couch_view_group.erl +++ b/src/couchdb/couch_view_group.erl @@ -446,7 +446,7 @@ 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 @@ -454,9 +454,26 @@ open_temp_group(DbName, Language, DesignOptions, MapSrc, RedSrc) -> 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 @@ -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], diff --git a/src/couchdb/couch_view_updater.erl b/src/couchdb/couch_view_updater.erl index d503219c..87a15f77 100644 --- a/src/couchdb/couch_view_updater.erl +++ b/src/couchdb/couch_view_updater.erl @@ -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, |