mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Support for run-time SQL queries selection depending on DBMS version
This commit is contained in:
parent
6374ef4866
commit
c58a4be6ee
@ -68,6 +68,7 @@
|
|||||||
-record(state,
|
-record(state,
|
||||||
{db_ref = self() :: pid(),
|
{db_ref = self() :: pid(),
|
||||||
db_type = odbc :: pgsql | mysql | sqlite | odbc | mssql,
|
db_type = odbc :: pgsql | mysql | sqlite | odbc | mssql,
|
||||||
|
db_version = undefined :: undefined | non_neg_integer(),
|
||||||
start_interval = 0 :: non_neg_integer(),
|
start_interval = 0 :: non_neg_integer(),
|
||||||
host = <<"">> :: binary(),
|
host = <<"">> :: binary(),
|
||||||
max_pending_requests_len :: non_neg_integer(),
|
max_pending_requests_len :: non_neg_integer(),
|
||||||
@ -263,15 +264,16 @@ connecting(connect, #state{host = Host} = State) ->
|
|||||||
end,
|
end,
|
||||||
{_, PendingRequests} = State#state.pending_requests,
|
{_, PendingRequests} = State#state.pending_requests,
|
||||||
case ConnectRes of
|
case ConnectRes of
|
||||||
{ok, Ref} ->
|
{ok, Ref} ->
|
||||||
erlang:monitor(process, Ref),
|
erlang:monitor(process, Ref),
|
||||||
lists:foreach(fun (Req) ->
|
lists:foreach(fun (Req) ->
|
||||||
(?GEN_FSM):send_event(self(), Req)
|
(?GEN_FSM):send_event(self(), Req)
|
||||||
end,
|
end,
|
||||||
queue:to_list(PendingRequests)),
|
queue:to_list(PendingRequests)),
|
||||||
{next_state, session_established,
|
State1 = State#state{db_ref = Ref,
|
||||||
State#state{db_ref = Ref,
|
pending_requests = {0, queue:new()}},
|
||||||
pending_requests = {0, queue:new()}}};
|
State2 = get_db_version(State1),
|
||||||
|
{next_state, session_established, State2};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?INFO_MSG("~p connection failed:~n** Reason: ~p~n** "
|
?INFO_MSG("~p connection failed:~n** Reason: ~p~n** "
|
||||||
"Retry after: ~p seconds",
|
"Retry after: ~p seconds",
|
||||||
@ -473,6 +475,14 @@ execute_bloc(F) ->
|
|||||||
Res -> {atomic, Res}
|
Res -> {atomic, Res}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
sql_query_internal([{_, _} | _] = Queries) ->
|
||||||
|
State = get(?STATE_KEY),
|
||||||
|
case select_sql_query(Queries, State) of
|
||||||
|
undefined ->
|
||||||
|
{error, <<"no matching query for the current DBMS found">>};
|
||||||
|
Query ->
|
||||||
|
sql_query_internal(Query)
|
||||||
|
end;
|
||||||
sql_query_internal(#sql_query{} = Query) ->
|
sql_query_internal(#sql_query{} = Query) ->
|
||||||
State = get(?STATE_KEY),
|
State = get(?STATE_KEY),
|
||||||
Res =
|
Res =
|
||||||
@ -545,6 +555,28 @@ sql_query_internal(Query) ->
|
|||||||
_Else -> Res
|
_Else -> Res
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
select_sql_query(Queries, State) ->
|
||||||
|
select_sql_query(
|
||||||
|
Queries, State#state.db_type, State#state.db_version, undefined).
|
||||||
|
|
||||||
|
select_sql_query([], _Type, _Version, undefined) ->
|
||||||
|
undefined;
|
||||||
|
select_sql_query([], _Type, _Version, Query) ->
|
||||||
|
Query;
|
||||||
|
select_sql_query([{Type, Query} | _], Type, _Version, _) ->
|
||||||
|
Query;
|
||||||
|
select_sql_query([{{Type, _Version1}, Query1} | Rest], Type, undefined, _) ->
|
||||||
|
select_sql_query(Rest, Type, undefined, Query1);
|
||||||
|
select_sql_query([{{Type, Version1}, Query1} | Rest], Type, Version, Query) ->
|
||||||
|
if
|
||||||
|
Version >= Version1 ->
|
||||||
|
Query1;
|
||||||
|
true ->
|
||||||
|
select_sql_query(Rest, Type, Version, Query)
|
||||||
|
end;
|
||||||
|
select_sql_query([{_, _} | Rest], Type, Version, Query) ->
|
||||||
|
select_sql_query(Rest, Type, Version, Query).
|
||||||
|
|
||||||
generic_sql_query(SQLQuery) ->
|
generic_sql_query(SQLQuery) ->
|
||||||
sql_query_format_res(
|
sql_query_format_res(
|
||||||
sql_query_internal(generic_sql_query_format(SQLQuery)),
|
sql_query_internal(generic_sql_query_format(SQLQuery)),
|
||||||
@ -780,6 +812,24 @@ to_odbc({error, Reason}) when is_list(Reason) ->
|
|||||||
to_odbc(Res) ->
|
to_odbc(Res) ->
|
||||||
Res.
|
Res.
|
||||||
|
|
||||||
|
get_db_version(#state{db_type = pgsql} = State) ->
|
||||||
|
case pgsql:squery(State#state.db_ref,
|
||||||
|
<<"select current_setting('server_version_num')">>) of
|
||||||
|
{ok, [{_, _, [[SVersion]]}]} ->
|
||||||
|
case catch binary_to_integer(SVersion) of
|
||||||
|
Version when is_integer(Version) ->
|
||||||
|
State#state{db_version = Version};
|
||||||
|
Error ->
|
||||||
|
?WARNING_MSG("error getting pgsql version: ~p", [Error]),
|
||||||
|
State
|
||||||
|
end;
|
||||||
|
Res ->
|
||||||
|
?WARNING_MSG("error getting pgsql version: ~p", [Res]),
|
||||||
|
State
|
||||||
|
end;
|
||||||
|
get_db_version(State) ->
|
||||||
|
State.
|
||||||
|
|
||||||
log(Level, Format, Args) ->
|
log(Level, Format, Args) ->
|
||||||
case Level of
|
case Level of
|
||||||
debug -> ?DEBUG(Format, Args);
|
debug -> ?DEBUG(Format, Args);
|
||||||
@ -927,7 +977,12 @@ check_error({error, Why} = Err, #sql_query{} = Query) ->
|
|||||||
[Query#sql_query.hash, Query#sql_query.loc, Why]),
|
[Query#sql_query.hash, Query#sql_query.loc, Why]),
|
||||||
Err;
|
Err;
|
||||||
check_error({error, Why} = Err, Query) ->
|
check_error({error, Why} = Err, Query) ->
|
||||||
?ERROR_MSG("SQL query '~s' failed: ~p", [Query, Why]),
|
case catch iolist_to_binary(Query) of
|
||||||
|
SQuery when is_binary(SQuery) ->
|
||||||
|
?ERROR_MSG("SQL query '~s' failed: ~p", [SQuery, Why]);
|
||||||
|
_ ->
|
||||||
|
?ERROR_MSG("SQL query ~p failed: ~p", [Query, Why])
|
||||||
|
end,
|
||||||
Err;
|
Err;
|
||||||
check_error(Result, _Query) ->
|
check_error(Result, _Query) ->
|
||||||
Result.
|
Result.
|
||||||
|
Loading…
Reference in New Issue
Block a user