summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgarren smith <garren.smith@gmail.com>2021-03-30 14:49:09 +0200
committergarren smith <garren.smith@gmail.com>2021-04-06 10:56:32 +0200
commit8736b9846f1b6d388977a4c1a34033781c26a883 (patch)
treef86dcf5da9b6a370ccbfda434adde453c6a24882
parentf6f81be96076192675c5fb989ba9b37bb3db9980 (diff)
downloadcouchdb-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.exs2
-rw-r--r--src/couch_eval/src/couch_eval.erl51
-rw-r--r--src/couch_js/src/couch_js.erl17
-rw-r--r--src/couch_mrview/src/couch_mrview.erl23
-rw-r--r--src/couch_replicator/test/eunit/couch_replicator_test_helper.erl2
-rw-r--r--src/fabric/src/fabric2_db.erl2
-rw-r--r--src/fabric/test/fabric2_doc_crud_tests.erl2
-rw-r--r--src/mango/src/mango_eval.erl17
-rw-r--r--test/elixir/lib/setup/common.ex4
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