25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-26 17:38:45 +01:00

Merge branch 'pg_prepared_statements' of https://github.com/sabudaye/ejabberd into sabudaye-pg_prepared_statements

Conflicts:
	ejabberd.yml.example
	src/ejabberd_sql.erl
This commit is contained in:
Alexey Shchepin 2019-11-26 19:45:01 +03:00
commit 2a35cadf80
3 changed files with 45 additions and 7 deletions

View File

@ -138,6 +138,7 @@
-export([sql_password/0, sql_password/1]). -export([sql_password/0, sql_password/1]).
-export([sql_pool_size/0, sql_pool_size/1]). -export([sql_pool_size/0, sql_pool_size/1]).
-export([sql_port/0, sql_port/1]). -export([sql_port/0, sql_port/1]).
-export([sql_prepared_statements/0, sql_prepared_statements/1]).
-export([sql_query_timeout/0, sql_query_timeout/1]). -export([sql_query_timeout/0, sql_query_timeout/1]).
-export([sql_queue_type/0, sql_queue_type/1]). -export([sql_queue_type/0, sql_queue_type/1]).
-export([sql_server/0, sql_server/1]). -export([sql_server/0, sql_server/1]).
@ -933,6 +934,13 @@ sql_port() ->
sql_port(Host) -> sql_port(Host) ->
ejabberd_config:get_option({sql_port, Host}). ejabberd_config:get_option({sql_port, Host}).
-spec sql_prepared_statements() -> boolean().
sql_prepared_statements() ->
sql_prepared_statements(global).
-spec sql_prepared_statements(global | binary()) -> boolean().
sql_prepared_statements(Host) ->
ejabberd_config:get_option({sql_prepared_statements, Host}).
-spec sql_query_timeout() -> pos_integer(). -spec sql_query_timeout() -> pos_integer().
sql_query_timeout() -> sql_query_timeout() ->
sql_query_timeout(global). sql_query_timeout(global).

View File

@ -380,6 +380,8 @@ opt_type(sql_type) ->
econf:enum([mysql, pgsql, sqlite, mssql, odbc]); econf:enum([mysql, pgsql, sqlite, mssql, odbc]);
opt_type(sql_username) -> opt_type(sql_username) ->
econf:binary(); econf:binary();
opt_type(sql_prepared_statements) ->
econf:bool();
opt_type(trusted_proxies) -> opt_type(trusted_proxies) ->
econf:either(all, econf:list(econf:ip_mask())); econf:either(all, econf:list(econf:ip_mask()));
opt_type(use_cache) -> opt_type(use_cache) ->
@ -652,6 +654,7 @@ options() ->
{sql_ssl_verify, false}, {sql_ssl_verify, false},
{sql_start_interval, timer:seconds(30)}, {sql_start_interval, timer:seconds(30)},
{sql_username, <<"ejabberd">>}, {sql_username, <<"ejabberd">>},
{sql_prepared_statements, true},
{trusted_proxies, []}, {trusted_proxies, []},
{validate_stream, false}, {validate_stream, false},
{websocket_origin, []}, {websocket_origin, []},

View File

@ -583,14 +583,23 @@ sql_query_internal(#sql_query{} = Query) ->
Key = {?PREPARE_KEY, Query#sql_query.hash}, Key = {?PREPARE_KEY, Query#sql_query.hash},
case get(Key) of case get(Key) of
undefined -> undefined ->
case pgsql_prepare(Query, State) of Host = State#state.host,
{ok, _, _, _} -> PreparedStatements =
put(Key, prepared); ejabberd_option:sql_prepared_statements(Host),
{error, Error} -> case PreparedStatements of
?ERROR_MSG("PREPARE failed for SQL query " false ->
put(Key, ignore);
true ->
case pgsql_prepare(Query, State) of
{ok, _, _, _} ->
put(Key, prepared);
{error, Error} ->
?ERROR_MSG(
"PREPARE failed for SQL query "
"at ~p: ~p", "at ~p: ~p",
[Query#sql_query.loc, Error]), [Query#sql_query.loc, Error]),
put(Key, ignore) put(Key, ignore)
end
end; end;
_ -> _ ->
ok ok
@ -599,7 +608,7 @@ sql_query_internal(#sql_query{} = Query) ->
prepared -> prepared ->
pgsql_execute_sql_query(Query, State); pgsql_execute_sql_query(Query, State);
_ -> _ ->
generic_sql_query(Query) pgsql_sql_query(Query)
end; end;
mysql -> mysql ->
generic_sql_query(Query); generic_sql_query(Query);
@ -695,6 +704,24 @@ generic_escape() ->
in_array_string = fun(X) -> <<"'", (escape(X))/binary, "'">> end in_array_string = fun(X) -> <<"'", (escape(X))/binary, "'">> end
}. }.
pgsql_sql_query(SQLQuery) ->
sql_query_format_res(
sql_query_internal(pgsql_sql_query_format(SQLQuery)),
SQLQuery).
pgsql_sql_query_format(SQLQuery) ->
Args = (SQLQuery#sql_query.args)(pgsql_escape()),
(SQLQuery#sql_query.format_query)(Args).
pgsql_escape() ->
#sql_escape{string = fun(X) -> <<"E'", (escape(X))/binary, "'">> end,
integer = fun(X) -> misc:i2l(X) end,
boolean = fun(true) -> <<"1">>;
(false) -> <<"0">>
end,
in_array_string = fun(X) -> <<"E'", (escape(X))/binary, "'">> end
}.
sqlite_sql_query(SQLQuery) -> sqlite_sql_query(SQLQuery) ->
sql_query_format_res( sql_query_format_res(
sql_query_internal(sqlite_sql_query_format(SQLQuery)), sql_query_internal(sqlite_sql_query_format(SQLQuery)),