You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by jc...@apache.org on 2009/02/01 23:21:09 UTC

svn commit: r739866 - in /couchdb/trunk: share/www/script/couch.js share/www/script/couch_tests.js src/couchdb/couch_db.hrl src/couchdb/couch_httpd_view.erl src/couchdb/couch_view.erl src/couchdb/couch_view_group.erl src/couchdb/couch_view_updater.erl

Author: jchris
Date: Sun Feb  1 22:21:09 2009
New Revision: 739866

URL: http://svn.apache.org/viewvc?rev=739866&view=rev
Log:
Added options member to design docs. Currently the only option is include_designs (views can now run over design docs as well if they need to), the default is false, which is the current behavior. Thanks davisp for the original patch. Closes COUCHDB-156

Modified:
    couchdb/trunk/share/www/script/couch.js
    couchdb/trunk/share/www/script/couch_tests.js
    couchdb/trunk/src/couchdb/couch_db.hrl
    couchdb/trunk/src/couchdb/couch_httpd_view.erl
    couchdb/trunk/src/couchdb/couch_view.erl
    couchdb/trunk/src/couchdb/couch_view_group.erl
    couchdb/trunk/src/couchdb/couch_view_updater.erl

Modified: couchdb/trunk/share/www/script/couch.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/couch.js?rev=739866&r1=739865&r2=739866&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/couch.js [utf-8] (original)
+++ couchdb/trunk/share/www/script/couch.js [utf-8] Sun Feb  1 22:21:09 2009
@@ -129,6 +129,10 @@
         reduceFun = reduceFun.toSource ? reduceFun.toSource() : "(" + reduceFun.toString() + ")";
       body.reduce = reduceFun;
     }
+    if (options && options.options != undefined) {
+        body.options = options.options;
+        delete options.options;
+    }
     this.last_req = this.request("POST", this.uri + "_temp_view" + encodeOptions(options), {
       headers: {"Content-Type": "application/json"},
       body: JSON.stringify(body)

Modified: couchdb/trunk/share/www/script/couch_tests.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/couch_tests.js?rev=739866&r1=739865&r2=739866&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/couch_tests.js [utf-8] (original)
+++ couchdb/trunk/share/www/script/couch_tests.js [utf-8] Sun Feb  1 22:21:09 2009
@@ -773,6 +773,58 @@
     }
   },
 
+  design_options: function(debug) {
+    var db = new CouchDB("test_suite_db");
+    db.deleteDb();
+    db.createDb();
+    if (debug) debugger;
+
+    //// test the includes_design option
+    var map = "function (doc) {emit(null, doc._id);}";
+
+    // we need a design doc even to test temp views with it
+    var designDoc = {
+      _id:"_design/fu",
+      language: "javascript",
+      options: {
+        include_design: true        
+      },
+      views: {
+        data: {"map": map}
+      }
+    };
+    T(db.save(designDoc).ok);
+
+    // should work for temp views
+    var rows = db.query(map, null, {options:{include_design: true}}).rows;
+    T(rows.length == 1);
+    T(rows[0].value == "_design/fu");
+
+    rows = db.query(map).rows;
+    T(rows.length == 0);
+
+    // when true, should include design docs in views
+    rows = db.view("fu/data").rows;
+    T(rows.length == 1);
+    T(rows[0].value == "_design/fu");
+
+    // when false, should not
+    designDoc.options.include_design = false;
+    delete designDoc._rev;
+    designDoc._id = "_design/bingo";
+    T(db.save(designDoc).ok);
+    rows = db.view("bingo/data").rows;
+    T(rows.length == 0);
+
+    // should default to false
+    delete designDoc.options;
+    delete designDoc._rev;
+    designDoc._id = "_design/bango";
+    T(db.save(designDoc).ok);
+    rows = db.view("bango/data").rows;
+    T(rows.length == 0);
+  },
+
   multiple_rows: function(debug) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();

Modified: couchdb/trunk/src/couchdb/couch_db.hrl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_db.hrl?rev=739866&r1=739865&r2=739866&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_db.hrl (original)
+++ couchdb/trunk/src/couchdb/couch_db.hrl Sun Feb  1 22:21:09 2009
@@ -174,6 +174,7 @@
     fd=nil,
     name,
     def_lang,
+    design_options=[],
     views,
     id_btree=nil,
     current_seq=0,

Modified: couchdb/trunk/src/couchdb/couch_httpd_view.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_view.erl?rev=739866&r1=739865&r2=739866&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd_view.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd_view.erl Sun Feb  1 22:21:09 2009
@@ -68,15 +68,17 @@
     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;
 

Modified: couchdb/trunk/src/couchdb/couch_view.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_view.erl?rev=739866&r1=739865&r2=739866&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_view.erl (original)
+++ couchdb/trunk/src/couchdb/couch_view.erl Sun Feb  1 22:21:09 2009
@@ -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 @@
             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+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 @@
     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 @@
             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;

Modified: couchdb/trunk/src/couchdb/couch_view_group.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_view_group.erl?rev=739866&r1=739865&r2=739866&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_view_group.erl (original)
+++ couchdb/trunk/src/couchdb/couch_view_group.erl Sun Feb  1 22:21:09 2009
@@ -262,7 +262,7 @@
         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 @@
             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 @@
 % 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 @@
             {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) ->

Modified: couchdb/trunk/src/couchdb/couch_view_updater.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_view_updater.erl?rev=739866&r1=739865&r2=739866&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_view_updater.erl (original)
+++ couchdb/trunk/src/couchdb/couch_view_updater.erl Sun Feb  1 22:21:09 2009
@@ -90,43 +90,52 @@
             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, []};