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 2015/09/24 17:15:37 UTC
couch-mrview commit: updated refs/heads/master to aa51eb4
Repository: couchdb-couch-mrview
Updated Branches:
refs/heads/master dfa6f7eee -> aa51eb4be
Fix validation of query design documents
Jira: COUCHDB-2818
If language is "query" then map functions will be objects.
Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/commit/aa51eb4b
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/tree/aa51eb4b
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/diff/aa51eb4b
Branch: refs/heads/master
Commit: aa51eb4beefaf69d32f835df82bd7f9e738c1884
Parents: dfa6f7e
Author: Nick Vatamaniuc <va...@gmail.com>
Authored: Thu Sep 24 11:07:25 2015 -0400
Committer: Nick Vatamaniuc <va...@gmail.com>
Committed: Thu Sep 24 11:07:25 2015 -0400
----------------------------------------------------------------------
src/couch_mrview.erl | 46 ++++++++++++++----------
test/couch_mrview_ddoc_validation_tests.erl | 34 +++++++++++++++++-
2 files changed, 60 insertions(+), 20 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/aa51eb4b/src/couch_mrview.erl
----------------------------------------------------------------------
diff --git a/src/couch_mrview.erl b/src/couch_mrview.erl
index bd866a2..612e31b 100644
--- a/src/couch_mrview.erl
+++ b/src/couch_mrview.erl
@@ -52,24 +52,31 @@
%% In the most common case name is the view name and
%% value is an object that must have a "map" function,
%% and an optional "reduce" function. "map" and "reduce"
-%% values should be strings (function contents).
+%% values should be strings (function contents), except
+%% in case when langauge is <<query>> then maps must
+%% be objects.
%%
%% "lib" is a special case. The value
%% of "lib" is an object that will contain libary code
%% so it not validated.
%%
-validate_view(<<"lib">>, {_Libs})->
+validate_view(<<"lib">>, {_Libs}, _Language)->
ok;
-validate_view(VName, {Views}) ->
- case couch_util:get_value(<<"map">>, Views) of
- MapVal when is_binary(MapVal) ->
+validate_view(VName, {Views}, Language) ->
+ case {couch_util:get_value(<<"map">>, Views), Language} of
+ {{[_ | _]}, <<"query">>} ->
ok;
- undefined ->
+ {_, <<"query">>} ->
+ Err1 = <<"`map` in ", VName/binary, " for queries must be an object">>,
+ throw({invalid_design_doc,Err1});
+ {Mapval, _} when is_binary(Mapval) ->
+ ok;
+ {undefined, _} ->
Err0 = <<"View ",VName/binary, " must have a map function">>,
throw ({invalid_design_doc, Err0});
- _ ->
- Err1 = <<"`map` in ", VName/binary, " must be a string">>,
- throw({invalid_design_doc, Err1})
+ {_, _} ->
+ Err2 = <<"`map` in ", VName/binary, " must be a string">>,
+ throw({invalid_design_doc, Err2})
end,
case couch_util:get_value(<<"reduce">>, Views) of
RedVal when is_binary(RedVal) ->
@@ -77,11 +84,11 @@ validate_view(VName, {Views}) ->
undefined ->
ok; % note: unlike map, reduce function is optional
_ ->
- Err2 = <<"`reduce` in ", VName/binary, " must be a string">>,
- throw({invalid_design_doc, Err2})
+ Err3 = <<"`reduce` in ", VName/binary, " must be a string">>,
+ throw({invalid_design_doc, Err3})
end,
ok;
-validate_view(VName, _) ->
+validate_view(VName, _, _Language) ->
throw({invalid_design_doc, <<"View ", VName/binary, " must be an object">>}).
@@ -99,17 +106,17 @@ validate_view(VName, _) ->
%% - views : Validated by a special function.
%% - options : Allowed to contain non-string values.
%%
-validate_opt_object(<<"views">>, {Views})->
- [validate_view(VName, ViewObj) || {VName, ViewObj} <- Views],
+validate_opt_object(<<"views">>, {Views}, Language)->
+ [validate_view(VName, ViewObj, Language) || {VName, ViewObj} <- Views],
ok;
-validate_opt_object(<<"options">>, {_})->
+validate_opt_object(<<"options">>, {_}, _Language)->
ok;
-validate_opt_object(Section, {Fields}) ->
+validate_opt_object(Section, {Fields}, _Language) ->
[validate_opt_string(FName, FVal, Section) || {FName, FVal} <- Fields],
ok;
-validate_opt_object(_, undefined) ->
+validate_opt_object(_, undefined, _Language) ->
ok;
-validate_opt_object(FieldName, _) ->
+validate_opt_object(FieldName, _, _Language) ->
throw({invalid_design_doc, <<"`", FieldName/binary, "` is not an object">>}).
@@ -141,9 +148,10 @@ validate(DbName, DDoc) ->
<<"shows">>, <<"updates">>, <<"views">>],
StringFields = [<<"language">>, <<"validate_doc_update">>],
ArrayFields = [<<"rewrites">>],
- [validate_opt_object(F, couch_util:get_value(F, Fields)) || F <- ObjFields],
[validate_opt_string(F, couch_util:get_value(F, Fields)) || F <- StringFields],
[validate_opt_array(F, couch_util:get_value(F, Fields)) || F <- ArrayFields],
+ Language = couch_util:get_value(<<"language">>, Fields),
+ [validate_opt_object(F, couch_util:get_value(F, Fields), Language) || F <- ObjFields],
GetName = fun
(#mrview{map_names = [Name | _]}) -> Name;
(#mrview{reduce_funs = [{Name, _} | _]}) -> Name;
http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/aa51eb4b/test/couch_mrview_ddoc_validation_tests.erl
----------------------------------------------------------------------
diff --git a/test/couch_mrview_ddoc_validation_tests.erl b/test/couch_mrview_ddoc_validation_tests.erl
index 1717616..279d4e2 100644
--- a/test/couch_mrview_ddoc_validation_tests.erl
+++ b/test/couch_mrview_ddoc_validation_tests.erl
@@ -63,7 +63,9 @@ ddoc_validation_test_() ->
fun should_reject_view_without_map_function/1,
fun should_reject_view_with_non_string_map_function/1,
fun should_reject_view_with_non_string_reduce_function/1,
- fun should_accept_any_in_lib/1
+ fun should_accept_any_in_lib/1,
+ fun should_accept_map_object_for_queries/1,
+ fun should_reject_map_non_objects_for_queries/1
]
}
}
@@ -363,3 +365,33 @@ should_accept_any_in_lib(Db) ->
]}}
]}),
?_assertMatch({ok,_}, couch_db:update_doc(Db, Doc, [])).
+
+
+should_accept_map_object_for_queries(Db) ->
+ Doc = couch_doc:from_json_obj({[
+ {<<"_id">>, <<"_design/should_accept_map_objects_for_queries">>},
+ {<<"language">>, <<"query">>},
+ {<<"views">>, {[
+ {<<"view1">>, {[
+ {<<"map">>, {[
+ {<<"x">>, <<"y">>}
+ ]}}
+ ]}}
+ ]}}
+ ]}),
+ ?_assertMatch({ok,_}, couch_db:update_doc(Db, Doc, [])).
+
+
+should_reject_map_non_objects_for_queries(Db) ->
+ Doc = couch_doc:from_json_obj({[
+ {<<"_id">>, <<"_design/should_reject_map_non_objects__with_nonstr_reduce">>},
+ {<<"language">>, <<"query">>},
+ {<<"views">>, {[
+ {<<"view1">>, {[
+ {<<"map">>, <<"function(d){}">>}
+ ]}}
+ ]}}
+ ]}),
+ ?_assertThrow({bad_request,invalid_design_doc,
+ <<"`map` in view1 for queries must be an object">>},
+ couch_db:update_doc(Db, Doc, [])).