diff --git a/sql/mssql.sql b/sql/mssql.sql index 36ce50f4a..155ea64a0 100644 Binary files a/sql/mssql.sql and b/sql/mssql.sql differ diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index e98665862..f595933a1 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -269,6 +269,7 @@ connecting(connect, #state{host = Host} = State) -> [mysql | Args] -> apply(fun mysql_connect/5, Args); [pgsql | Args] -> apply(fun pgsql_connect/5, Args); [sqlite | Args] -> apply(fun sqlite_connect/1, Args); + [mssql | Args] -> apply(fun odbc_connect/1, Args); [odbc | Args] -> apply(fun odbc_connect/1, Args) end, {_, PendingRequests} = State#state.pending_requests, @@ -505,6 +506,8 @@ sql_query_internal(#sql_query{} = Query) -> case State#state.db_type of odbc -> generic_sql_query(Query); + mssql -> + generic_sql_query(Query); pgsql -> Key = {?PREPARE_KEY, Query#sql_query.hash}, case get(Key) of @@ -554,7 +557,10 @@ sql_query_internal(Query) -> ?DEBUG("SQL: \"~s\"", [Query]), Res = case State#state.db_type of odbc -> - to_odbc(odbc:sql_query(State#state.db_ref, Query, + to_odbc(odbc:sql_query(State#state.db_ref, [Query], + (?TRANSACTION_TIMEOUT) - 1000)); + mssql -> + to_odbc(odbc:sql_query(State#state.db_ref, [Query], (?TRANSACTION_TIMEOUT) - 1000)); pgsql -> pgsql_to_odbc(pgsql:squery(State#state.db_ref, Query)); @@ -898,8 +904,8 @@ db_opts(Host) -> <<"">>), case Type of mssql -> - [odbc, <<"DSN=", Host/binary, ";UID=", User/binary, - ";PWD=", Pass/binary>>]; + [mssql, <<"DSN=", Host/binary, ";UID=", User/binary, + ";PWD=", Pass/binary>>]; _ -> [Type, Server, Port, DB, User, Pass] end diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 38642c0c6..d212f63c6 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -1260,7 +1260,7 @@ make_matchspec(LUser, LServer, Start, End, none) -> Msg end). -make_sql_query(User, _LServer, Start, End, With, RSM) -> +make_sql_query(User, LServer, Start, End, With, RSM) -> {Max, Direction, ID} = case RSM of #rsm_in{} -> {RSM#rsm_in.max, @@ -1269,11 +1269,19 @@ make_sql_query(User, _LServer, Start, End, With, RSM) -> none -> {none, none, <<>>} end, - LimitClause = if is_integer(Max), Max >= 0 -> + ODBCType = ejabberd_config:get_option( + {odbc_type, LServer}, + ejabberd_odbc:opt_type(odbc_type)), + LimitClause = if is_integer(Max), Max >= 0, ODBCType /= mssql -> [<<" limit ">>, jlib:integer_to_binary(Max+1)]; true -> [] end, + TopClause = if is_integer(Max), Max >= 0, ODBCType == mssql -> + [<<" TOP ">>, jlib:integer_to_binary(Max+1)]; + true -> + [] + end, WithClause = case With of {text, <<>>} -> []; @@ -1320,7 +1328,7 @@ make_sql_query(User, _LServer, Start, End, With, RSM) -> end, SUser = ejabberd_odbc:escape(User), - Query = [<<"SELECT timestamp, xml, peer, kind, nick" + Query = [<<"SELECT ">>, TopClause, <<" timestamp, xml, peer, kind, nick" " FROM archive WHERE username='">>, SUser, <<"'">>, WithClause, StartClause, EndClause, PageClause], diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index e3c579382..5aeb973d1 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -697,12 +697,21 @@ get_items(Nidx, _From, {selected, [_], [[C]]} -> C; _ -> <<"0">> end, - case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " - "from pubsub_item where nodeid='">>, Nidx, - <<"' and ">>, AttrName, <<" ">>, Way, <<" ">>, Id, <<" order by ">>, - AttrName, <<" ">>, Order, <<" limit ">>, jlib:i2l(Max), <<" ;">>]) - of + Query = fun(mssql, _) -> + ejabberd_odbc:sql_query_t( + [<<"select top ">>, jlib:i2l(Max), + <<" itemid, publisher, creation, modification, payload " + "from pubsub_item where nodeid='">>, Nidx, + <<"' and ">>, AttrName, <<" ">>, Way, <<" ">>, Id, <<" order by ">>, + AttrName, <<" ">>, Order, <<";">>]); + (_, _) -> + ejabberd_odbc:sql_query_t( + [<<"select itemid, publisher, creation, modification, payload " + "from pubsub_item where nodeid='">>, Nidx, + <<"' and ">>, AttrName, <<" ">>, Way, <<" ">>, Id, <<" order by ">>, + AttrName, <<" ">>, Order, <<" limit ">>, jlib:i2l(Max), <<" ;">>]) + end, + case catch ejabberd_odbc:sql_query_t(Query) of {selected, [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> case RItems of @@ -760,11 +769,20 @@ get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM end. get_last_items(Nidx, _From, Count) -> - case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " - "from pubsub_item where nodeid='">>, Nidx, - <<"' order by modification desc limit ">>, jlib:i2l(Count), <<";">>]) - of + Limit = jlib:i2l(Count), + Query = fun(mssql, _) -> + ejabberd_odbc:sql_query_t( + [<<"select top ">>, Limit, + <<" itemid, publisher, creation, modification, payload " + "from pubsub_item where nodeid='">>, Nidx, + <<"' order by modification desc ;">>]); + (_, _) -> + ejabberd_odbc:sql_query_t( + [<<"select itemid, publisher, creation, modification, payload " + "from pubsub_item where nodeid='">>, Nidx, + <<"' order by modification desc limit ">>, Limit, <<";">>]) + end, + case catch ejabberd_odbc:sql_query_t(Query) of {selected, [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> {result, [raw_to_item(Nidx, RItem) || RItem <- RItems]};