diff options
author | Garren Smith <garren.smith@gmail.com> | 2020-01-21 13:39:56 +0200 |
---|---|---|
committer | Garren Smith <garren.smith@gmail.com> | 2020-01-27 19:36:58 +0200 |
commit | a03c704a213432ba973e5dd0f02d5cc86b7fc298 (patch) | |
tree | bf5ac82fd99df1955878676d603e3650e91f023f | |
parent | ecaf215cfc55544db03ce87cf93ae7dc44451f9e (diff) | |
download | couchdb-a03c704a213432ba973e5dd0f02d5cc86b7fc298.tar.gz |
add crude mango hook and indexer setup
-rw-r--r-- | src/fabric/src/fabric2_fdb.erl | 13 | ||||
-rw-r--r-- | src/mango/src/mango_fdb.erl | 35 | ||||
-rw-r--r-- | src/mango/src/mango_indexer.erl | 101 | ||||
-rw-r--r-- | src/mango/test/exunit/mango_indexer_test.exs | 68 | ||||
-rw-r--r-- | src/mango/test/exunit/test_helper.exs | 2 |
5 files changed, 215 insertions, 4 deletions
diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl index 6abe1f6de..723f14d1c 100644 --- a/src/fabric/src/fabric2_fdb.erl +++ b/src/fabric/src/fabric2_fdb.erl @@ -697,13 +697,15 @@ write_doc(#{} = Db0, Doc, NewWinner0, OldWinner, ToUpdate, ToRemove) -> if not IsDDoc -> ok; true -> incr_stat(Db, <<"doc_design_count">>, 1) end, - incr_stat(Db, <<"doc_count">>, 1); + incr_stat(Db, <<"doc_count">>, 1), + mango_indexer:update(Db, created, Doc, not_found); recreated -> if not IsDDoc -> ok; true -> incr_stat(Db, <<"doc_design_count">>, 1) end, incr_stat(Db, <<"doc_count">>, 1), - incr_stat(Db, <<"doc_del_count">>, -1); + incr_stat(Db, <<"doc_del_count">>, -1), + mango_indexer:update(Db, created, Doc, not_found); replicate_deleted -> incr_stat(Db, <<"doc_del_count">>, 1); ignore -> @@ -713,9 +715,12 @@ write_doc(#{} = Db0, Doc, NewWinner0, OldWinner, ToUpdate, ToRemove) -> incr_stat(Db, <<"doc_design_count">>, -1) end, incr_stat(Db, <<"doc_count">>, -1), - incr_stat(Db, <<"doc_del_count">>, 1); + incr_stat(Db, <<"doc_del_count">>, 1), + OldDoc = get_doc_body(Db, DocId, OldWinner), + mango_indexer:update(Db, deleted, not_found, OldDoc); updated -> - ok + OldDoc = get_doc_body(Db, DocId, OldWinner), + mango_indexer:update(Db, updated, Doc, OldDoc) end, ok. diff --git a/src/mango/src/mango_fdb.erl b/src/mango/src/mango_fdb.erl new file mode 100644 index 000000000..c29ae8f53 --- /dev/null +++ b/src/mango/src/mango_fdb.erl @@ -0,0 +1,35 @@ +% Licensed under the Apache License, Version 2.0 (the "License"); you may not +% use this file except in compliance with the License. You may obtain a copy of +% the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +% License for the specific language governing permissions and limitations under +% the License. + + +-module(mango_fdb). + + +-export([ + write_doc/4 +]). + + +write_doc(Db, Doc, Indexes, Results) -> + lists:foreach(fun (Index) -> + MangoIdxPrefix = mango_idx_prefix(Db, Index), + ok + end, Indexes). + + +mango_idx_prefix(Db, Index) -> + #{ + db_prefix := DbPrefix + } = Db, + io:format("INDEX ~p ~n", [Index]), + ok. + diff --git a/src/mango/src/mango_indexer.erl b/src/mango/src/mango_indexer.erl new file mode 100644 index 000000000..b217ce1df --- /dev/null +++ b/src/mango/src/mango_indexer.erl @@ -0,0 +1,101 @@ +% Licensed under the Apache License, Version 2.0 (the "License"); you may not +% use this file except in compliance with the License. You may obtain a copy of +% the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +% License for the specific language governing permissions and limitations under +% the License. + + +-module(mango_indexer). + + +-export([ + update/4 +]). + + +update(Db, deleted, _, OldDoc) -> + ok; +update(Db, updated, Doc, OldDoc) -> + ok; +update(Db, created, Doc, _) -> +%% Indexes = mango_idx:list(Db), +%% Fun = fun (DDoc, Acc) -> +%% io:format("DESIGN DOC ~p ~n", [DDoc]), +%% Acc +%% end, +%% fabric2_db:fold_design_docs(Db, Fun, [], []), +%% % maybe validate indexes here +%% JSONDoc = mango_json:to_binary(couch_doc:to_json_obj(Doc, [])), +%% io:format("Update ~p ~n, ~p ~n", [Doc, JSONDoc]), +%% Results = index_doc(Indexes, JSONDoc), + ok. + + +index_doc(Indexes, Doc) -> + lists:map(fun(Idx) -> get_index_entries(Idx, Doc) end, Indexes). + + +get_index_entries({IdxProps}, Doc) -> + {Fields} = couch_util:get_value(<<"fields">>, IdxProps), + Selector = get_index_partial_filter_selector(IdxProps), + case should_index(Selector, Doc) of + false -> + []; + true -> + Values = get_index_values(Fields, Doc), + case lists:member(not_found, Values) of + true -> []; + false -> [[Values, null]] + end + end. + + +get_index_values(Fields, Doc) -> + lists:map(fun({Field, _Dir}) -> + case mango_doc:get_field(Doc, Field) of + not_found -> not_found; + bad_path -> not_found; + Value -> Value + end + end, Fields). + + +get_index_partial_filter_selector(IdxProps) -> + case couch_util:get_value(<<"partial_filter_selector">>, IdxProps, {[]}) of + {[]} -> + % this is to support legacy text indexes that had the partial_filter_selector + % set as selector + couch_util:get_value(<<"selector">>, IdxProps, {[]}); + Else -> + Else + end. + + +should_index(Selector, Doc) -> + NormSelector = mango_selector:normalize(Selector), + Matches = mango_selector:match(NormSelector, Doc), + IsDesign = case mango_doc:get_field(Doc, <<"_id">>) of + <<"_design/", _/binary>> -> true; + _ -> false + end, + Matches and not IsDesign. + + +validate_index_info(IndexInfo) -> + IdxTypes = [mango_idx_view, mango_idx_text], + Results = lists:foldl(fun(IdxType, Results0) -> + try + IdxType:validate_index_def(IndexInfo), + [valid_index | Results0] + catch _:_ -> + [invalid_index | Results0] + end + end, [], IdxTypes), + lists:member(valid_index, Results). + diff --git a/src/mango/test/exunit/mango_indexer_test.exs b/src/mango/test/exunit/mango_indexer_test.exs new file mode 100644 index 000000000..3a86ae4f3 --- /dev/null +++ b/src/mango/test/exunit/mango_indexer_test.exs @@ -0,0 +1,68 @@ +defmodule MangoIndexerTest do + use Couch.Test.ExUnit.Case + + alias Couch.Test.Utils + alias Couch.Test.Setup + alias Couch.Test.Setup.Step + + setup_all do + test_ctx = + :test_util.start_couch([:couch_log, :fabric, :couch_js, :couch_jobs]) + + on_exit(fn -> + :test_util.stop_couch(test_ctx) + end) + end + + setup do + db_name = Utils.random_name("db") + + admin_ctx = + {:user_ctx, + Utils.erlang_record(:user_ctx, "couch/include/couch_db.hrl", roles: ["_admin"])} + + {:ok, db} = :fabric2_db.create(db_name, [admin_ctx]) + + docs = create_docs() + ddoc = create_ddoc() + + {ok, _} = :fabric2_db.update_docs(db, [ddoc | docs]) + + on_exit(fn -> + :fabric2_db.delete(db_name, [admin_ctx]) + end) + + %{ + :db_name => db_name, + :db => db, + :ddoc => ddoc + } + end + + test "create design doc through _index", context do + db = context[:db] + end + +# Create 1 design doc that should be filtered out and ignored + defp create_ddocs() do + views = %{ + "_id" => "_design/bar", + "views" => %{ + "dates_sum" => %{ + "map" => """ + function(doc) { + if (doc.date) { + emit(doc.date, doc.date_val); + } + } + """ + } + } + } + :couch_doc.from_json_obj(:jiffy.decode(:jiffy.encode(views))) + end + + defp create_docs() do + [] + end +end
\ No newline at end of file diff --git a/src/mango/test/exunit/test_helper.exs b/src/mango/test/exunit/test_helper.exs new file mode 100644 index 000000000..f4ab64ff3 --- /dev/null +++ b/src/mango/test/exunit/test_helper.exs @@ -0,0 +1,2 @@ +ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter]) +ExUnit.start()
\ No newline at end of file |