From 70a490114d17b3d75cc743d8fa04c00a036f2f2c Mon Sep 17 00:00:00 2001 From: Shawn <506895667@qq.com> Date: Fri, 5 Feb 2021 10:59:58 +0800 Subject: [PATCH] fix(rulesql): proc cassandra cql with apostrophes failed --- apps/emqx_rule_engine/src/emqx_rule_utils.erl | 33 ++++++++++++++----- .../test/emqx_rule_utils_SUITE.erl | 9 +++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/apps/emqx_rule_engine/src/emqx_rule_utils.erl b/apps/emqx_rule_engine/src/emqx_rule_utils.erl index 420a80274..409095e02 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_utils.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_utils.erl @@ -27,6 +27,7 @@ , preproc_sql/2 , proc_sql/2 , proc_sql_param_str/2 + , proc_cql_param_str/2 ]). %% type converting @@ -145,8 +146,15 @@ proc_sql(Tokens, Data) -> -spec(proc_sql_param_str(tmpl_token(), map()) -> binary()). proc_sql_param_str(Tokens, Data) -> + proc_param_str(Tokens, Data, fun quote_sql/1). + +-spec(proc_cql_param_str(tmpl_token(), map()) -> binary()). +proc_cql_param_str(Tokens, Data) -> + proc_param_str(Tokens, Data, fun quote_cql/1). + +proc_param_str(Tokens, Data, Quote) -> iolist_to_binary( - proc_tmpl(Tokens, Data, #{return => rawlist, var_trans => fun quote/1})). + proc_tmpl(Tokens, Data, #{return => rawlist, var_trans => Quote})). %% backward compatibility for hot upgrading from =< e4.2.1 get_phld_var(Fun, Data) when is_function(Fun) -> @@ -238,16 +246,23 @@ 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(Str) when is_list(Str); - is_binary(Str); - is_atom(Str); - is_map(Str) -> - [$', escape_apo(bin(Str)), $']; -quote(Val) -> +quote_sql(Str) -> + quote(Str, <<"\\\\'">>). + +quote_cql(Str) -> + quote(Str, <<"''">>). + +quote(Str, ReplaceWith) when + is_list(Str); + is_binary(Str); + is_atom(Str); + is_map(Str) -> + [$', escape_apo(bin(Str), ReplaceWith), $']; +quote(Val, _) -> bin(Val). -escape_apo(Str) -> - re:replace(Str, <<"'">>, <<"\\\\'">>, [{return, binary}, global]). +escape_apo(Str, ReplaceWith) -> + re:replace(Str, <<"'">>, ReplaceWith, [{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 7c186c7fe..90b6ff86f 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_utils_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_utils_SUITE.erl @@ -125,3 +125,12 @@ t_preproc_sql4(_) -> 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)). + +t_preproc_sql5(_) -> + %% with apostrophes for cassandra + %% https://github.com/emqx/emqx/issues/4148 + 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_cql_param_str(ParamsTokens, Selected)).