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

Add virtual host support for SQLite

This commit is contained in:
Evgeniy Khramtsov 2015-04-08 15:31:28 +03:00
parent fb0e82f743
commit 9b4942890d
5 changed files with 71 additions and 50 deletions

View File

@ -33,10 +33,6 @@
-define(SQL_DIR, filename:join(["priv", "sql"])).
-define(SQLITE_DB, ejabberd_sqlite).
-define(DEFAULT_SQLITE_DB_PATH, <<"/tmp/ejabberd.db">>).
-define(CONFIG_PATH, <<"ejabberd.cfg">>).
-define(LOG_PATH, <<"ejabberd.log">>).

View File

@ -40,6 +40,8 @@
escape/1,
escape_like/1,
to_bool/1,
sqlite_db/1,
sqlite_file/1,
encode_term/1,
decode_term/1,
keep_alive/1]).
@ -199,6 +201,22 @@ decode_term(Bin) ->
{ok, Term} = erl_parse:parse_term(Tokens),
Term.
-spec sqlite_db(binary()) -> atom().
sqlite_db(Host) ->
list_to_atom("ejabberd_sqlite_" ++ binary_to_list(Host)).
-spec sqlite_file(binary()) -> string().
sqlite_file(Host) ->
case ejabberd_config:get_option({odbc_database, Host},
fun iolist_to_binary/1) of
undefined ->
{ok, Cwd} = file:get_cwd(),
filename:join([Cwd, "sqlite", atom_to_list(node()),
binary_to_list(Host), "ejabberd.db"]);
File ->
binary_to_list(File)
end.
%%%----------------------------------------------------------------------
%%% Callback functions from gen_fsm
%%%----------------------------------------------------------------------
@ -329,7 +347,7 @@ terminate(_Reason, _StateName, State) ->
ejabberd_odbc_sup:remove_pid(State#state.host, self()),
case State#state.db_type of
mysql -> catch p1_mysql_conn:stop(State#state.db_ref);
sqlite -> catch sqlite3:close(?SQLITE_DB);
sqlite -> catch sqlite3:close(sqlite_db(State#state.host));
_ -> ok
end,
ok.
@ -460,7 +478,8 @@ sql_query_internal(Query) ->
%% ?INFO_MSG("MySQL, Received result~n~p~n", [R]),
R;
sqlite ->
sqlite_to_odbc(sqlite3:sql_exec(?SQLITE_DB, Query))
Host = State#state.host,
sqlite_to_odbc(Host, sqlite3:sql_exec(sqlite_db(Host), Query))
end,
case Res of
{error, <<"No SQL-driver information available.">>} ->
@ -497,23 +516,30 @@ odbc_connect(SQLServer) ->
%% part of init/1
%% Open a database connection to SQLite
sqlite_connect(DB) ->
case sqlite3:open(?SQLITE_DB, [{file, binary_to_list(DB)}]) of
sqlite_connect(Host) ->
File = sqlite_file(Host),
case filelib:ensure_dir(File) of
ok ->
case sqlite3:open(sqlite_db(Host), [{file, File}]) of
{ok, Ref} ->
sqlite3:sql_exec(?SQLITE_DB, "pragma foreign_keys = on"),
sqlite3:sql_exec(
sqlite_db(Host), "pragma foreign_keys = on"),
{ok, Ref};
{error, {already_started, Ref}} ->
{ok, Ref};
{error, Reason} ->
{error, Reason}
end;
Err ->
Err
end.
%% Convert SQLite query result to Erlang ODBC result formalism
sqlite_to_odbc(ok) ->
{updated, sqlite3:changes(?SQLITE_DB)};
sqlite_to_odbc({rowid, _}) ->
{updated, sqlite3:changes(?SQLITE_DB)};
sqlite_to_odbc([{columns, Columns}, {rows, TRows}]) ->
sqlite_to_odbc(Host, ok) ->
{updated, sqlite3:changes(sqlite_db(Host))};
sqlite_to_odbc(Host, {rowid, _}) ->
{updated, sqlite3:changes(sqlite_db(Host))};
sqlite_to_odbc(_Host, [{columns, Columns}, {rows, TRows}]) ->
Rows = [lists:map(
fun(I) when is_integer(I) ->
jlib:integer_to_binary(I);
@ -521,9 +547,9 @@ sqlite_to_odbc([{columns, Columns}, {rows, TRows}]) ->
B
end, tuple_to_list(Row)) || Row <- TRows],
{selected, [list_to_binary(C) || C <- Columns], Rows};
sqlite_to_odbc({error, _Code, Reason}) ->
sqlite_to_odbc(_Host, {error, _Code, Reason}) ->
{error, Reason};
sqlite_to_odbc(_) ->
sqlite_to_odbc(_Host, _) ->
{updated, undefined}.
%% == Native PostgreSQL code
@ -633,10 +659,7 @@ db_opts(Host) ->
odbc ->
[odbc, Server];
sqlite ->
DB = ejabberd_config:get_option({odbc_database, Host},
fun iolist_to_binary/1,
?DEFAULT_SQLITE_DB_PATH),
[sqlite, DB];
[sqlite, Host];
_ ->
Port = ejabberd_config:get_option(
{odbc_port, Host},

View File

@ -75,10 +75,7 @@ init([Host]) ->
end, odbc),
case Type of
sqlite ->
DB = ejabberd_config:get_option({odbc_database, Host},
fun iolist_to_binary/1,
?DEFAULT_SQLITE_DB_PATH),
check_sqlite_db(DB);
check_sqlite_db(Host);
_ ->
ok
end,
@ -134,19 +131,26 @@ transform_options({odbc_server, {sqlite, DB}}, Opts) ->
transform_options(Opt, Opts) ->
[Opt|Opts].
check_sqlite_db(DB) ->
Ret = case sqlite3:open(?SQLITE_DB, [{file, binary_to_list(DB)}]) of
check_sqlite_db(Host) ->
DB = ejabberd_odbc:sqlite_db(Host),
File = ejabberd_odbc:sqlite_file(Host),
Ret = case filelib:ensure_dir(File) of
ok ->
case sqlite3:open(DB, [{file, File}]) of
{ok, _Ref} -> ok;
{error, {already_started, _Ref}} -> ok;
{error, R} -> {error, R}
end;
Err ->
Err
end,
case Ret of
ok ->
sqlite3:sql_exec(?SQLITE_DB, "pragma foreign_keys = on"),
case sqlite3:list_tables(?SQLITE_DB) of
sqlite3:sql_exec(DB, "pragma foreign_keys = on"),
case sqlite3:list_tables(DB) of
[] ->
create_sqlite_tables(),
sqlite3:close(?SQLITE_DB),
create_sqlite_tables(DB),
sqlite3:close(DB),
ok;
[_H | _] ->
ok
@ -155,7 +159,7 @@ check_sqlite_db(DB) ->
?INFO_MSG("Failed open sqlite database, reason ~p", [Reason])
end.
create_sqlite_tables() ->
create_sqlite_tables(DB) ->
SqlDir = case code:priv_dir(ejabberd) of
{error, _} ->
?SQL_DIR;
@ -166,12 +170,12 @@ create_sqlite_tables() ->
case file:open(File, [read, binary]) of
{ok, Fd} ->
Qs = read_lines(Fd, File, []),
ok = sqlite3:sql_exec(?SQLITE_DB, "begin"),
[ok = sqlite3:sql_exec(?SQLITE_DB, Q) || Q <- Qs],
ok = sqlite3:sql_exec(?SQLITE_DB, "commit");
ok = sqlite3:sql_exec(DB, "begin"),
[ok = sqlite3:sql_exec(DB, Q) || Q <- Qs],
ok = sqlite3:sql_exec(DB, "commit");
{error, Reason} ->
?INFO_MSG("Not found sqlite database schema, reason: ~p", [Reason]),
ok
?INFO_MSG("Failed to read SQLite schema file: ~s",
[file:format_error(Reason)])
end.
read_lines(Fd, File, Acc) ->

View File

@ -35,7 +35,6 @@ init_per_suite(Config) ->
LDIFFile = filename:join([DataDir, "ejabberd.ldif"]),
{ok, _} = file:copy(ExtAuthScript, filename:join([CWD, "extauth.py"])),
{ok, _} = ldap_srv:start(LDIFFile),
file:delete("/tmp/ejabberd_test.db"),
ok = application:start(ejabberd),
NewConfig.

View File

@ -57,7 +57,6 @@ Welcome to this XMPP server."
mod_version: []
"sqlite.localhost":
odbc_type: sqlite
odbc_database: "/tmp/ejabberd_test.db"
auth_method: odbc
modules:
mod_announce: