fix: sql compare to undefined values

This commit is contained in:
Shawn 2022-08-16 21:32:24 +08:00
parent bffff65df5
commit 4055b20259
2 changed files with 216 additions and 6 deletions

View File

@ -216,10 +216,8 @@ match_conditions({}, _Data) ->
true. true.
%% comparing numbers against strings %% comparing numbers against strings
compare(Op, undefined, undefined) -> compare(Op, L, R) when L == undefined; R == undefined ->
do_compare(Op, undefined, undefined); do_compare(Op, L, R);
compare(_Op, L, R) when L == undefined; R == undefined ->
false;
compare(Op, L, R) when is_number(L), is_binary(R) -> compare(Op, L, R) when is_number(L), is_binary(R) ->
do_compare(Op, L, number(R)); do_compare(Op, L, number(R));
compare(Op, L, R) when is_binary(L), is_number(R) -> compare(Op, L, R) when is_binary(L), is_number(R) ->
@ -232,10 +230,14 @@ compare(Op, L, R) ->
do_compare(Op, L, R). do_compare(Op, L, R).
do_compare('=', L, R) -> L == R; do_compare('=', L, R) -> L == R;
do_compare('>', L, R) when L == undefined; R == undefined -> false;
do_compare('>', L, R) -> L > R; do_compare('>', L, R) -> L > R;
do_compare('<', L, R) when L == undefined; R == undefined -> false;
do_compare('<', L, R) -> L < R; do_compare('<', L, R) -> L < R;
do_compare('<=', L, R) -> L =< R; do_compare('<=', L, R) ->
do_compare('>=', L, R) -> L >= R; do_compare('=', L, R) orelse do_compare('<', L, R);
do_compare('>=', L, R) ->
do_compare('=', L, R) orelse do_compare('>', L, R);
do_compare('<>', L, R) -> L /= R; do_compare('<>', L, R) -> L /= R;
do_compare('!=', L, R) -> L /= R; do_compare('!=', L, R) -> L /= R;
do_compare('=~', T, F) -> emqx_topic:match(T, F). do_compare('=~', T, F) -> emqx_topic:match(T, F).

View File

@ -126,6 +126,10 @@ groups() ->
t_sqlparse_array_range_1, t_sqlparse_array_range_1,
t_sqlparse_array_range_2, t_sqlparse_array_range_2,
t_sqlparse_true_false, t_sqlparse_true_false,
t_sqlparse_compare_null_null,
t_sqlparse_compare_null_notnull,
t_sqlparse_compare_notnull_null,
t_sqlparse_compare,
t_sqlparse_new_map, t_sqlparse_new_map,
t_sqlparse_invalid_json t_sqlparse_invalid_json
]}, ]},
@ -2486,6 +2490,210 @@ t_sqlparse_true_false(_Config) ->
<<"c">> := [true] <<"c">> := [true]
}, Res00). }, Res00).
-define(TEST_SQL(SQL),
emqx_rule_sqltester:test(
#{<<"rawsql">> => SQL,
<<"ctx">> => #{<<"payload">> => <<"">>,
<<"topic">> => <<"t/a">>}})).
t_sqlparse_compare_null_null(_Config) ->
%% test undefined == undefined
Sql00 = "select "
" a = b as c "
"from \"t/#\" ",
{ok, Res00} = ?TEST_SQL(Sql00),
?assertMatch(#{<<"c">> := true
}, Res00),
%% test undefined != undefined
Sql01 = "select "
" a != b as c "
"from \"t/#\" ",
{ok, Res01} = ?TEST_SQL(Sql01),
?assertMatch(#{<<"c">> := false
}, Res01),
%% test undefined > undefined
Sql02 = "select "
" a > b as c "
"from \"t/#\" ",
{ok, Res02} = ?TEST_SQL(Sql02),
?assertMatch(#{<<"c">> := false
}, Res02),
%% test undefined < undefined
Sql03 = "select "
" a < b as c "
"from \"t/#\" ",
{ok, Res03} = ?TEST_SQL(Sql03),
?assertMatch(#{<<"c">> := false
}, Res03),
%% test undefined <= undefined
Sql04 = "select "
" a <= b as c "
"from \"t/#\" ",
{ok, Res04} = ?TEST_SQL(Sql04),
?assertMatch(#{<<"c">> := true
}, Res04),
%% test undefined >= undefined
Sql05 = "select "
" a >= b as c "
"from \"t/#\" ",
{ok, Res05} = ?TEST_SQL(Sql05),
?assertMatch(#{<<"c">> := true
}, Res05).
t_sqlparse_compare_null_notnull(_Config) ->
%% test undefined == b
Sql00 = "select "
" 'b' as b, a = b as c "
"from \"t/#\" ",
{ok, Res00} = ?TEST_SQL(Sql00),
?assertMatch(#{<<"c">> := false
}, Res00),
%% test undefined != b
Sql01 = "select "
" 'b' as b, a != b as c "
"from \"t/#\" ",
{ok, Res01} = ?TEST_SQL(Sql01),
?assertMatch(#{<<"c">> := true
}, Res01),
%% test undefined > b
Sql02 = "select "
" 'b' as b, a > b as c "
"from \"t/#\" ",
{ok, Res02} = ?TEST_SQL(Sql02),
?assertMatch(#{<<"c">> := false
}, Res02),
%% test undefined < b
Sql03 = "select "
" 'b' as b, a < b as c "
"from \"t/#\" ",
{ok, Res03} = ?TEST_SQL(Sql03),
?assertMatch(#{<<"c">> := false
}, Res03),
%% test undefined <= b
Sql04 = "select "
" 'b' as b, a <= b as c "
"from \"t/#\" ",
{ok, Res04} = ?TEST_SQL(Sql04),
?assertMatch(#{<<"c">> := false
}, Res04),
%% test undefined >= b
Sql05 = "select "
" 'b' as b, a >= b as c "
"from \"t/#\" ",
{ok, Res05} = ?TEST_SQL(Sql05),
?assertMatch(#{<<"c">> := false
}, Res05).
t_sqlparse_compare_notnull_null(_Config) ->
%% test 'a' == undefined
Sql00 = "select "
" 'a' as a, a = b as c "
"from \"t/#\" ",
{ok, Res00} = ?TEST_SQL(Sql00),
?assertMatch(#{<<"c">> := false
}, Res00),
%% test 'a' != undefined
Sql01 = "select "
" 'a' as a, a != b as c "
"from \"t/#\" ",
{ok, Res01} = ?TEST_SQL(Sql01),
?assertMatch(#{<<"c">> := true
}, Res01),
%% test 'a' > undefined
Sql02 = "select "
" 'a' as a, a > b as c "
"from \"t/#\" ",
{ok, Res02} = ?TEST_SQL(Sql02),
?assertMatch(#{<<"c">> := false
}, Res02),
%% test 'a' < undefined
Sql03 = "select "
" 'a' as a, a < b as c "
"from \"t/#\" ",
{ok, Res03} = ?TEST_SQL(Sql03),
?assertMatch(#{<<"c">> := false
}, Res03),
%% test 'a' <= undefined
Sql04 = "select "
" 'a' as a, a <= b as c "
"from \"t/#\" ",
{ok, Res04} = ?TEST_SQL(Sql04),
?assertMatch(#{<<"c">> := false
}, Res04),
%% test 'a' >= undefined
Sql05 = "select "
" 'a' as a, a >= b as c "
"from \"t/#\" ",
{ok, Res05} = ?TEST_SQL(Sql05),
?assertMatch(#{<<"c">> := false
}, Res05).
t_sqlparse_compare(_Config) ->
Sql00 = "select "
" 'a' as a, 'a' as b, a = b as c "
"from \"t/#\" ",
{ok, Res00} = ?TEST_SQL(Sql00),
?assertMatch(#{<<"c">> := true
}, Res00),
Sql01 = "select "
" is_null(a) as c "
"from \"t/#\" ",
{ok, Res01} = ?TEST_SQL(Sql01),
?assertMatch(#{<<"c">> := true
}, Res01),
Sql02 = "select "
" 1 as a, 2 as b, a < b as c "
"from \"t/#\" ",
{ok, Res02} = ?TEST_SQL(Sql02),
?assertMatch(#{<<"c">> := true
}, Res02),
Sql03 = "select "
" 1 as a, 2 as b, a > b as c "
"from \"t/#\" ",
{ok, Res03} = ?TEST_SQL(Sql03),
?assertMatch(#{<<"c">> := false
}, Res03),
Sql04 = "select "
" 1 as a, 2 as b, a = b as c "
"from \"t/#\" ",
{ok, Res04} = ?TEST_SQL(Sql04),
?assertMatch(#{<<"c">> := false
}, Res04),
%% test 'a' >= undefined
Sql05 = "select "
" 1 as a, 2 as b, a >= b as c "
"from \"t/#\" ",
{ok, Res05} = ?TEST_SQL(Sql05),
?assertMatch(#{<<"c">> := false
}, Res05),
%% test 'a' >= undefined
Sql06 = "select "
" 1 as a, 2 as b, a <= b as c "
"from \"t/#\" ",
{ok, Res06} = ?TEST_SQL(Sql06),
?assertMatch(#{<<"c">> := true
}, Res06).
t_sqlparse_new_map(_Config) -> t_sqlparse_new_map(_Config) ->
%% construct a range without 'as' %% construct a range without 'as'
Sql00 = "select " Sql00 = "select "