diff options
author | garren smith <garren.smith@gmail.com> | 2021-03-30 14:49:09 +0200 |
---|---|---|
committer | garren smith <garren.smith@gmail.com> | 2021-04-06 10:56:32 +0200 |
commit | 8736b9846f1b6d388977a4c1a34033781c26a883 (patch) | |
tree | f86dcf5da9b6a370ccbfda434adde453c6a24882 | |
parent | f6f81be96076192675c5fb989ba9b37bb3db9980 (diff) | |
download | couchdb-8736b9846f1b6d388977a4c1a34033781c26a883.tar.gz |
Validate ddoc uses couch_eval
Change the validate ddoc check to use couch_eval.
Also add in some extra functions in couch_eval so that the try_compile
will work.
-rw-r--r-- | src/couch/test/exunit/fabric_test.exs | 2 | ||||
-rw-r--r-- | src/couch_eval/src/couch_eval.erl | 51 | ||||
-rw-r--r-- | src/couch_js/src/couch_js.erl | 17 | ||||
-rw-r--r-- | src/couch_mrview/src/couch_mrview.erl | 23 | ||||
-rw-r--r-- | src/couch_replicator/test/eunit/couch_replicator_test_helper.erl | 2 | ||||
-rw-r--r-- | src/fabric/src/fabric2_db.erl | 2 | ||||
-rw-r--r-- | src/fabric/test/fabric2_doc_crud_tests.erl | 2 | ||||
-rw-r--r-- | src/mango/src/mango_eval.erl | 17 | ||||
-rw-r--r-- | test/elixir/lib/setup/common.ex | 4 |
9 files changed, 94 insertions, 26 deletions
diff --git a/src/couch/test/exunit/fabric_test.exs b/src/couch/test/exunit/fabric_test.exs index bdb84e9a2..4cbd26b68 100644 --- a/src/couch/test/exunit/fabric_test.exs +++ b/src/couch/test/exunit/fabric_test.exs @@ -15,7 +15,7 @@ defmodule Couch.Test.Fabric do def with_db(context, setup) do setup = setup - |> Setup.Common.with_db() + |> Setup.Common.with_db([:couch_js]) |> Setup.run() context = diff --git a/src/couch_eval/src/couch_eval.erl b/src/couch_eval/src/couch_eval.erl index 3541a5b94..a6e59657b 100644 --- a/src/couch_eval/src/couch_eval.erl +++ b/src/couch_eval/src/couch_eval.erl @@ -17,7 +17,9 @@ -export([ acquire_map_context/6, release_map_context/1, - map_docs/2 + map_docs/2, + with_context/2, + try_compile/4 ]). @@ -35,6 +37,10 @@ -type result() :: {doc_id(), [[{any(), any()}]]}. -type api_mod() :: atom(). -type context() :: {api_mod(), any()}. +-type function_type() :: binary(). +-type function_name() :: binary(). +-type function_src() :: binary(). +-type error(_Error) :: no_return(). -type context_opts() :: #{ db_name := db_name(), @@ -46,10 +52,17 @@ api_mod => api_mod() }. +-type with_context_opts() :: #{ + language := language() +}. + -callback acquire_map_context(context_opts()) -> {ok, any()} | {error, any()}. -callback release_map_context(context()) -> ok | {error, any()}. -callback map_docs(context(), [doc()]) -> {ok, [result()]} | {error, any()}. +-callback acquire_context() -> {ok, any()} | {error, any()}. +-callback release_context(context()) -> ok | {error, any()}. +-callback try_compile(context(), function_type(), function_name(), function_src()) -> ok. -spec acquire_map_context( @@ -59,7 +72,10 @@ sig(), lib(), map_funs() - ) -> {ok, context()} | {error, any()}. + ) -> + {ok, context()} + | error({invalid_eval_api_mod, Language :: binary()}) + | error({unknown_eval_api_language, Language :: binary()}). acquire_map_context(DbName, DDocId, Language, Sig, Lib, MapFuns) -> ApiMod = get_api_mod(Language), CtxOpts = #{ @@ -87,6 +103,37 @@ map_docs({ApiMod, Ctx}, Docs) -> ApiMod:map_docs(Ctx, Docs). +-spec with_context(with_context_opts(), function()) -> + any() + | error({invalid_eval_api_mod, Language :: binary()}) + | error({unknown_eval_api_language, Language :: binary()}). +with_context(#{language := Language}, Fun) -> + {ok, Ctx} = acquire_context(Language), + try + Fun(Ctx) + after + release_context(Ctx) + end. + + +-spec try_compile(context(), function_type(), function_name(), function_src()) -> ok. +try_compile({ApiMod, Ctx}, FuncType, FuncName, FuncSrc) -> + ApiMod:try_compile(Ctx, FuncType, FuncName, FuncSrc). + + +acquire_context(Language) -> + ApiMod = get_api_mod(Language), + {ok, Ctx} = ApiMod:acquire_context(), + {ok, {ApiMod, Ctx}}. + + +release_context(nil) -> + ok; + +release_context({ApiMod, Ctx}) -> + ApiMod:release_context(Ctx). + + get_api_mod(Language) when is_binary(Language) -> try LangStr = binary_to_list(Language), diff --git a/src/couch_js/src/couch_js.erl b/src/couch_js/src/couch_js.erl index 1bc0f1927..a9c974ef8 100644 --- a/src/couch_js/src/couch_js.erl +++ b/src/couch_js/src/couch_js.erl @@ -18,7 +18,10 @@ -export([ acquire_map_context/1, release_map_context/1, - map_docs/2 + map_docs/2, + acquire_context/0, + release_context/1, + try_compile/4 ]). @@ -49,3 +52,15 @@ map_docs(Proc, Docs) -> end, Results), {Doc#doc.id, Tupled} end, Docs)}. + +acquire_context() -> + Ctx = couch_query_servers:get_os_process(?JS), + {ok, Ctx}. + + +release_context(Proc) -> + couch_query_servers:ret_os_process(Proc). + + +try_compile(Proc, FunctionType, FunName, FunSrc) -> + couch_query_servers:try_compile(Proc, FunctionType, FunName, FunSrc). diff --git a/src/couch_mrview/src/couch_mrview.erl b/src/couch_mrview/src/couch_mrview.erl index 880dfa725..32f823d5b 100644 --- a/src/couch_mrview/src/couch_mrview.erl +++ b/src/couch_mrview/src/couch_mrview.erl @@ -188,8 +188,8 @@ validate(DbName, _IsDbPartitioned, DDoc) -> (#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), + ValidateView = fun(Ctx, #mrview{def=MapSrc, reduce_funs=Reds}=View) -> + couch_eval:try_compile(Ctx, map, GetName(View), MapSrc), lists:foreach(fun ({_RedName, <<"_sum", _/binary>>}) -> ok; @@ -203,7 +203,7 @@ validate(DbName, _IsDbPartitioned, DDoc) -> Msg = ["`", Bad, "` is not a supported reduce function."], throw({invalid_design_doc, Msg}); ({RedName, RedSrc}) -> - couch_query_servers:try_compile(Proc, reduce, RedName, RedSrc) + couch_eval:try_compile(Ctx, reduce, RedName, RedSrc) end, Reds) end, {ok, #mrst{ @@ -211,19 +211,10 @@ validate(DbName, _IsDbPartitioned, DDoc) -> 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) - after - couch_query_servers:ret_os_process(Proc) - end - catch {unknown_query_language, _Lang} -> - %% Allow users to save ddocs written in unknown languages - ok - end. + Views =/= [] andalso couch_eval:with_context(#{language => Lang}, fun (Ctx) -> + lists:foreach(fun(V) -> ValidateView(Ctx, V) end, Views) + end), + ok. query_all_docs(Db, Args) -> diff --git a/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl b/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl index 2ac447eb3..39717dd0d 100644 --- a/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl +++ b/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl @@ -56,7 +56,7 @@ start_couch() -> - Ctx = test_util:start_couch([fabric, chttpd, couch_replicator]), + Ctx = test_util:start_couch([fabric, chttpd, couch_replicator, couch_js]), Hashed = couch_passwords:hash_admin_password(?PASSWORD), ok = config:set("admins", ?USERNAME, ?b2l(Hashed), _Persist = false), Ctx. diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl index 6d8bb72e9..4e0a9fdfa 100644 --- a/src/fabric/src/fabric2_db.erl +++ b/src/fabric/src/fabric2_db.erl @@ -2154,7 +2154,7 @@ validate_doc_update(Db, Doc, PrevDoc) -> validate_ddoc(Db, DDoc) -> try - ok = couch_index_server:validate(Db, couch_doc:with_ejson_body(DDoc)) + ok = couch_mrview:validate(Db, couch_doc:with_ejson_body(DDoc)) catch throw:{invalid_design_doc, Reason} -> throw({bad_request, invalid_design_doc, Reason}); diff --git a/src/fabric/test/fabric2_doc_crud_tests.erl b/src/fabric/test/fabric2_doc_crud_tests.erl index 7a24b7d52..bc78887d2 100644 --- a/src/fabric/test/fabric2_doc_crud_tests.erl +++ b/src/fabric/test/fabric2_doc_crud_tests.erl @@ -75,7 +75,7 @@ doc_crud_test_() -> setup() -> - Ctx = test_util:start_couch([fabric]), + Ctx = test_util:start_couch([fabric, couch_js]), {ok, Db} = fabric2_db:create(?tempdb(), [{user_ctx, ?ADMIN_USER}]), {Db, Ctx}. diff --git a/src/mango/src/mango_eval.erl b/src/mango/src/mango_eval.erl index 59d784b49..7fd81df77 100644 --- a/src/mango/src/mango_eval.erl +++ b/src/mango/src/mango_eval.erl @@ -18,7 +18,10 @@ -export([ acquire_map_context/1, release_map_context/1, - map_docs/2 + map_docs/2, + acquire_context/0, + release_context/1, + try_compile/4 ]). @@ -60,6 +63,18 @@ map_docs(Indexes, Docs) -> end, Docs)}. +acquire_context() -> + {ok, no_ctx}. + + +release_context(_) -> + ok. + + +try_compile(_Ctx, _FunType, _IndexName, IndexInfo) -> + mango_idx_view:validate_index_def(IndexInfo). + + index_doc(Indexes, Doc) -> lists:map(fun(Idx) -> {IdxDef} = mango_idx:def(Idx), diff --git a/test/elixir/lib/setup/common.ex b/test/elixir/lib/setup/common.ex index e81f109c9..65cd04fe3 100644 --- a/test/elixir/lib/setup/common.ex +++ b/test/elixir/lib/setup/common.ex @@ -19,9 +19,9 @@ defmodule Couch.Test.Setup.Common do |> Step.Create.DB.new(:db) end - def with_db(setup) do + def with_db(setup, apps \\ []) do setup - |> Step.Start.new(:start, extra_apps: [:fabric]) + |> Step.Start.new(:start, extra_apps: [:fabric] ++ apps) |> Step.Create.DB.new(:db) end end
\ No newline at end of file |