* src/odbc/mysql.sql: Database description for MySQL Database

4.1 (Max version, with Innodb)
* src/ejabberd_auth_odbc.erl: MySQL ODBC support.
* src/mod_offline_odbc.erl: likewise
* src/mod_vcard_odbc.erl: likewsie
* src/mod_roster_odbc.erl: likewise
* src/odbc/ejabberd_odbc.erl: likewise
* src/mod_last_odbc.erl: likewise

SVN Revision: 474
This commit is contained in:
Mickaël Rémond 2005-12-21 16:10:56 +00:00
parent c275a24597
commit 559b5cae14
7 changed files with 147 additions and 130 deletions

View File

@ -1,3 +1,14 @@
2005-12-21 Mickael Remond <mickael.remond@process-one.net>
* src/odbc/mysql.sql: Database description for MySQL Database 4.1 (Max
version, with Innodb)
* src/ejabberd_auth_odbc.erl: MySQL ODBC support.
* src/mod_offline_odbc.erl: likewise
* src/mod_vcard_odbc.erl: likewsie
* src/mod_roster_odbc.erl: likewise
* src/odbc/ejabberd_odbc.erl: likewise
* src/mod_last_odbc.erl: likewise
2005-12-16 Mickael Remond <mickael.remond@process-one.net>
* doc/Makefile: Added helper to generate the docs (Thanks to Sander

View File

@ -91,12 +91,12 @@ set_password(User, Server, Password) ->
LUser ->
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["begin;"
"delete from users where username='", Username ,"';"
"insert into users(username, password) "
"values ('", Username, "', '", Pass, "'); commit"])
LServer = jlib:nameprep(Server),
catch ejabberd_odbc:sql_transaction(
LServer,
[["delete from users where username='", Username ,"';"],
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "');"]])
end.
@ -203,21 +203,25 @@ remove_user(User, Server, Password) ->
LUser ->
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
case catch
ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["begin;"
"select password from users where username='", Username, "';"
"delete from users "
"where username='", Username, "' and password='", Pass, "';"
"commit"]) of
{selected, ["password"], [{Password}]} ->
ejabberd_hooks:run(remove_user, jlib:nameprep(Server),
[User, Server]),
ok;
{selected, ["password"], []} ->
not_exists;
_ ->
not_allowed
end
LServer = jlib:nameprep(Server),
F = fun() ->
Result = ejabberd_odbc:sql_query_t(
["select password from users where username='",
Username, "';"]),
ejabberd_odbc:sql_query_t(["delete from users "
"where username='", Username,
"' and password='", Pass, "';"]),
case Result of
{selected, ["password"], [{Password}]} ->
ejabberd_hooks:run(remove_user, jlib:nameprep(Server),
[User, Server]),
ok;
{selected, ["password"], []} ->
not_exists;
_ ->
not_allowed
end
end,
{atomic, Result } = ejabberd_odbc:transaction(LServer, F),
Result
end.

View File

@ -56,7 +56,6 @@ process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) ->
[]}]}
end.
process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
case Type of
set ->
@ -99,7 +98,7 @@ get_last(IQ, SubEl, LUser, LServer) ->
case catch ejabberd_odbc:sql_query(
LServer,
["select seconds, state from last "
"where username='", Username, "'"]) of
"where username='", Username, "';"]) of
{'EXIT', _Reason} ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]};
{selected, ["seconds","state"], []} ->
@ -121,8 +120,6 @@ get_last(IQ, SubEl, LUser, LServer) ->
end
end.
on_presence_update(User, Server, _Resource, Status) ->
{MegaSecs, Secs, _MicroSecs} = now(),
TimeStamp = MegaSecs * 1000000 + Secs,
@ -134,20 +131,16 @@ store_last_info(User, Server, TimeStamp, Status) ->
Username = ejabberd_odbc:escape(LUser),
Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)),
State = ejabberd_odbc:escape(Status),
ejabberd_odbc:sql_query(
%% MREMOND: I think this should be turn into a non transactional behaviour
ejabberd_odbc:sql_transaction(
LServer,
["begin;"
"delete from last where username='", Username, "';"
"insert into last(username, seconds, state) "
"values ('", Username, "', '", Seconds, "', '", State, "');",
"commit"]).
[["delete from last where username='", Username, "';"],
["insert into last(username, seconds, state) "
"values ('", Username, "', '", Seconds, "', '", State, "');"]]).
remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
ejabberd_odbc:sql_query(
LServer,
["delete from last where username='", Username, "'"]).
ejabberd_odbc:sql_query(LServer,
["delete from last where username='", Username, "';"]).

View File

@ -5,7 +5,6 @@
%%% Created : 5 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
-module(mod_offline_odbc).
-author('alexey@sevcom.net').
@ -73,9 +72,9 @@ loop(Host) ->
XML,
"');"]
end, Msgs),
case catch ejabberd_odbc:sql_query(
case catch ejabberd_odbc:sql_transaction(
Host,
["begin; ", Query, " commit"]) of
Query) of
{'EXIT', Reason} ->
?ERROR_MSG("~p~n", [Reason]);
_ ->
@ -212,17 +211,16 @@ pop_offline_messages(Ls, User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
EUser = ejabberd_odbc:escape(LUser),
case ejabberd_odbc:sql_query(
LServer,
["begin;"
"select username, xml from spool where username='", EUser, "'"
" order by seq;"
"delete from spool where username='", EUser, "';"
"commit"]) of
[{updated, undefined},
{selected, ["username","xml"], Rs},
{updated, _},
{updated, undefined}] ->
F = fun() ->
Result = ejabberd_odbc:sql_query_t(
["select username, xml from spool where username='", EUser, "'"
" order by seq;"]),
ejabberd_odbc:sql_query_t(
["delete from spool where username='", EUser, "';"]),
Result
end,
case ejabberd_odbc:sql_transaction(LServer,F) of
{atomic, {selected, ["username","xml"], Rs}} ->
Ls ++ lists:flatmap(
fun({_, XML}) ->
case xml_stream:parse_element(XML) of
@ -253,5 +251,5 @@ remove_user(User, Server) ->
Username = ejabberd_odbc:escape(LUser),
ejabberd_odbc:sql_query(
LServer,
["delete from spool where username='", Username, "'"]).
["delete from spool where username='", Username, "';"]).

View File

@ -255,29 +255,35 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"
"delete from rostergroups "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "'"]);
" and jid='", SJID, "';"]);
_ ->
ItemVals = record_to_string(Item2),
ItemGroups = groups_to_string(Item2),
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"
"insert into rosterusers("
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" server, subscribe, type) "
" values ", ItemVals, ";"
"delete from rostergroups "
" values ", ItemVals, ";"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';",
[["insert into rostergroups("
" username, jid, grp) "
" values ", ItemGroup, ";"] ||
ItemGroup <- ItemGroups]])
" and jid='", SJID, "';"]),
lists:foreach(fun(ItemGroup) ->
ejabberd_odbc:sql_query_t(
["insert into rostergroups("
" username, jid, grp) "
" values ", ItemGroup, ";"])
end,
ItemGroups)
end,
{Item, Item2}
end,
@ -466,7 +472,7 @@ process_subscription(Direction, User, Server, JID1, Type) ->
["select username, jid, nick, subscription, ask, "
"server, subscribe, type from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "'"]) of
"and jid='", SJID, "';"]) of
{selected,
["username", "jid", "nick", "subscription", "ask",
"server", "subscribe", "type"],
@ -476,7 +482,7 @@ process_subscription(Direction, User, Server, JID1, Type) ->
case ejabberd_odbc:sql_query_t(
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SJID, "'"]) of
"and jid='", SJID, "';"]) of
{selected, ["grp"], JGrps} when is_list(JGrps) ->
[JGrp || {JGrp} <- JGrps];
_ ->
@ -518,12 +524,13 @@ process_subscription(Direction, User, Server, JID1, Type) ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"
"insert into rosterusers("
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" server, subscribe, type) "
" values ", ItemVals]),
" values ", ItemVals, ";"]),
{{push, NewItem}, AutoReply}
end
end,
@ -659,9 +666,10 @@ remove_user(User, Server) ->
fun() ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "';"
"delete from rostergroups "
" where username='", Username, "'"])
" where username='", Username, "';"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "';"])
end),
ok.
@ -671,13 +679,11 @@ set_items(User, Server, SubEl) ->
{xmlelement, _Name, _Attrs, Els} = SubEl,
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
catch ejabberd_odbc:sql_query(
catch ejabberd_odbc:transaction(
LServer,
["begin;",
lists:map(fun(El) ->
process_item_set_t(LUser, LServer, El)
end, Els),
"commit"]).
end, Els)).
process_item_set_t(LUser, LServer, {xmlelement, _Name, Attrs, Els}) ->
JID1 = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)),
@ -695,26 +701,26 @@ process_item_set_t(LUser, LServer, {xmlelement, _Name, Attrs, Els}) ->
Item2 = process_item_els(Item1, Els),
case Item2#roster.subscription of
remove ->
["delete from rosterusers "
[["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"
"delete from rostergroups "
" and jid='", SJID, "';"],
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"];
" and jid='", SJID, "';"]];
_ ->
ItemVals = record_to_string(Item1),
ItemGroups = groups_to_string(Item2),
["delete from rosterusers "
[["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"
"insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" server, subscribe, type) "
" values ", ItemVals, ";"
"delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';",
" and jid='", SJID, "';"],
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" server, subscribe, type) "
" values ", ItemVals, ";"],
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"],
[["insert into rostergroups("
" username, jid, grp) "
" values ", ItemGroup, ";"] ||

View File

@ -136,7 +136,7 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
case catch ejabberd_odbc:sql_query(
LServer,
["select vcard from vcard "
"where username='", Username, "'"]) of
"where username='", Username, "';"]) of
{selected, ["vcard"], [{SVCARD}]} ->
case xml_stream:parse_element(SVCARD) of
{error, _Reason} ->
@ -231,32 +231,30 @@ set_vcard(User, LServer, VCARD) ->
SOrgUnit = ejabberd_odbc:escape(OrgUnit),
SLOrgUnit = ejabberd_odbc:escape(LOrgUnit),
ejabberd_odbc:sql_query(
ejabberd_odbc:sql_transaction(
LServer,
["begin;"
"delete from vcard where username='", LUsername, "';"
"insert into vcard(username, vcard) "
"values ('", LUsername, "', '", SVCARD, "');"
"delete from vcard_search where lusername='", LUsername, "';"
"insert into vcard_search("
" username, lusername, fn, lfn, family, lfamily,"
" given, lgiven, middle, lmiddle, nickname, lnickname,"
" bday, lbday, ctry, lctry, locality, llocality,"
" email, lemail, orgname, lorgname, orgunit, lorgunit)"
"values (",
" '", Username, "', '", LUsername, "',"
" '", SFN, "', '", SLFN, "',"
" '", SFamily, "', '", SLFamily, "',"
" '", SGiven, "', '", SLGiven, "',"
" '", SMiddle, "', '", SLMiddle, "',"
" '", SNickname, "', '", SLNickname, "',"
" '", SBDay, "', '", SLBDay, "',"
" '", SCTRY, "', '", SLCTRY, "',"
" '", SLocality, "', '", SLLocality, "',"
" '", SEMail, "', '", SLEMail, "',"
" '", SOrgName, "', '", SLOrgName, "',"
" '", SOrgUnit, "', '", SLOrgUnit, "');"
"commit"])
[["delete from vcard where username='", LUsername, "';"],
["insert into vcard(username, vcard) "
"values ('", LUsername, "', '", SVCARD, "');"],
["delete from vcard_search where lusername='", LUsername, "';"],
["insert into vcard_search("
" username, lusername, fn, lfn, family, lfamily,"
" given, lgiven, middle, lmiddle, nickname, lnickname,"
" bday, lbday, ctry, lctry, locality, llocality,"
" email, lemail, orgname, lorgname, orgunit, lorgunit)"
"values (",
" '", Username, "', '", LUsername, "',"
" '", SFN, "', '", SLFN, "',"
" '", SFamily, "', '", SLFamily, "',"
" '", SGiven, "', '", SLGiven, "',"
" '", SMiddle, "', '", SLMiddle, "',"
" '", SNickname, "', '", SLNickname, "',"
" '", SBDay, "', '", SLBDay, "',"
" '", SCTRY, "', '", SLCTRY, "',"
" '", SLocality, "', '", SLLocality, "',"
" '", SEMail, "', '", SLEMail, "',"
" '", SOrgName, "', '", SLOrgName, "',"
" '", SOrgUnit, "', '", SLOrgUnit, "');"]])
end.
-define(TLFIELD(Type, Label, Var),
@ -291,9 +289,6 @@ set_vcard(User, LServer, VCARD) ->
?TLFIELD("text-single", "Organization Unit", "orgunit")
]}]).
do_route(ServerHost, From, To, Packet) ->
#jid{user = User, resource = Resource} = To,
if
@ -514,7 +509,7 @@ search(LServer, Data) ->
["select username, fn, family, given, middle, "
" nickname, bday, ctry, locality, "
" email, orgname, orgunit from vcard_search ",
MatchSpec, Limit]) of
MatchSpec, Limit, ";"]) of
{selected, ["username", "fn", "family", "given", "middle",
"nickname", "bday", "ctry", "locality",
"email", "orgname", "orgunit"],
@ -660,11 +655,9 @@ remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
ejabberd_odbc:sql_query(
ejabberd_odbc:sql_transaction(
LServer,
["begin;"
"delete from vcard where username='", Username, "';"
"delete from vcard_search where lusername='", Username, "';"
"commit"]).
[["delete from vcard where username='", Username, "';"],
["delete from vcard_search where lusername='", Username, "';"]]).

View File

@ -45,10 +45,22 @@ sql_query(Host, Query) ->
gen_server:call(ejabberd_odbc_sup:get_random_pid(Host),
{sql_query, Query}, 60000).
%% SQL transaction based on a list of queries
%% This function automatically
sql_transaction(Host, Queries) when is_list(Queries) ->
F = fun() ->
lists:foreach(fun(Query) ->
R = sql_query(Host, Query)
end,
Queries)
end,
sql_transaction(Host, F);
%% SQL transaction, based on a erlang anonymous function (F = fun)
sql_transaction(Host, F) ->
gen_server:call(ejabberd_odbc_sup:get_random_pid(Host),
{sql_transaction, F}, 60000).
%% This function is intended to be used from inside an sql_transaction:
sql_query_t(Query) ->
State = get(?STATE_KEY),
QRes = sql_query_internal(State, Query),
@ -106,7 +118,7 @@ init([Host]) ->
_ when is_list(SQLServer) ->
{ok, Ref} = odbc:connect(SQLServer,
[{scrollable_cursors, off}]),
{ok, #state{db_ref = Ref,
{ok, #state{db_ref = Ref,
db_type = odbc}}
end.
@ -177,15 +189,15 @@ execute_transaction(_State, _F, 0) ->
{aborted, restarts_exceeded};
execute_transaction(State, F, NRestarts) ->
put(?STATE_KEY, State),
sql_query_internal(State, "begin"),
sql_query_internal(State, "begin;"),
case catch F() of
aborted ->
execute_transaction(State, F, NRestarts - 1);
{'EXIT', Reason} ->
sql_query_internal(State, "rollback"),
sql_query_internal(State, "rollback;"),
{aborted, Reason};
Res ->
sql_query_internal(State, "commit"),
sql_query_internal(State, "commit;"),
{atomic, Res}
end.