diff --git a/apps/emqx_connector/src/emqx_connector_template.erl b/apps/emqx_connector/src/emqx_connector_template.erl index 6f9688347..72062fc2c 100644 --- a/apps/emqx_connector/src/emqx_connector_template.erl +++ b/apps/emqx_connector/src/emqx_connector_template.erl @@ -340,8 +340,6 @@ lookup(Prop, Bindings) when is_binary(Prop) -> -spec to_string(binding()) -> unicode:chardata(). -to_string(undefined) -> - []; to_string(Bin) when is_binary(Bin) -> Bin; to_string(Num) when is_integer(Num) -> integer_to_binary(Num); to_string(Num) when is_float(Num) -> float_to_binary(Num, [{decimals, 10}, compact]); diff --git a/apps/emqx_connector/test/emqx_connector_template_SUITE.erl b/apps/emqx_connector/test/emqx_connector_template_SUITE.erl index 41f637226..b6784ea54 100644 --- a/apps/emqx_connector/test/emqx_connector_template_SUITE.erl +++ b/apps/emqx_connector/test/emqx_connector_template_SUITE.erl @@ -94,7 +94,7 @@ t_render_missing_bindings(_) -> <<"a:${a},b:${b},c:${c},d:${d.d1},e:${no.such_atom_i_swear}">> ), ?assertEqual( - {<<"a:,b:,c:,d:,e:">>, [ + {<<"a:undefined,b:undefined,c:undefined,d:undefined,e:undefined">>, [ {"no.such_atom_i_swear", undefined}, {"d.d1", undefined}, {"c", undefined}, diff --git a/apps/emqx_rule_engine/src/emqx_rule_actions.erl b/apps/emqx_rule_engine/src/emqx_rule_actions.erl index fa677ce78..7473572c8 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_actions.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_actions.erl @@ -118,10 +118,11 @@ republish( } } ) -> - Topic = unicode:characters_to_binary( - emqx_connector_template:render_strict(TopicTemplate, Selected) - ), - Payload = emqx_connector_template:render_strict(PayloadTemplate, Selected), + % NOTE: rendering missing bindings as string "undefined" + {TopicString, _Errors1} = emqx_connector_template:render(TopicTemplate, Selected), + {PayloadString, _Errors2} = emqx_connector_template:render(PayloadTemplate, Selected), + Topic = iolist_to_binary(TopicString), + Payload = iolist_to_binary(PayloadString), QoS = render_simple_var(QoSTemplate, Selected, 0), Retain = render_simple_var(RetainTemplate, Selected, false), %% 'flags' is set for message re-publishes or message related 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 fcb04f9b3..41fec48ee 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl @@ -81,6 +81,7 @@ groups() -> t_sqlselect_3, t_sqlselect_message_publish_event_keep_original_props_1, t_sqlselect_message_publish_event_keep_original_props_2, + t_sqlselect_missing_template_vars_render_as_undefined, t_sqlparse_event_1, t_sqlparse_event_2, t_sqlparse_event_3, @@ -1946,6 +1947,32 @@ t_sqlselect_as_put(_Config) -> PayloadMap2 ). +t_sqlselect_missing_template_vars_render_as_undefined(_Config) -> + SQL = <<"SELECT * FROM \"$events/client_connected\"">>, + Repub = republish_action(<<"t2">>, <<"${clientid}:${missing.var}">>), + {ok, TopicRule} = emqx_rule_engine:create_rule( + #{ + sql => SQL, + id => ?TMP_RULEID, + actions => [Repub] + } + ), + {ok, Client1} = emqtt:start_link([{clientid, <<"sub-01">>}]), + {ok, _} = emqtt:connect(Client1), + {ok, _, _} = emqtt:subscribe(Client1, <<"t2">>), + {ok, Client2} = emqtt:start_link([{clientid, <<"pub-02">>}]), + {ok, _} = emqtt:connect(Client2), + emqtt:publish(Client2, <<"foo/bar/1">>, <<>>), + receive + {publish, Msg} -> + ?assertMatch(#{topic := <<"t2">>, payload := <<"pub-02:undefined">>}, Msg) + after 2000 -> + ct:fail(wait_for_t2) + end, + emqtt:stop(Client2), + emqtt:stop(Client1), + delete_rule(TopicRule). + t_sqlparse_event_1(_Config) -> Sql = "select topic as tp "