24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-14 22:00:16 +02:00

Use prepared statement with mysql

This commit is contained in:
Paweł Chmielowski 2023-07-25 16:52:49 +02:00
parent db03c7428c
commit 3710dc1e3b
4 changed files with 41 additions and 7 deletions

View File

@ -138,7 +138,7 @@ defmodule Ejabberd.MixProject do
{config(:zlib), {:ezlib, "~> 1.0"}}, {config(:zlib), {:ezlib, "~> 1.0"}},
{if_version_below('22', true), {:lager, "~> 3.9.1"}}, {if_version_below('22', true), {:lager, "~> 3.9.1"}},
{config(:lua), {:luerl, "~> 1.0"}}, {config(:lua), {:luerl, "~> 1.0"}},
{config(:mysql), {:p1_mysql, "~> 1.0.20"}}, {config(:mysql), {:p1_mysql, git: "https://github.com/processone/p1_mysql.git", ref: "150c15b96d2fb84cb00e07cc53cd97ec72b77efc"}},
{config(:pgsql), {:p1_pgsql, "~> 1.1"}}, {config(:pgsql), {:p1_pgsql, "~> 1.1"}},
{config(:sqlite), {:sqlite3, "~> 1.1"}}, {config(:sqlite), {:sqlite3, "~> 1.1"}},
{config(:stun), {:stun, "~> 1.0"}}], do: {config(:stun), {:stun, "~> 1.0"}}], do:

View File

@ -63,7 +63,7 @@
{mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.15"}}}, {mqtree, ".*", {git, "https://github.com/processone/mqtree", {tag, "1.0.15"}}},
{p1_acme, ".*", {git, "https://github.com/processone/p1_acme", {tag, "1.0.22"}}}, {p1_acme, ".*", {git, "https://github.com/processone/p1_acme", {tag, "1.0.22"}}},
{if_var_true, mysql, {if_var_true, mysql,
{p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.21"}}}}, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", "150c15b96d2fb84cb00e07cc53cd97ec72b77efc"}}},
{p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.11"}}}, {p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.11"}}},
{if_var_true, pgsql, {if_var_true, pgsql,
{p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.22"}}}}, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.22"}}}},

View File

@ -683,7 +683,14 @@ sql_query_internal(#sql_query{} = Query) ->
pgsql_sql_query(Query) pgsql_sql_query(Query)
end; end;
mysql -> mysql ->
generic_sql_query(Query); case {Query#sql_query.flags, ejabberd_option:sql_prepared_statements(State#state.host)} of
{1, _} ->
generic_sql_query(Query);
{_, false} ->
generic_sql_query(Query);
_ ->
mysql_prepared_execute(Query, State)
end;
sqlite -> sqlite ->
sqlite_sql_query(Query) sqlite_sql_query(Query)
end end
@ -862,6 +869,24 @@ pgsql_execute_sql_query(SQLQuery, State) ->
Res = pgsql_execute_to_odbc(ExecuteRes), Res = pgsql_execute_to_odbc(ExecuteRes),
sql_query_format_res(Res, SQLQuery). sql_query_format_res(Res, SQLQuery).
mysql_prepared_execute(#sql_query{hash = Hash} = Query, State) ->
ValEsc = #sql_escape{like_escape = fun() -> ignore end, _ = fun(X) -> X end},
TypesEsc = #sql_escape{string = fun(_) -> string end,
integer = fun(_) -> integer end,
boolean = fun(_) -> bool end,
in_array_string = fun(_) -> string end,
like_escape = fun() -> ignore end},
Val = [X || X <- (Query#sql_query.args)(ValEsc), X /= ignore],
Types = [X || X <- (Query#sql_query.args)(TypesEsc), X /= ignore],
QueryFn = fun() ->
PrepEsc = #sql_escape{like_escape = fun() -> <<>> end, _ = fun(_) -> <<"?">> end},
(Query#sql_query.format_query)((Query#sql_query.args)(PrepEsc))
end,
QueryTimeout = query_timeout(State#state.host),
Res = p1_mysql_conn:prepared_query(State#state.db_ref, QueryFn, Hash, Val, Types,
self(), [{timeout, QueryTimeout - 1000}]),
Res2 = mysql_to_odbc(Res),
sql_query_format_res(Res2, Query).
sql_query_format_res({selected, _, Rows}, SQLQuery) -> sql_query_format_res({selected, _, Rows}, SQLQuery) ->
Res = Res =

View File

@ -42,7 +42,8 @@
used_vars = [], used_vars = [],
use_new_schema, use_new_schema,
need_timestamp_pass = false, need_timestamp_pass = false,
need_array_pass = false}). need_array_pass = false,
has_list = false}).
-define(QUERY_RECORD, "sql_query"). -define(QUERY_RECORD, "sql_query").
@ -268,9 +269,12 @@ parse1([$@, $( | S], Acc, State) ->
Convert = Convert =
case Type of case Type of
integer -> integer ->
erl_syntax:application( erl_syntax:if_expr([
erl_syntax:atom(binary_to_integer), erl_syntax:clause(
[EVar]); [erl_syntax:application(erl_syntax:atom(is_binary), [EVar])],
[erl_syntax:application(erl_syntax:atom(binary_to_integer), [EVar])]),
erl_syntax:clause([erl_syntax:atom(true)], [EVar])
]);
string -> string ->
EVar; EVar;
timestamp -> timestamp ->
@ -339,6 +343,7 @@ parse1([$%, $( | S], Acc, State) ->
erl_syntax:variable(Name)]), erl_syntax:variable(Name)]),
State2#state{'query' = [[{var, Var, Type}] | State2#state.'query'], State2#state{'query' = [[{var, Var, Type}] | State2#state.'query'],
need_array_pass = true, need_array_pass = true,
has_list = true,
args = [[Convert, ConvertArr] | State2#state.args], args = [[Convert, ConvertArr] | State2#state.args],
params = [Var | State2#state.params], params = [Var | State2#state.params],
param_pos = State2#state.param_pos + 1, param_pos = State2#state.param_pos + 1,
@ -467,6 +472,7 @@ make_sql_query(State, Type) ->
Hash = erlang:phash2(State#state{loc = undefined, use_new_schema = true}), Hash = erlang:phash2(State#state{loc = undefined, use_new_schema = true}),
SHash = <<"Q", (integer_to_binary(Hash))/binary>>, SHash = <<"Q", (integer_to_binary(Hash))/binary>>,
Query = pack_query(State#state.'query'), Query = pack_query(State#state.'query'),
Flags = case State#state.has_list of true -> 1; _ -> 0 end,
EQuery = EQuery =
lists:flatmap( lists:flatmap(
fun({str, S}) -> fun({str, S}) ->
@ -515,6 +521,9 @@ make_sql_query(State, Type) ->
none, none,
[erl_syntax:tuple(State#state.res)] [erl_syntax:tuple(State#state.res)]
)])), )])),
erl_syntax:record_field(
erl_syntax:atom(flags),
erl_syntax:abstract(Flags)),
erl_syntax:record_field( erl_syntax:record_field(
erl_syntax:atom(loc), erl_syntax:atom(loc),
erl_syntax:abstract({get(?MOD), State#state.loc})) erl_syntax:abstract({get(?MOD), State#state.loc}))