Merge branch 'sabudaye-pg_prepared_statements'

This commit is contained in:
Alexey Shchepin 2019-11-26 19:45:47 +03:00
commit a9f3fd2179
3 changed files with 45 additions and 7 deletions

View File

@ -138,6 +138,7 @@
-export([sql_password/0, sql_password/1]).
-export([sql_pool_size/0, sql_pool_size/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_queue_type/0, sql_queue_type/1]).
-export([sql_server/0, sql_server/1]).
@ -933,6 +934,13 @@ sql_port() ->
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().
sql_query_timeout() ->
sql_query_timeout(global).

View File

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

View File

@ -583,14 +583,23 @@ sql_query_internal(#sql_query{} = Query) ->
Key = {?PREPARE_KEY, Query#sql_query.hash},
case get(Key) of
undefined ->
case pgsql_prepare(Query, State) of
{ok, _, _, _} ->
put(Key, prepared);
{error, Error} ->
?ERROR_MSG("PREPARE failed for SQL query "
Host = State#state.host,
PreparedStatements =
ejabberd_option:sql_prepared_statements(Host),
case PreparedStatements of
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",
[Query#sql_query.loc, Error]),
put(Key, ignore)
put(Key, ignore)
end
end;
_ ->
ok
@ -599,7 +608,7 @@ sql_query_internal(#sql_query{} = Query) ->
prepared ->
pgsql_execute_sql_query(Query, State);
_ ->
generic_sql_query(Query)
pgsql_sql_query(Query)
end;
mysql ->
generic_sql_query(Query);
@ -695,6 +704,24 @@ generic_escape() ->
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) ->
sql_query_format_res(
sql_query_internal(sqlite_sql_query_format(SQLQuery)),