Просмотр исходного кода

fix(utils_sql): improve insert sql regular expression

JimMoen 1 год назад
Родитель
Сommit
627b8c45d2
1 измененных файлов с 20 добавлено и 11 удалено
  1. 20 11
      apps/emqx_utils/src/emqx_utils_sql.erl

+ 20 - 11
apps/emqx_utils/src/emqx_utils_sql.erl

@@ -54,17 +54,26 @@ get_statement_type(Query) ->
 -spec parse_insert(iodata()) ->
     {ok, {_Statement :: binary(), _Rows :: binary()}} | {error, not_insert_sql}.
 parse_insert(SQL) ->
-    case re:split(SQL, "((?i)values)", [{return, binary}]) of
-        [Part1, _, Part3] ->
-            case string:trim(Part1, leading) of
-                <<"insert", _/binary>> = InsertSQL ->
-                    {ok, {InsertSQL, Part3}};
-                <<"INSERT", _/binary>> = InsertSQL ->
-                    {ok, {InsertSQL, Part3}};
-                _ ->
-                    {error, not_insert_sql}
-            end;
-        _ ->
+    Pattern = <<
+        %% case-insensitive
+        "(?i)^\\s*",
+        %% Group-1: insert into, table name and columns (when existed).
+        %% All space characters suffixed to <TABLE_NAME> will be kept
+        %% `INSERT INTO <TABLE_NAME> [(<COLUMN>, ..)]`
+        "(insert\\s+into\\s+[^\\s\\(\\)]+\\s*(?:\\([^\\)]*\\))?)",
+        %% Keyword: `VALUES`
+        "\\s*values\\s*",
+        %% Group-2: literals value(s) or placeholder(s) with round brackets.
+        %% And the sub-pattern in brackets does not do any capturing
+        %% `([<VALUE> | <PLACEHOLDER>], ..])`
+        "(\\((?:[^()]++|(?2))*\\))",
+        "\\s*$"
+    >>,
+
+    case re:run(SQL, Pattern, [{capture, all_but_first, binary}]) of
+        {match, [InsertInto, ValuesTemplate]} ->
+            {ok, {InsertInto, ValuesTemplate}};
+        nomatch ->
             {error, not_insert_sql}
     end.