diff --git a/apps/emqx_rule_engine/src/emqx_rule_utils.erl b/apps/emqx_rule_engine/src/emqx_rule_utils.erl index b4fa0e6fc..420a80274 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_utils.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_utils.erl @@ -238,12 +238,16 @@ sql_data(Bool) when is_boolean(Bool) -> Bool; sql_data(Atom) when is_atom(Atom) -> atom_to_binary(Atom, utf8); sql_data(Map) when is_map(Map) -> emqx_json:encode(Map). -quote(List) when is_list(List) -> [$', List, $']; -quote(Bin) when is_binary(Bin) -> [$', Bin, $']; -quote(Num) when is_number(Num) -> bin(Num); -quote(Bool) when is_boolean(Bool) -> bin(Bool); -quote(Atom) when is_atom(Atom) -> [$', atom_to_binary(Atom, utf8), $']; -quote(Map) when is_map(Map) -> [$', emqx_json:encode(Map), $']. +quote(Str) when is_list(Str); + is_binary(Str); + is_atom(Str); + is_map(Str) -> + [$', escape_apo(bin(Str)), $']; +quote(Val) -> + bin(Val). + +escape_apo(Str) -> + re:replace(Str, <<"'">>, <<"\\\\'">>, [{return, binary}, global]). str(Bin) when is_binary(Bin) -> binary_to_list(Bin); str(Num) when is_number(Num) -> number_to_list(Num); diff --git a/apps/emqx_rule_engine/test/emqx_rule_utils_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_utils_SUITE.erl index 006320ad8..7c186c7fe 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_utils_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_utils_SUITE.erl @@ -116,3 +116,12 @@ t_preproc_sql3(_) -> ParamsTokens = emqx_rule_utils:preproc_tmpl(<<"a:${a},b:${b},c:${c},d:${d}">>), ?assertEqual(<<"a:'1',b:1,c:1.0,d:'{\"d1\":\"hi\"}'">>, emqx_rule_utils:proc_sql_param_str(ParamsTokens, Selected)). + +t_preproc_sql4(_) -> + %% with apostrophes + %% https://github.com/emqx/emqx/issues/4135 + Selected = #{a => <<"1''2">>, b => 1, c => 1.0, + d => #{d1 => <<"someone's phone">>}}, + ParamsTokens = emqx_rule_utils:preproc_tmpl(<<"a:${a},b:${b},c:${c},d:${d}">>), + ?assertEqual(<<"a:'1\\'\\'2',b:1,c:1.0,d:'{\"d1\":\"someone\\'s phone\"}'">>, + emqx_rule_utils:proc_sql_param_str(ParamsTokens, Selected)).