diff --git a/priv/default_schema.xml b/priv/default_schema.xml index 32058ca6..16fd1a43 100644 --- a/priv/default_schema.xml +++ b/priv/default_schema.xml @@ -97,6 +97,7 @@ + diff --git a/riak_test/yz_dt_test.erl b/riak_test/yz_dt_test.erl index 6608e2a5..29e1bcb1 100644 --- a/riak_test/yz_dt_test.erl +++ b/riak_test/yz_dt_test.erl @@ -8,11 +8,13 @@ -define(COUNTER, <<"counters">>). -define(SET, <<"sets">>). -define(HLL, <<"hlls">>). +-define(GSET, <<"gsets">>). -define(MAP, <<"maps">>). -define(TYPES, [{?COUNTER, counter}, {?SET, set}, {?HLL, hll}, + {?GSET, gset}, {?MAP, map}]). -import(yz_rt, [create_index/2, @@ -40,12 +42,14 @@ confirm() -> counter_update(PB), set_update(PB), hll_update(PB), + gset_update(PB), map_update(PB), %% Search the index for the types counter_search(ANode), set_search(ANode), hll_search(ANode), + gset_search(ANode), map_search(ANode), pass. @@ -69,6 +73,12 @@ set_update(PB) -> ?assertEqual(ok, riakc_pb_socket:update_type(PB, {?SET, <<"databass">>}, <<"dynamo">>, riakc_set:to_op(Dynamos))), ?assertEqual(ok, riakc_pb_socket:update_type(PB, {?SET, <<"databass">>}, <<"erlang">>, riakc_set:to_op(Erlangs))). +gset_update(PB) -> + Dynamos = lists:foldl(fun riakc_gset:add_element/2, riakc_gset:new(), [<<"Riak">>, <<"Cassandra">>, <<"Voldemort">>, <<"Couchbase">>]), + Erlangs = lists:foldl(fun riakc_gset:add_element/2, riakc_gset:new(), [<<"Riak">>, <<"Couchbase">>, <<"CouchDB">>]), + ?assertEqual(ok, riakc_pb_socket:update_type(PB, {?GSET, <<"databass">>}, <<"dynamo">>, riakc_gset:to_op(Dynamos))), + ?assertEqual(ok, riakc_pb_socket:update_type(PB, {?GSET, <<"databass">>}, <<"erlang">>, riakc_gset:to_op(Erlangs))). + set_search(Node) -> ?assertSearch(Node, ?SET, "set", "Riak", 2), ?assertSearch(Node, ?SET, "set", "CouchDB", 1), @@ -103,6 +113,12 @@ hll_search(Node) -> ?assertSearch(Node, ?HLL, "hll", "[5 TO 1000]", 0), ?assertSearch(Node, ?HLL, "hll", "[0 TO 2]", 0). +gset_search(Node) -> + ?assertSearch(Node, ?GSET, "gset", "Riak", 2), + ?assertSearch(Node, ?GSET, "gset", "CouchDB", 1), + ?assertSearch(Node, ?GSET, "gset", "Voldemort", 1), + ?assertSearch(Node, ?GSET, "gset", "C*", 2). + map_update(PB) -> Sam = lists:foldl(fun({Key, Fun}, Map) -> riakc_map:update(Key, Fun, Map) diff --git a/src/yz_dt_extractor.erl b/src/yz_dt_extractor.erl index 8b5e3bc6..495838c7 100644 --- a/src/yz_dt_extractor.erl +++ b/src/yz_dt_extractor.erl @@ -76,7 +76,7 @@ }). -type state() :: #state{}. -type field_path_name() :: undefined | {binary() | undefined, binary()}. --type datatype() :: map | set | counter | register | flag | hll. +-type datatype() :: map | gset | set | counter | register | flag | hll. -spec extract(binary()) -> fields() | {error, any()}. extract(Value) -> extract(Value, ?NO_OPTIONS). @@ -103,6 +103,9 @@ extract_fields(Name0, map, Pairs, #state{field_separator=Sep}=State) -> extract_fields(Name0, set, Entries, #state{field_separator=Sep}=State) -> Name = field_name(Name0, set, Sep), lists:foldl(extract_set(Name), State, Entries); +extract_fields(Name0, gset, Entries, #state{field_separator=Sep}=State) -> + Name = field_name(Name0, gset, Sep), + lists:foldl(extract_gset(Name), State, Entries); extract_fields(Name, counter, Value, #state{fields=Fields, field_separator=Sep}=State) -> FieldName = field_name(Name, counter, Sep), State#state{fields=[{FieldName, ?INT_TO_BIN(Value)}|Fields]}; @@ -136,6 +139,12 @@ extract_set(Name) -> Acc#state{fields=[{Name, Elem}|Fields]} end. +-spec extract_gset(binary()) -> fun((binary(), state()) -> state()). +extract_gset(Name) -> + fun(Elem, #state{fields=Fields}=Acc) -> + Acc#state{fields=[{Name, Elem}|Fields]} + end. + -spec extract_map(field_path_name()) -> fun(({{binary(), module()}, term()}, state()) -> state()). extract_map(Prefix) -> fun({{FieldName, Mod}, Value}, Acc) -> diff --git a/src/yz_extractor.erl b/src/yz_extractor.erl index 8be47940..4e8b986b 100644 --- a/src/yz_extractor.erl +++ b/src/yz_extractor.erl @@ -31,6 +31,7 @@ -define(DEFAULT_MAP, [{default, yz_noop_extractor}, {"application/json",yz_json_extractor}, {"application/riak_counter", yz_dt_extractor}, + {"application/riak_gset", yz_dt_extractor}, {"application/riak_hll", yz_dt_extractor}, {"application/riak_map", yz_dt_extractor}, {"application/riak_set", yz_dt_extractor}, diff --git a/test/yz_dt_extractor_tests.erl b/test/yz_dt_extractor_tests.erl index 5e11552f..93f39998 100644 --- a/test/yz_dt_extractor_tests.erl +++ b/test/yz_dt_extractor_tests.erl @@ -22,12 +22,21 @@ set_test() -> valid_extraction(Result, Expect). + %% Test hll extract hll_test() -> HllBin = binary_crdt(hll), Result = yz_dt_extractor:extract(HllBin), Expect = [{<<"hll">>, <<"9">>}], + valid_extraction(Result, Expect). +%% Test gset extract +gset_test() -> + SetBin = binary_crdt(gset), + Result = yz_dt_extractor:extract(SetBin), + Expect = [{<<"gset">>, <<"Dublin">>}, + {<<"gset">>, <<"Tel Aviv">>}, + {<<"gset">>, <<"Stoke-on-Trent">>}], valid_extraction(Result, Expect). %% Test map extract @@ -88,6 +97,11 @@ raw_type(set) -> element(2,?SET_TYPE:update({add_all, [<<"Riak">>, <<"Cassandra">>, <<"Voldemort">>]}, <<0>>, ?SET_TYPE:new())) ); +raw_type(gset) -> + ?GSET_TYPE( + element(2,?GSET_TYPE:update({add_all, [<<"Dublin">>, <<"Tel Aviv">>, <<"Stoke-on-Trent">>]}, + nil, ?GSET_TYPE:new())) + ); raw_type(counter) -> ?COUNTER_TYPE( element(2,?COUNTER_TYPE:update({increment, 10}, <<0>>, ?COUNTER_TYPE:new())));