You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2013/06/29 17:18:09 UTC

[28/50] [abbrv] git commit: updated refs/heads/1843-feature-bigcouch to cba2e81

Reject design docs with compilation errors

If we know the language for a given design doc we'll attempt to compile
the map/reduce functions and reject updates that introduce code that
doesn't compile. We don't yet do the other types of functions because
those errors are more user visible.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/b474248c
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/b474248c
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/b474248c

Branch: refs/heads/1843-feature-bigcouch
Commit: b474248c6fd7f2bb5bab20225869920d87414ea7
Parents: 0861ab0
Author: Paul J. Davis <pa...@gmail.com>
Authored: Sun Mar 10 16:03:00 2013 -0500
Committer: Paul J. Davis <pa...@gmail.com>
Committed: Wed Mar 20 06:02:54 2013 -0500

----------------------------------------------------------------------
 etc/couchdb/default.ini.tpl.in             |  3 +++
 src/couch/src/couch_db.erl                 | 15 +++++++++--
 src/couch/src/couch_query_servers.erl      | 12 +++++++++
 src/couch_index/src/couch_index_server.erl | 28 +++++++++++++++++++-
 src/couch_mrview/src/couch_mrview.erl      | 35 +++++++++++++++++++++++++
 5 files changed, 90 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/b474248c/etc/couchdb/default.ini.tpl.in
----------------------------------------------------------------------
diff --git a/etc/couchdb/default.ini.tpl.in b/etc/couchdb/default.ini.tpl.in
index 02341d3..9d9465e 100644
--- a/etc/couchdb/default.ini.tpl.in
+++ b/etc/couchdb/default.ini.tpl.in
@@ -142,6 +142,9 @@ replicator_manager={couch_replicator_manager, start_link, []}
 os_daemons={couch_os_daemons, start_link, []}
 compaction_daemon={couch_compaction_daemon, start_link, []}
 
+[indexers]
+couch_mrview = true
+
 [httpd_global_handlers]
 / = {couch_httpd_misc_handlers, handle_welcome_req, <<"Welcome">>}
 favicon.ico = {couch_httpd_misc_handlers, handle_favicon_req, "%localdatadir%/www"}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/b474248c/src/couch/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index 56cb0d2..7734c7c 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -502,8 +502,11 @@ group_alike_docs([{Doc,Ref}|Rest], [Bucket|RestBuckets]) ->
        group_alike_docs(Rest, [[{Doc,Ref}]|[Bucket|RestBuckets]])
     end.
 
-validate_doc_update(#db{}=Db, #doc{id= <<"_design/",_/binary>>}, _GetDiskDocFun) ->
-    catch check_is_admin(Db);
+validate_doc_update(#db{}=Db, #doc{id= <<"_design/",_/binary>>}=Doc, _GetDiskDocFun) ->
+    case catch check_is_admin(Db) of
+        ok -> validate_ddoc(Db#db.name, Doc);
+        Error -> Error
+    end;
 validate_doc_update(#db{validate_doc_funs = undefined} = Db, Doc, Fun) ->
     ValidationFuns = load_validation_funs(Db),
     validate_doc_update(Db#db{validate_doc_funs=ValidationFuns}, Doc, Fun);
@@ -519,6 +522,14 @@ validate_doc_update(Db, Doc, GetDiskDocFun) ->
             validate_doc_update_int(Db, Doc, GetDiskDocFun)
     end.
 
+validate_ddoc(DbName, DDoc) ->
+    try
+        couch_index_server:validate(DbName, couch_doc:with_ejson_body(DDoc))
+    catch
+        throw:Error ->
+            Error
+    end.
+
 validate_doc_update_int(Db, Doc, GetDiskDocFun) ->
     DiskDoc = GetDiskDocFun(),
     JsonCtx = couch_util:json_user_ctx(Db),

http://git-wip-us.apache.org/repos/asf/couchdb/blob/b474248c/src/couch/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index d919a85..8e4130e 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -12,6 +12,7 @@
 
 -module(couch_query_servers).
 
+-export([try_compile/4]).
 -export([start_doc_map/3, map_docs/2, map_docs_raw/2, stop_doc_map/1, raw_to_ejson/1]).
 -export([reduce/3, rereduce/3,validate_doc_update/5]).
 -export([filter_docs/5]).
@@ -65,6 +66,17 @@
 46,65,9,27,108,27,101,27,110,27,103,27,116,27,104,56,9,34,59,84,0,78,84,1,102,
 65,9,27,125,56,9,84,1,206,0,0,0,0,0,0,0>>}).
 
+
+try_compile(Proc, FunctionType, FunctionName, FunctionSource) ->
+    try
+        proc_prompt(Proc, [<<"add_fun">>, FunctionSource]),
+        ok
+    catch {compilation_error, E} ->
+        Fmt = "Compilation of the ~s function in the '~s' view failed: ~s",
+        Msg = io_lib:format(Fmt, [FunctionType, FunctionName, E]),
+        throw({compilation_error, Msg})
+    end.
+
 start_doc_map(Lang, Functions, Lib) ->
     Proc = get_os_process(Lang),
     case Lib of

http://git-wip-us.apache.org/repos/asf/couchdb/blob/b474248c/src/couch_index/src/couch_index_server.erl
----------------------------------------------------------------------
diff --git a/src/couch_index/src/couch_index_server.erl b/src/couch_index/src/couch_index_server.erl
index a106f14..3d8a797 100644
--- a/src/couch_index/src/couch_index_server.erl
+++ b/src/couch_index/src/couch_index_server.erl
@@ -14,7 +14,7 @@
 -behaviour(gen_server).
 -behaviour(config_listener).
 
--export([start_link/0, get_index/4, get_index/3, get_index/2]).
+-export([start_link/0, validate/2, get_index/4, get_index/3, get_index/2]).
 -export([update_notify/1]).
 
 -export([init/1, terminate/2, code_change/3]).
@@ -35,6 +35,32 @@
 start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 
+
+validate(DbName, DDoc) ->
+    LoadModFun = fun
+        ({ModNameList, "true"}) ->
+            try
+                [list_to_existing_atom(ModNameList)]
+            catch error:badarg ->
+                []
+            end;
+        ({_ModNameList, _Enabled}) ->
+            []
+    end,
+    ValidateFun = fun
+        (ModName, ok) ->
+            try
+                ModName:validate(DbName, DDoc)
+            catch Type:Reason ->
+                {Type, Reason}
+            end;
+        (_ModName, Error) ->
+            Error
+    end,
+    EnabledIndexers = lists:flatmap(LoadModFun, config:get("indexers")),
+    lists:foldl(ValidateFun, ok, EnabledIndexers).
+
+
 get_index(Module, <<"shards/", _/binary>>=DbName, DDoc) ->
     {Pid, Ref} = spawn_monitor(fun() ->
         exit(fabric:open_doc(mem3:dbname(DbName), DDoc, []))

http://git-wip-us.apache.org/repos/asf/couchdb/blob/b474248c/src/couch_mrview/src/couch_mrview.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview/src/couch_mrview.erl b/src/couch_mrview/src/couch_mrview.erl
index 20ba6d9..29b86d7 100644
--- a/src/couch_mrview/src/couch_mrview.erl
+++ b/src/couch_mrview/src/couch_mrview.erl
@@ -12,6 +12,7 @@
 
 -module(couch_mrview).
 
+-export([validate/2]).
 -export([query_all_docs/2, query_all_docs/4]).
 -export([query_view/3, query_view/4, query_view/6]).
 -export([get_info/2]).
@@ -40,6 +41,40 @@
 }).
 
 
+validate(DbName, DDoc) ->
+    GetName = fun
+        (#mrview{map_names = [Name | _]}) -> Name;
+        (#mrview{reduce_funs = [{Name, _} | _]}) -> Name;
+        (_) -> null
+    end,
+    ValidateView = fun(Proc, #mrview{def=MapSrc, reduce_funs=Reds}=View) ->
+        couch_query_servers:try_compile(Proc, map, GetName(View), MapSrc),
+        lists:foreach(fun
+            ({_RedName, <<"_", _/binary>>}) ->
+                ok;
+            ({RedName, RedSrc}) ->
+                couch_query_servers:try_compile(Proc, reduce, RedName, RedSrc)
+        end, Reds)
+    end,
+    {ok, #mrst{language=Lang, views=Views}}
+            = couch_mrview_util:ddoc_to_mrst(DbName, DDoc),
+    try Views =/= [] andalso couch_query_servers:get_os_process(Lang) of
+        false ->
+            ok;
+        Proc ->
+            try
+                lists:foreach(fun(V) -> ValidateView(Proc, V) end, Views)
+            catch Error ->
+                Error
+            after
+                couch_query_servers:ret_os_process(Proc)
+            end
+    catch {unknown_query_language, _Lang} ->
+        %% Allow users to save ddocs written in uknown languages
+        ok
+    end.
+
+
 query_all_docs(Db, Args) ->
     query_all_docs(Db, Args, fun default_cb/2, []).