diff --git a/apps/emqx_rule_engine/src/emqx_rule_index.erl b/apps/emqx_rule_engine/src/emqx_rule_index.erl index 70564f62c..16f23896a 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_index.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_index.erl @@ -114,6 +114,10 @@ matches(K, Prefix, Words, RPrefix, Acc, Tab) -> matches_rest(false, [W | Rest], RPrefix, Acc, Tab) -> matches(Rest, [W | RPrefix], Acc, Tab); +matches_rest({false, exact}, [W | Rest], RPrefix, Acc, Tab) -> + NAcc1 = matches(Rest, ['#' | RPrefix], Acc, Tab), + NAcc2 = matches(Rest, ['+' | RPrefix], NAcc1, Tab), + matches(Rest, [W | RPrefix], NAcc2, Tab); matches_rest(plus, [W | Rest], RPrefix, Acc, Tab) -> NAcc = matches(Rest, ['+' | RPrefix], Acc, Tab), matches(Rest, [W | RPrefix], NAcc, Tab); @@ -129,7 +133,12 @@ match_filter(Prefix, {Filter, _ID}, NotPrefix) -> case match_filter(Prefix, Filter) of exact -> % NOTE: exact match is `true` only if we match whole topic, not prefix - NotPrefix; + case NotPrefix of + true -> + true; + false -> + {false, exact} + end; Match -> Match end; diff --git a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl index 87563f660..2b70ea8ae 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl @@ -427,8 +427,7 @@ t_get_rules_for_topic_3(_Config) -> <<"rule-debug-2">>, <<"rule-debug-3">>, <<"rule-debug-4">>, - <<"rule-debug-5">>, - <<"rule-debug-6">> + <<"rule-debug-5">> ]), ok. diff --git a/apps/emqx_rule_engine/test/emqx_rule_index_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_index_SUITE.erl index 76ad1cda6..027d85b7e 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_index_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_index_SUITE.erl @@ -162,8 +162,26 @@ t_match_ordering(_) -> ?assertEqual(Ids1, Ids2), ?assertEqual([t_match_id1, t_match_id2, t_match_id3], Ids1). +t_match_wildcards(_) -> + Tab = new(), + emqx_rule_index:insert(<<"a/b">>, id1, <<>>, Tab), + emqx_rule_index:insert(<<"a/b/#">>, id2, <<>>, Tab), + emqx_rule_index:insert(<<"a/b/#">>, id3, <<>>, Tab), + emqx_rule_index:insert(<<"a/b/c">>, id4, <<>>, Tab), + emqx_rule_index:insert(<<"a/b/+">>, id5, <<>>, Tab), + emqx_rule_index:insert(<<"a/b/d">>, id6, <<>>, Tab), + emqx_rule_index:insert(<<"a/+/+">>, id7, <<>>, Tab), + emqx_rule_index:insert(<<"a/+/#">>, id8, <<>>, Tab), + + Rules = [id(M) || M <- emqx_rule_index:matches(<<"a/b/c">>, Tab, [])], + ?assertEqual([id2, id3, id4, id5, id7, id8], Rules), + + Rules1 = [id(M) || M <- emqx_rule_index:matches(<<"a/b">>, Tab, [])], + ?assertEqual([id1, id2, id3, id8], Rules1), + ok. + new() -> - ets:new(?MODULE, [public, ordered_set, {write_concurrency, true}]). + ets:new(?MODULE, [public, ordered_set, {read_concurrency, true}]). match(T, Tab) -> emqx_rule_index:match(T, Tab).