aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2019-11-26 19:45:01 +0300
committerAlexey Shchepin <alexey@process-one.net>2019-11-26 19:45:01 +0300
commit2a35cadf80a5598a84a6dc3280877d6c0ed4b19b (patch)
treee6fa21affb164ca8f1171f696adf9b66a187e6ee /src
parentFix previous commit (diff)
parentAdded option to disable prepared statements (postgresql only) (diff)
Merge branch 'pg_prepared_statements' of https://github.com/sabudaye/ejabberd into sabudaye-pg_prepared_statements
Conflicts: ejabberd.yml.example src/ejabberd_sql.erl
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_option.erl8
-rw-r--r--src/ejabberd_options.erl3
-rw-r--r--src/ejabberd_sql.erl41
3 files changed, 45 insertions, 7 deletions
diff --git a/src/ejabberd_option.erl b/src/ejabberd_option.erl
index 773775743..a2855b1bf 100644
--- a/src/ejabberd_option.erl
+++ b/src/ejabberd_option.erl
@@ -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).
diff --git a/src/ejabberd_options.erl b/src/ejabberd_options.erl
index f0987986a..d1019dd62 100644
--- a/src/ejabberd_options.erl
+++ b/src/ejabberd_options.erl
@@ -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, []},
diff --git a/src/ejabberd_sql.erl b/src/ejabberd_sql.erl
index 1f3d27421..c1d9383a0 100644
--- a/src/ejabberd_sql.erl
+++ b/src/ejabberd_sql.erl
@@ -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)),