Native MySQL support. The Erlang MySQL module is needed:

http://support.process-one.net/doc/display/CONTRIBS/Yxa

SVN Revision: 482
This commit is contained in:
Mickaël Rémond 2006-01-02 17:39:04 +00:00
parent 7ee3e45df1
commit 8401a5ac55
3 changed files with 79 additions and 23 deletions

View File

@ -1,3 +1,7 @@
2006-01-02 Mickael Remond <mickael.remond@process-one.net>
* src/odbc/ejabberd_odbc.erl: Native MySQL support
2005-12-24 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_logger_h.erl: Speed optimizations

View File

@ -49,7 +49,7 @@ check_password(User, Server, Password) ->
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "'"]) of
"where username='", Username, "';"]) of
{selected, ["password"], [{Password}]} ->
true;
_ ->
@ -66,7 +66,7 @@ check_password(User, Server, Password, StreamID, Digest) ->
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "'"]) of
"where username='", Username, "';"]) of
{selected, ["password"], [{Passwd}]} ->
DigRes = if
Digest /= "" ->
@ -110,7 +110,7 @@ try_register(User, Server, Password) ->
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "')"]) of
"values ('", Username, "', '", Pass, "');"]) of
{updated, 1} ->
{atomic, ok};
_ ->
@ -141,7 +141,7 @@ get_password(User, Server) ->
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "'"]) of
"where username='", Username, "';"]) of
{selected, ["password"], [{Password}]} ->
Password;
_ ->
@ -158,7 +158,7 @@ get_password_s(User, Server) ->
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "'"]) of
"where username='", Username, "';"]) of
{selected, ["password"], [{Password}]} ->
Password;
_ ->
@ -175,7 +175,7 @@ is_user_exists(User, Server) ->
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "'"]) of
"where username='", Username, "';"]) of
{selected, ["password"], [{_Password}]} ->
true;
_ ->
@ -191,7 +191,7 @@ remove_user(User, Server) ->
Username = ejabberd_odbc:escape(LUser),
catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["delete from users where username='", Username ,"'"]),
["delete from users where username='", Username ,"';"]),
ejabberd_hooks:run(remove_user, jlib:nameprep(Server),
[User, Server])
end.

View File

@ -33,6 +33,7 @@
-define(STATE_KEY, ejabberd_odbc_state).
-define(MAX_TRANSACTION_RESTARTS, 10).
-define(MYSQL_PORT, 3306).
%%%----------------------------------------------------------------------
%%% API
@ -114,24 +115,14 @@ init([Host]) ->
SQLServer = ejabberd_config:get_local_option({odbc_server, Host}),
case SQLServer of
{pgsql, Server, DB, Username, Password} ->
case pgsql:connect(Server, DB, Username, Password) of
{ok, Ref} ->
{ok, #state{db_ref = Ref, db_type = pgsql}};
{error, Reason} ->
?ERROR_MSG("PostgreSQL connection failed: ~p~n", [Reason]),
{stop, pgsql_connection_failed}
end;
pgsql_connect(Server, DB, Username, Password);
{mysql, Server, DB, Username, Password} ->
mysql_connect(Server, DB, Username, Password);
_ when is_list(SQLServer) ->
case odbc:connect(SQLServer,[{scrollable_cursors, off}]) of
{ok, Ref} ->
{ok, #state{db_ref = Ref, db_type = odbc}};
{error, Reason} ->
?ERROR_MSG("ODBC connection (~s) failed: ~p~n",
[SQLServer, Reason]),
{stop, odbc_connection_failed}
end
odbc_connect(SQLServer)
end.
%%----------------------------------------------------------------------
%% Func: handle_call/3
%% Returns: {reply, Reply, State} |
@ -192,7 +183,9 @@ sql_query_internal(State, Query) ->
odbc ->
odbc:sql_query(State#state.db_ref, Query);
pgsql ->
pgsql_to_odbc(pgsql:squery(State#state.db_ref, Query))
pgsql_to_odbc(pgsql:squery(State#state.db_ref, Query));
mysql ->
mysql_to_odbc(mysql_conn:fetch(State#state.db_ref, Query, self()))
end.
execute_transaction(_State, _F, 0) ->
@ -211,6 +204,35 @@ execute_transaction(State, F, NRestarts) ->
{atomic, Res}
end.
%% == pure ODBC code
%% part of init/1
%% Open an ODBC database connection
odbc_connect(SQLServer) ->
case odbc:connect(SQLServer,[{scrollable_cursors, off}]) of
{ok, Ref} ->
{ok, #state{db_ref = Ref, db_type = odbc}};
{error, Reason} ->
?ERROR_MSG("ODBC connection (~s) failed: ~p~n",
[SQLServer, Reason]),
{stop, odbc_connection_failed}
end.
%% == Native PostgreSQL code
%% part of init/1
%% Open a database connection to PostgreSQL
pgsql_connect(Server, DB, Username, Password) ->
case pgsql:connect(Server, DB, Username, Password) of
{ok, Ref} ->
{ok, #state{db_ref = Ref, db_type = pgsql}};
{error, Reason} ->
?ERROR_MSG("PostgreSQL connection failed: ~p~n", [Reason]),
{stop, pgsql_connection_failed}
end.
%% Convert PostgreSQL query result to Erlang ODBC result formalism
pgsql_to_odbc({ok, PGSQLResult}) ->
case PGSQLResult of
[Item] ->
@ -233,3 +255,33 @@ pgsql_item_to_odbc({error, Error}) ->
pgsql_item_to_odbc(_) ->
{updated,undefined}.
%% == Native MySQL code
%% part of init/1
%% Open a database connection to MySQL
mysql_connect(Server, DB, Username, Password) ->
NoLogFun = fun(_Level,_Format,_Argument) -> ok end,
case mysql_conn:start(Server, ?MYSQL_PORT, Username, Password, DB, NoLogFun) of
{ok, Ref} ->
{ok, #state{db_ref = Ref, db_type = mysql}};
{error, Reason} ->
?ERROR_MSG("MySQL connection failed: ~p~n", [Reason]),
{stop, mysql_connection_failed}
end.
%% Convert MySQL query result to Erlang ODBC result formalism
mysql_to_odbc({updated, MySQLRes}) ->
{updated, mysql:get_result_affected_rows(MySQLRes)};
mysql_to_odbc({data, MySQLRes}) ->
mysql_item_to_odbc(mysql:get_result_field_info(MySQLRes),
mysql:get_result_rows(MySQLRes));
mysql_to_odbc({error, MySQLRes}) ->
{error, mysql:get_result_reason(MySQLRes)}.
%% When tabular data is returned, convert it to the ODBC formalism
mysql_item_to_odbc(Columns, Recs) ->
%% For now, there is a bug and we do not get the correct value from MySQL
%% module:
{selected,
[element(2, Column) || Column <- Columns],
[list_to_tuple(Rec) || Rec <- Recs]}.