25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

Fix MSSQL support

This commit is contained in:
Evgeniy Khramtsov 2015-09-13 14:20:31 +03:00
parent 48c5e73321
commit 25791cfde8
6 changed files with 19 additions and 5028 deletions

BIN
sql/mssql.sql Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -432,13 +432,13 @@ outer_transaction(F, NRestarts, _Reason) ->
[T]), [T]),
erlang:exit(implementation_faulty) erlang:exit(implementation_faulty)
end, end,
sql_query_internal(<<"begin;">>), sql_query_internal([<<"begin;">>]),
put(?NESTING_KEY, PreviousNestingLevel + 1), put(?NESTING_KEY, PreviousNestingLevel + 1),
Result = (catch F()), Result = (catch F()),
put(?NESTING_KEY, PreviousNestingLevel), put(?NESTING_KEY, PreviousNestingLevel),
case Result of case Result of
{aborted, Reason} when NRestarts > 0 -> {aborted, Reason} when NRestarts > 0 ->
sql_query_internal(<<"rollback;">>), sql_query_internal([<<"rollback;">>]),
outer_transaction(F, NRestarts - 1, Reason); outer_transaction(F, NRestarts - 1, Reason);
{aborted, Reason} when NRestarts =:= 0 -> {aborted, Reason} when NRestarts =:= 0 ->
?ERROR_MSG("SQL transaction restarts exceeded~n** " ?ERROR_MSG("SQL transaction restarts exceeded~n** "
@ -447,11 +447,11 @@ outer_transaction(F, NRestarts, _Reason) ->
"== ~p", "== ~p",
[?MAX_TRANSACTION_RESTARTS, Reason, [?MAX_TRANSACTION_RESTARTS, Reason,
erlang:get_stacktrace(), get(?STATE_KEY)]), erlang:get_stacktrace(), get(?STATE_KEY)]),
sql_query_internal(<<"rollback;">>), sql_query_internal([<<"rollback;">>]),
{aborted, Reason}; {aborted, Reason};
{'EXIT', Reason} -> {'EXIT', Reason} ->
sql_query_internal(<<"rollback;">>), {aborted, Reason}; sql_query_internal([<<"rollback;">>]), {aborted, Reason};
Res -> sql_query_internal(<<"commit;">>), {atomic, Res} Res -> sql_query_internal([<<"commit;">>]), {atomic, Res}
end. end.
execute_bloc(F) -> execute_bloc(F) ->
@ -463,6 +463,7 @@ execute_bloc(F) ->
sql_query_internal(Query) -> sql_query_internal(Query) ->
State = get(?STATE_KEY), State = get(?STATE_KEY),
?DEBUG("SQL: \"~s\"", [Query]),
Res = case State#state.db_type of Res = case State#state.db_type of
odbc -> odbc ->
to_odbc(odbc:sql_query(State#state.db_ref, Query, to_odbc(odbc:sql_query(State#state.db_ref, Query,
@ -512,7 +513,9 @@ abort_on_driver_error(Reply, From) ->
%% Open an ODBC database connection %% Open an ODBC database connection
odbc_connect(SQLServer) -> odbc_connect(SQLServer) ->
ejabberd:start_app(odbc), ejabberd:start_app(odbc),
odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off}, odbc:connect(binary_to_list(SQLServer),
[{scrollable_cursors, off},
{tuple_row, off},
{binary_strings, on}]). {binary_strings, on}]).
%% == Native SQLite code %% == Native SQLite code
@ -638,7 +641,15 @@ mysql_item_to_odbc(Columns, Recs) ->
{selected, [element(2, Column) || Column <- Columns], Recs}. {selected, [element(2, Column) || Column <- Columns], Recs}.
to_odbc({selected, Columns, Recs}) -> to_odbc({selected, Columns, Recs}) ->
{selected, [list_to_binary(Column) || Column <- Columns], [tuple_to_list(Rec) || Rec <- Recs]}; Rows = [lists:map(
fun(I) when is_integer(I) ->
jlib:integer_to_binary(I);
(B) ->
B
end, Row) || Row <- Recs],
{selected, [list_to_binary(C) || C <- Columns], Rows};
to_odbc({error, Reason}) when is_list(Reason) ->
{error, list_to_binary(Reason)};
to_odbc(Res) -> to_odbc(Res) ->
Res. Res.

View File

@ -58,17 +58,6 @@
escape/1, count_records_where/3, get_roster_version/2, escape/1, count_records_where/3, get_roster_version/2,
set_roster_version/2, opt_type/1]). set_roster_version/2, opt_type/1]).
%% We have only two compile time options for db queries:
%-define(generic, true).
%-define(mssql, true).
-ifndef(mssql).
-undef(generic).
-define(generic, true).
-endif.
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("logger.hrl"). -include("logger.hrl").
@ -78,10 +67,6 @@
join([], _Sep) -> []; join([], _Sep) -> [];
join([H | T], Sep) -> [H, [[Sep, X] || X <- T]]. join([H | T], Sep) -> [H, [[Sep, X] || X <- T]].
%% -----------------
%% Generic queries
-ifdef(generic).
get_db_type() -> generic. get_db_type() -> generic.
%% Safe atomic update. %% Safe atomic update.
@ -662,332 +647,6 @@ set_roster_version(LUser, Version) ->
[<<"username">>, <<"version">>], [LUser, Version], [<<"username">>, <<"version">>], [LUser, Version],
[<<"username = '">>, LUser, <<"'">>]). [<<"username = '">>, LUser, <<"'">>]).
-endif.
%% -----------------
%% MSSQL queries
-ifdef(mssql).
%% Queries can be either a fun or a list of queries
get_db_type() -> mssql.
sql_transaction(LServer, Queries)
when is_list(Queries) ->
F = fun () ->
lists:foreach(fun (Query) ->
ejabberd_odbc:sql_query(LServer, Query)
end,
Queries)
end,
{atomic, catch F()};
sql_transaction(_LServer, FQueries) ->
{atomic, catch FQueries()}.
get_last(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_last '">>, Username, <<"'">>]).
set_last_t(LServer, Username, Seconds, State) ->
Result = ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.set_last '">>, Username,
<<"', '">>, Seconds, <<"', '">>, State,
<<"'">>]),
{atomic, Result}.
del_last(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.del_last '">>, Username, <<"'">>]).
get_password(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_password '">>, Username,
<<"'">>]).
set_password_t(LServer, Username, Pass) ->
Result = ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.set_password '">>,
Username, <<"', '">>, Pass, <<"'">>]),
{atomic, Result}.
add_user(LServer, Username, Pass) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.add_user '">>, Username, <<"', '">>,
Pass, <<"'">>]).
del_user(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.del_user '">>, Username, <<"'">>]).
del_user_return_password(LServer, Username, Pass) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.del_user_return_password '">>,
Username, <<"'">>]),
Pass.
list_users(LServer) ->
ejabberd_odbc:sql_query(LServer,
<<"EXECUTE dbo.list_users">>).
list_users(LServer, _) -> list_users(LServer).
users_number(LServer) ->
ejabberd_odbc:sql_query(LServer,
<<"select count(*) from users with (nolock)">>).
users_number(LServer, _) -> users_number(LServer).
add_spool_sql(Username, XML) ->
[<<"EXECUTE dbo.add_spool '">>, Username, <<"' , '">>,
XML, <<"'">>].
add_spool(LServer, Queries) ->
lists:foreach(fun (Query) ->
ejabberd_odbc:sql_query(LServer, Query)
end,
Queries).
get_and_del_spool_msg_t(LServer, Username) ->
[Result] = case ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_and_del_spool_msg '">>,
Username, <<"'">>])
of
Rs when is_list(Rs) ->
lists:filter(fun ({selected, _Header, _Row}) -> true;
({updated, _N}) -> false
end,
Rs);
Rs -> [Rs]
end,
{atomic, Result}.
del_spool_msg(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.del_spool_msg '">>, Username,
<<"'">>]).
get_roster(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_roster '">>, Username,
<<"'">>]).
get_roster_jid_groups(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_roster_jid_groups '">>,
Username, <<"'">>]).
get_roster_groups(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_roster_groups '">>, Username,
<<"' , '">>, SJID, <<"'">>]).
del_user_roster_t(LServer, Username) ->
Result = ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.del_user_roster '">>,
Username, <<"'">>]),
{atomic, Result}.
get_roster_by_jid(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_roster_by_jid '">>, Username,
<<"' , '">>, SJID, <<"'">>]).
get_rostergroup_by_jid(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_rostergroup_by_jid '">>,
Username, <<"' , '">>, SJID, <<"'">>]).
del_roster(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.del_roster '">>, Username,
<<"', '">>, SJID, <<"'">>]).
del_roster_sql(Username, SJID) ->
[<<"EXECUTE dbo.del_roster '">>, Username, <<"', '">>,
SJID, <<"'">>].
update_roster(LServer, Username, SJID, ItemVals,
ItemGroups) ->
Query1 = [<<"EXECUTE dbo.del_roster '">>, Username,
<<"', '">>, SJID, <<"' ">>],
ejabberd_odbc:sql_query(LServer, lists:flatten(Query1)),
Query2 = [<<"EXECUTE dbo.add_roster_user ">>, ItemVals],
ejabberd_odbc:sql_query(LServer, lists:flatten(Query2)),
Query3 = [<<"EXECUTE dbo.del_roster_groups '">>,
Username, <<"', '">>, SJID, <<"' ">>],
ejabberd_odbc:sql_query(LServer, lists:flatten(Query3)),
lists:foreach(fun (ItemGroup) ->
Query = [<<"EXECUTE dbo.add_roster_group ">>,
ItemGroup],
ejabberd_odbc:sql_query(LServer, lists:flatten(Query))
end,
ItemGroups).
update_roster_sql(Username, SJID, ItemVals,
ItemGroups) ->
[<<"BEGIN TRANSACTION ">>,
<<"EXECUTE dbo.del_roster_groups '">>, Username,
<<"','">>, SJID, <<"' ">>,
<<"EXECUTE dbo.add_roster_user ">>, ItemVals, <<" ">>]
++
[lists:flatten(<<"EXECUTE dbo.add_roster_group ">>,
ItemGroup, <<" ">>)
|| ItemGroup <- ItemGroups]
++ [<<"COMMIT">>].
roster_subscribe(LServer, _Username, _SJID, ItemVals) ->
catch ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.add_roster_user ">>,
ItemVals]).
get_subscription(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_subscription '">>, Username,
<<"' , '">>, SJID, <<"'">>]).
set_private_data(LServer, Username, LXMLNS, SData) ->
ejabberd_odbc:sql_query(LServer,
set_private_data_sql(Username, LXMLNS, SData)).
set_private_data_sql(Username, LXMLNS, SData) ->
[<<"EXECUTE dbo.set_private_data '">>, Username,
<<"' , '">>, LXMLNS, <<"' , '">>, SData, <<"'">>].
get_private_data(LServer, Username, LXMLNS) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_private_data '">>, Username,
<<"' , '">>, LXMLNS, <<"'">>]).
del_user_private_storage(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.del_user_storage '">>, Username,
<<"'">>]).
set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail, SFN,
SFamily, SGiven, SLBDay, SLCTRY, SLEMail, SLFN,
SLFamily, SLGiven, SLLocality, SLMiddle, SLNickname,
SLOrgName, SLOrgUnit, SLocality, SMiddle, SNickname,
SOrgName, SOrgUnit, SVCARD, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.set_vcard '">>, SVCARD, <<"' , '">>,
Username, <<"' , '">>, LUsername, <<"' , '">>, SFN,
<<"' , '">>, SLFN, <<"' , '">>, SFamily,
<<"' , '">>, SLFamily, <<"' , '">>, SGiven,
<<"' , '">>, SLGiven, <<"' , '">>, SMiddle,
<<"' , '">>, SLMiddle, <<"' , '">>, SNickname,
<<"' , '">>, SLNickname, <<"' , '">>, SBDay,
<<"' , '">>, SLBDay, <<"' , '">>, SCTRY,
<<"' , '">>, SLCTRY, <<"' , '">>, SLocality,
<<"' , '">>, SLLocality, <<"' , '">>, SEMail,
<<"' , '">>, SLEMail, <<"' , '">>, SOrgName,
<<"' , '">>, SLOrgName, <<"' , '">>, SOrgUnit,
<<"' , '">>, SLOrgUnit, <<"'">>]).
get_vcard(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_vcard '">>, Username, <<"'">>]).
get_default_privacy_list(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_default_privacy_list '">>,
Username, <<"'">>]).
get_default_privacy_list_t(Username) ->
ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.get_default_privacy_list '">>,
Username, <<"'">>]).
get_privacy_list_names(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_privacy_list_names '">>,
Username, <<"'">>]).
get_privacy_list_names_t(Username) ->
ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.get_privacy_list_names '">>,
Username, <<"'">>]).
get_privacy_list_id(LServer, Username, SName) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_privacy_list_id '">>, Username,
<<"' , '">>, SName, <<"'">>]).
get_privacy_list_id_t(Username, SName) ->
ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.get_privacy_list_id '">>,
Username, <<"' , '">>, SName, <<"'">>]).
get_privacy_list_data(LServer, Username, SName) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_privacy_list_data '">>,
Username, <<"' , '">>, SName, <<"'">>]).
get_privacy_list_data_by_id(LServer, ID) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_privacy_list_data_by_id '">>,
ID, <<"'">>]).
get_privacy_list_data_by_id_t(ID) ->
ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.get_privacy_list_data_by_id '">>,
ID, <<"'">>]).
set_default_privacy_list(Username, SName) ->
ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.set_default_privacy_list '">>,
Username, <<"' , '">>, SName, <<"'">>]).
unset_default_privacy_list(LServer, Username) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.unset_default_privacy_list '">>,
Username, <<"'">>]).
remove_privacy_list(Username, SName) ->
ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.remove_privacy_list '">>,
Username, <<"' , '">>, SName, <<"'">>]).
add_privacy_list(Username, SName) ->
ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.add_privacy_list '">>,
Username, <<"' , '">>, SName, <<"'">>]).
set_privacy_list(ID, RItems) ->
ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.del_privacy_list_by_id '">>,
ID, <<"'">>]),
lists:foreach(fun (Items) ->
ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.set_privacy_list '">>,
ID, <<"', '">>,
join(Items, <<"', '">>),
<<"'">>])
end,
RItems).
del_privacy_lists(LServer, Server, Username) ->
%% Characters to escape
%% Count number of records in a table given a where clause
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.del_privacy_lists @Server='">>,
Server, <<"' @username='">>, Username, <<"'">>]).
escape($\000) -> <<"\\0">>;
escape($\t) -> <<"\\t">>;
escape($\b) -> <<"\\b">>;
escape($\r) -> <<"\\r">>;
escape($') -> <<"''">>;
escape($") -> <<"\\\"">>;
escape(C) -> C.
count_records_where(LServer, Table, WhereClause) ->
ejabberd_odbc:sql_query(LServer,
[<<"select count(*) from ">>, Table,
<<" with (nolock) ">>, WhereClause]).
get_roster_version(LServer, LUser) ->
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.get_roster_version '">>, LUser,
<<"'">>]).
set_roster_version(Username, Version) ->
LServer = (?MYNAME),
ejabberd_odbc:sql_query(LServer,
[<<"EXECUTE dbo.set_roster_version '">>, Username,
<<"', '">>, Version, <<"'">>]).
-endif.
opt_type(odbc_type) -> opt_type(odbc_type) ->
fun (pgsql) -> pgsql; fun (pgsql) -> pgsql;
(mysql) -> mysql; (mysql) -> mysql;