Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

CommonJS support in map functions

git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1001895 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
commit 7665e449cdfff1e660ed2bbac3de4507cb063a18 1 parent 6c6db01
Chris Anderson authored September 27, 2010
1  share/server/loop.js
@@ -100,6 +100,7 @@ var Loop = function() {
100 100
     // "view"    : Views.handler,
101 101
     "reset"    : State.reset,
102 102
     "add_fun"  : State.addFun,
  103
+    "add_lib"  : State.addLib,
103 104
     "map_doc"  : Views.mapDoc,
104 105
     "reduce"   : Views.reduce,
105 106
     "rereduce" : Views.rereduce
7  share/server/state.js
@@ -14,6 +14,7 @@ var State = {
14 14
   reset : function(config) {
15 15
     // clear the globals and run gc
16 16
     State.funs = [];
  17
+    State.lib = null;
17 18
     State.query_config = config || {};
18 19
     init_sandbox();
19 20
     gc();
@@ -21,7 +22,11 @@ var State = {
21 22
   },
22 23
   addFun : function(newFun) {
23 24
     // Compile to a function and add it to funs array
24  
-    State.funs.push(Couch.compileFunction(newFun));
  25
+    State.funs.push(Couch.compileFunction(newFun, {views : {lib : State.lib}}));
  26
+    print("true");
  27
+  },
  28
+  addLib : function(lib) {
  29
+    State.lib = lib;
25 30
     print("true");
26 31
   }
27 32
 }
19  share/www/script/test/design_docs.js
@@ -54,7 +54,18 @@ function() {
54 54
       summate2: {map:"function (doc) {emit(doc.integer, doc.integer)};",
55 55
                 reduce:"function (keys, values) { return sum(values); };"},
56 56
       huge_src_and_results: {map: "function(doc) { if (doc._id == \"1\") { emit(\"" + makebigstring(16) + "\", null) }}",
57  
-                reduce:"function (keys, values) { return \"" + makebigstring(16) + "\"; };"}
  57
+                reduce:"function (keys, values) { return \"" + makebigstring(16) + "\"; };"},
  58
+      lib : {
  59
+        baz : "exports.baz = 'bam';",
  60
+        foo : {
  61
+          foo : "exports.foo = 'bar';",
  62
+          boom : "exports.boom = 'ok';",
  63
+          zoom : "exports.zoom = 'yeah';"
  64
+        }
  65
+      },
  66
+      commonjs : {
  67
+        map : "function(doc) { emit(null, require('views/lib/foo/boom').boom)}"
  68
+      }
58 69
     },
59 70
     shows: {
60 71
       simple: "function() {return 'ok'};",
@@ -99,10 +110,14 @@ function() {
99 110
   var vinfo = dinfo.view_index;
100 111
   TEquals(51, vinfo.disk_size);
101 112
   TEquals(false, vinfo.compact_running);
102  
-  TEquals("3f88e53b303e2342e49a66c538c30679", vinfo.signature);
  113
+  TEquals("dc3264b45b74cc6d94666e3043e07154", vinfo.signature, 'ddoc sig');
103 114
 
104 115
   db.bulkSave(makeDocs(1, numDocs + 1));
105 116
 
  117
+  // test commonjs in map functions
  118
+  resp = db.view("test/commonjs", {limit:1});
  119
+  T(resp.rows[0].value == 'ok');
  120
+
106 121
   // test that the _all_docs view returns correctly with keys
107 122
   var results = db.allDocs({startkey:"_design", endkey:"_design0"});
108 123
   T(results.rows.length == 1);
1  src/couchdb/couch_db.hrl
@@ -231,6 +231,7 @@
231 231
     def_lang,
232 232
     design_options=[],
233 233
     views,
  234
+    lib,
234 235
     id_btree=nil,
235 236
     current_seq=0,
236 237
     purge_seq=0,
9  src/couchdb/couch_query_servers.erl
@@ -16,7 +16,7 @@
16 16
 -export([start_link/0]).
17 17
 
18 18
 -export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2,code_change/3]).
19  
--export([start_doc_map/2, map_docs/2, stop_doc_map/1]).
  19
+-export([start_doc_map/3, map_docs/2, stop_doc_map/1]).
20 20
 -export([reduce/3, rereduce/3,validate_doc_update/5]).
21 21
 -export([filter_docs/5]).
22 22
 
@@ -47,8 +47,13 @@
47 47
 start_link() ->
48 48
     gen_server:start_link({local, couch_query_servers}, couch_query_servers, [], []).
49 49
 
50  
-start_doc_map(Lang, Functions) ->
  50
+start_doc_map(Lang, Functions, Lib) ->
51 51
     Proc = get_os_process(Lang),
  52
+    case Lib of
  53
+    {[]} -> ok;
  54
+    Lib ->
  55
+        true = proc_prompt(Proc, [<<"add_lib">>, Lib])
  56
+    end,
52 57
     lists:foreach(fun(FunctionSource) ->
53 58
         true = proc_prompt(Proc, [<<"add_fun">>, FunctionSource])
54 59
     end, Functions),
58  src/couchdb/couch_view_group.erl
@@ -446,7 +446,7 @@ open_temp_group(DbName, Language, DesignOptions, MapSrc, RedSrc) ->
446 446
             reduce_funs= if RedSrc==[] -> []; true -> [{<<"_temp">>, RedSrc}] end,
447 447
             options=DesignOptions},
448 448
 
449  
-        {ok, Db, set_view_sig(#group{name = <<"_temp">>, db=Db, views=[View],
  449
+        {ok, Db, set_view_sig(#group{name = <<"_temp">>,lib={[]}, db=Db, views=[View],
450 450
             def_lang=Language, design_options=DesignOptions})};
451 451
     Error ->
452 452
         Error
@@ -454,9 +454,26 @@ open_temp_group(DbName, Language, DesignOptions, MapSrc, RedSrc) ->
454 454
 
455 455
 set_view_sig(#group{
456 456
             views=Views,
  457
+            lib={[]},
457 458
             def_lang=Language,
458 459
             design_options=DesignOptions}=G) ->
459  
-    G#group{sig=couch_util:md5(term_to_binary({Views, Language, DesignOptions}))}.
  460
+    G#group{sig=couch_util:md5(term_to_binary({Views, Language, DesignOptions}))};
  461
+set_view_sig(#group{
  462
+            views=Views,
  463
+            lib=Lib,
  464
+            def_lang=Language,
  465
+            design_options=DesignOptions}=G) ->
  466
+    G#group{sig=couch_util:md5(term_to_binary({Views, Language, DesignOptions, sort_lib(Lib)}))}.
  467
+
  468
+sort_lib({Lib}) ->
  469
+    sort_lib(Lib, []).
  470
+sort_lib([], LAcc) ->
  471
+    lists:keysort(1, LAcc);
  472
+sort_lib([{LName, {LObj}}|Rest], LAcc) ->
  473
+    LSorted = sort_lib(LObj, []), % descend into nested object
  474
+    sort_lib(Rest, [{LName, LSorted}|LAcc]);
  475
+sort_lib([{LName, LCode}|Rest], LAcc) ->
  476
+    sort_lib(Rest, [{LName, LCode}|LAcc]).
460 477
 
461 478
 open_db_group(DbName, GroupId) ->
462 479
     case couch_db:open_int(DbName, []) of
@@ -505,33 +522,36 @@ design_doc_to_view_group(#doc{id=Id,body={Fields}}) ->
505 522
     Language = ?getv(<<"language">>, Fields, <<"javascript">>),
506 523
     {DesignOptions} = ?getv(<<"options">>, Fields, {[]}),
507 524
     {RawViews} = ?getv(<<"views">>, Fields, {[]}),
  525
+    Lib = ?getv(<<"lib">>, RawViews, {[]}),
508 526
     % add the views to a dictionary object, with the map source as the key
509 527
     DictBySrc =
510 528
     lists:foldl(
511 529
         fun({Name, {MRFuns}}, DictBySrcAcc) ->
512  
-            MapSrc = ?getv(<<"map">>, MRFuns),
513  
-            RedSrc = ?getv(<<"reduce">>, MRFuns, null),
514  
-            {ViewOptions} = ?getv(<<"options">>, MRFuns, {[]}),
515  
-            View =
516  
-            case dict:find({MapSrc, ViewOptions}, DictBySrcAcc) of
517  
-                {ok, View0} -> View0;
518  
-                error -> #view{def=MapSrc, options=ViewOptions} % create new view object
519  
-            end,
520  
-            View2 =
521  
-            if RedSrc == null ->
522  
-                View#view{map_names=[Name|View#view.map_names]};
523  
-            true ->
524  
-                View#view{reduce_funs=[{Name,RedSrc}|View#view.reduce_funs]}
525  
-            end,
526  
-            dict:store({MapSrc, ViewOptions}, View2, DictBySrcAcc)
  530
+            case ?getv(<<"map">>, MRFuns) of
  531
+            undefined -> DictBySrcAcc;
  532
+            MapSrc ->
  533
+                RedSrc = ?getv(<<"reduce">>, MRFuns, null),
  534
+                {ViewOptions} = ?getv(<<"options">>, MRFuns, {[]}),
  535
+                View =
  536
+                case dict:find({MapSrc, ViewOptions}, DictBySrcAcc) of
  537
+                    {ok, View0} -> View0;
  538
+                    error -> #view{def=MapSrc, options=ViewOptions} % create new view object
  539
+                end,
  540
+                View2 =
  541
+                if RedSrc == null ->
  542
+                    View#view{map_names=[Name|View#view.map_names]};
  543
+                true ->
  544
+                    View#view{reduce_funs=[{Name,RedSrc}|View#view.reduce_funs]}
  545
+                end,
  546
+                dict:store({MapSrc, ViewOptions}, View2, DictBySrcAcc)
  547
+            end
527 548
         end, dict:new(), RawViews),
528 549
     % number the views
529 550
     {Views, _N} = lists:mapfoldl(
530 551
         fun({_Src, View}, N) ->
531 552
             {View#view{id_num=N},N+1}
532 553
         end, 0, lists:sort(dict:to_list(DictBySrc))),
533  
-
534  
-    set_view_sig(#group{name=Id, views=Views, def_lang=Language, design_options=DesignOptions}).
  554
+    set_view_sig(#group{name=Id, lib=Lib, views=Views, def_lang=Language, design_options=DesignOptions}).
535 555
 
536 556
 reset_group(#group{views=Views}=Group) ->
537 557
     Views2 = [View#view{btree=nil} || View <- Views],
4  src/couchdb/couch_view_updater.erl
@@ -203,12 +203,12 @@ view_insert_doc_query_results(#doc{id=DocId}=Doc, [ResultKVs|RestResults], [{Vie
203 203
 
204 204
 view_compute(Group, []) ->
205 205
     {Group, []};
206  
-view_compute(#group{def_lang=DefLang, query_server=QueryServerIn}=Group, Docs) ->
  206
+view_compute(#group{def_lang=DefLang, lib=Lib, query_server=QueryServerIn}=Group, Docs) ->
207 207
     {ok, QueryServer} =
208 208
     case QueryServerIn of
209 209
     nil -> % doc map not started
210 210
         Definitions = [View#view.def || View <- Group#group.views],
211  
-        couch_query_servers:start_doc_map(DefLang, Definitions);
  211
+        couch_query_servers:start_doc_map(DefLang, Definitions, Lib);
212 212
     _ ->
213 213
         {ok, QueryServerIn}
214 214
     end,

0 notes on commit 7665e44

Please sign in to comment.
Something went wrong with that request. Please try again.