From f97cf4a66396b8cbcbb4f9bad7e62ed2f321321a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E7=A4=BC=E6=88=90?= Date: Mon, 27 Feb 2023 22:48:45 +0800 Subject: [PATCH] fix rule --- apps/iot/include/iot.hrl | 22 ++++- apps/iot/src/http_host_handler.erl | 1 + apps/iot/src/iot_mock.erl | 26 +++++- apps/iot/src/iot_rule_parser.erl | 126 +++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 apps/iot/src/iot_rule_parser.erl diff --git a/apps/iot/include/iot.hrl b/apps/iot/include/iot.hrl index b167e37..5995dda 100644 --- a/apps/iot/include/iot.hrl +++ b/apps/iot/include/iot.hrl @@ -152,4 +152,24 @@ %% 指标, 终端指标涉及到查询效率和更新效率的问题,因此合并到一起 metrics = [] :: [#service_metric{}], status = 0 -}). \ No newline at end of file +}). + +-record(http_endpoint, { + url = <<>> +}). + +-record(kafka_endpoint, { + +}). + +%% 数据转换规则表 +-record(router, { + %% 名称 + name = <<>>, + %% 数据过滤规则 + rule = <<>>, + %% 对端 + endpoint, + %% 状态 + status = 0 +}). diff --git a/apps/iot/src/http_host_handler.erl b/apps/iot/src/http_host_handler.erl index dcbe936..75bdeaf 100644 --- a/apps/iot/src/http_host_handler.erl +++ b/apps/iot/src/http_host_handler.erl @@ -72,6 +72,7 @@ handle_request(_, "/host/list", Params, PostParams) -> handle_request("GET", "/host/detail", #{<<"id">> := HostId}, _) -> lager:debug("[host_handler] detail id is: ~p", [HostId]), + timer:tc(), case host_model:get_host(HostId) of undefined -> {ok, 200, iot_util:json_error(404, <<"host not found">>)}; diff --git a/apps/iot/src/iot_mock.erl b/apps/iot/src/iot_mock.erl index 381d15e..5eb5f3b 100644 --- a/apps/iot/src/iot_mock.erl +++ b/apps/iot/src/iot_mock.erl @@ -106,4 +106,28 @@ rsa_decode(EncData) when is_binary(EncData) -> PlainData = public_key:decrypt_private(EncData, PubKey), lager:debug("plain data is: ~p", [PlainData]), - ok. \ No newline at end of file + ok. + +scan_and(Tokens) -> + scan_and(Tokens, [], [], 0). +%% 扫描完成并且最后一个表达式为空 +scan_and([], [], Acc, 0) -> + lists:reverse(Acc); +%% 扫描完成并且最后一个表达式不为空 +scan_and([], Expr, Acc, 0) -> + lists:reverse([{simple, lists:reverse(Expr)}|Acc]); +%% 遇到OR关键词, 并且此时的层级为0 +scan_and([32, $O, $R, 32|Tokens], Expr, Acc, 0) -> + scan_and(Tokens, [], [{simple, lists:reverse(Expr)}|Acc], 0); +%% 扫描到左括号 && Level > 0; 此时的Expr需要更多的字符 +scan_and([Token|Tokens], Expr, Acc, Level) when Token == $( -> + scan_and(Tokens, [Token|Expr], Acc, Level + 1); +%% 扫描到右括号 && Level == 1; 此时的Expr表达式的内部嵌套的子串扫描完成 +scan_and([Token|Tokens], Expr, Acc, 1) when Token == $) -> + scan_and(Tokens, [Token|Expr], Acc, 0); +%% 扫描到右括号 && Level > 1; 此时的Expr表达式的内部嵌套的子串扫描完成,Level的值减1 +scan_and([Token|Tokens], Expr, Acc, Level) when Token == $) -> + scan_and(Tokens, [Token|Expr], Acc, Level - 1); +%% 普通字符 +scan_and([Token|Tokens], Expr, Acc, Level) -> + scan_and(Tokens, [Token|Expr], Acc, Level). \ No newline at end of file diff --git a/apps/iot/src/iot_rule_parser.erl b/apps/iot/src/iot_rule_parser.erl new file mode 100644 index 0000000..6946d54 --- /dev/null +++ b/apps/iot/src/iot_rule_parser.erl @@ -0,0 +1,126 @@ +%%%------------------------------------------------------------------- +%%% @author licheng5 +%%% @copyright (C) 2023, +%%% @doc +%%% +%%% @end +%%% Created : 27. 2月 2023 16:00 +%%%------------------------------------------------------------------- +-module(iot_rule_parser). +-author("licheng5"). + +%% API +-export([parse/1, test/0]). + +test() -> + %Rule = <<"SELECT * FROM service.data WHERE id > 0 AND (name = 'anlicheng' OR name = 'test')">>, + %parse(Rule), + Tokens = parse_condition(<<"id > 0 OR id < 3 AND (name = 'anlicheng' OR (name = 'test' AND (y = 1 OR x = 1))) AND (age > 1)">>), + % generate(Tokens, #{<<"name">> => <<"anlicheng">>, <<"id">> => 1234}), + ok. + +scan(Tokens) -> + ExprList = scan_or(Tokens), + lists:map(fun(Expr) -> scan_and(Expr) end, ExprList). + +scan_or(Tokens) -> + scan_or(Tokens, [], [], 0). +%% 扫描完成并且最后一个表达式为空 +scan_or([], [], Acc, 0) -> + lists:reverse(Acc); +%% 扫描完成并且最后一个表达式不为空 +scan_or([], Expr, Acc, 0) -> + lists:reverse([lists:reverse(Expr)|Acc]); +%% 遇到OR关键词, 并且此时的层级为0 +scan_or([32, $O, $R, 32|Tokens], Expr, Acc, 0) -> + scan_or(Tokens, [], [lists:reverse(Expr)|Acc], 0); +%% 扫描到左括号 && Level > 0; 此时的Expr需要更多的字符 +scan_or([Token|Tokens], Expr, Acc, Level) when Token == $( -> + scan_or(Tokens, [Token|Expr], Acc, Level + 1); +%% 扫描到右括号 && Level == 1; 此时的Expr表达式的内部嵌套的子串扫描完成 +scan_or([Token|Tokens], Expr, Acc, 1) when Token == $) -> + scan_or(Tokens, [Token|Expr], Acc, 0); +%% 扫描到右括号 && Level > 1; 此时的Expr表达式的内部嵌套的子串扫描完成,Level的值减1 +scan_or([Token|Tokens], Expr, Acc, Level) when Token == $) -> + scan_or(Tokens, [Token|Expr], Acc, Level - 1); +%% 普通字符 +scan_or([Token|Tokens], Expr, Acc, Level) -> + scan_or(Tokens, [Token|Expr], Acc, Level). + +scan_and(Tokens) -> + scan_and(Tokens, [], [], 0). +%% 扫描完成并且最后一个表达式为空 +scan_and([], [], Acc, 0) -> + lists:reverse(Acc); +%% 扫描完成并且最后一个表达式不为空 +scan_and([], Expr, Acc, 0) -> + lists:reverse([{simple, lists:reverse(Expr)}|Acc]); +%% 遇到OR关键词, 并且此时的层级为0 +scan_and([32, $A, $N, $D, 32|Tokens], Expr, Acc, 0) -> + scan_and(Tokens, [], [{simple, lists:reverse(Expr)}|Acc], 0); +%% 扫描到左括号 && Level > 0; 此时的Expr需要更多的字符 +scan_and([Token|Tokens], Expr, Acc, Level) when Token == $( -> + scan_and(Tokens, [Token|Expr], Acc, Level + 1); +%% 扫描到右括号 && Level == 1; 此时的Expr表达式的内部嵌套的子串扫描完成 +scan_and([Token|Tokens], Expr, Acc, 1) when Token == $) -> + scan_and(Tokens, [Token|Expr], Acc, 0); +%% 扫描到右括号 && Level > 1; 此时的Expr表达式的内部嵌套的子串扫描完成,Level的值减1 +scan_and([Token|Tokens], Expr, Acc, Level) when Token == $) -> + scan_and(Tokens, [Token|Expr], Acc, Level - 1); +%% 普通字符 +scan_and([Token|Tokens], Expr, Acc, Level) -> + scan_and(Tokens, [Token|Expr], Acc, Level). + +parse(Rule) -> + {ok, MP} = re:compile("SELECT (.*) FROM (.*) WHERE (.*)"), + case re:run(Rule, MP, [{capture, all, binary}]) of + nomatch -> + lager:debug("not match rule"); + {match, Captured} -> + lager:debug("match rule: ~p", [Captured]) + end, + ok. + +parse_condition(Condition) when is_binary(Condition) -> + Tokens = unicode:characters_to_list(Condition), + X = scan(Tokens), + lists:foreach(fun(E) -> lager:debug("E is: ~p", [E]) end, X), + X. + +parse_token(Tokens) -> + parse_token(Tokens, [], [], 0). +%% 扫描完成并且最后一个表达式为空 +parse_token([], [], Acc, 0) -> + lists:reverse(Acc); +%% 扫描完成并且最后一个表达式不为空 +parse_token([], Expr, Acc, 0) -> + lists:reverse([{simple, lists:reverse(Expr)}|Acc]); +%% 扫描到左括号 && Level == 0; 此时的Expr为简单表达式 +parse_token([Token|Tokens], Expr, Acc, 0) when Token == $( -> + parse_token(Tokens, [], [{simple, lists:reverse(Expr)}|Acc], 1); +%% 扫描到左括号 && Level > 0; 此时的Expr需要更多的字符 +parse_token([Token|Tokens], Expr, Acc, Level) when Token == $( -> + parse_token(Tokens, [Token|Expr], Acc, Level + 1); +%% 扫描到右括号 && Level == 1; 此时的Expr表达式的字符串扫描完毕; 递归处理子表达式 +parse_token([Token|Tokens], Expr, Acc, 1) when Token == $) -> + parse_token(Tokens, [], [{complex, parse_token(lists:reverse(Expr))}|Acc], 0); +%% 扫描到右括号 && Level > 1; 此时的Expr表达式的内部嵌套的子串扫描完成,Level的值减1 +parse_token([Token|Tokens], Expr, Acc, Level) when Token == $) -> + parse_token(Tokens, [Token|Expr], Acc, Level - 1); +%% 普通字符 +parse_token([Token|Tokens], Expr, Acc, Level) -> + parse_token(Tokens, [Token|Expr], Acc, Level). + +%% 处理表达式的优先级关系 +generate([{simple, Expr}|ExprList], Data) -> + Tokens = string:tokens(Expr, "OR"), + Tokens1 = lists:map(fun(Token) -> string:tokens(Token, "AND") end, Tokens), + + lager:debug("tokens: ~p", [Tokens1]), + + + + ok. + + +