mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-20 16:15:59 +01:00
commit
5a820aca40
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,6 +4,8 @@
|
||||
*~
|
||||
\#*#
|
||||
.#*
|
||||
.edts
|
||||
*.dump
|
||||
/Makefile
|
||||
/config.log
|
||||
/config.status
|
||||
@ -38,3 +40,4 @@ XmppAddr.hrl
|
||||
/dialyzer/
|
||||
/test/*.beam
|
||||
/logs/
|
||||
/priv/sql
|
||||
|
@ -11,7 +11,7 @@ before_install:
|
||||
- sudo apt-get -qq update
|
||||
|
||||
install:
|
||||
- sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev
|
||||
- sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev libsqlite3-dev
|
||||
|
||||
before_script:
|
||||
- mysql -u root -e "CREATE USER 'ejabberd_test'@'localhost' IDENTIFIED BY 'ejabberd_test';"
|
||||
|
11
Makefile.in
11
Makefile.in
@ -43,6 +43,9 @@ SODIR = $(PRIVDIR)/lib
|
||||
# /usr/lib/ejabberd/priv/msgs
|
||||
MSGSDIR = $(PRIVDIR)/msgs
|
||||
|
||||
# /usr/lib/ejabberd/priv/sql
|
||||
SQLDIR = $(PRIVDIR)/sql
|
||||
|
||||
# /var/lib/ejabberd/
|
||||
SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
|
||||
|
||||
@ -176,11 +179,16 @@ install: all
|
||||
$(INSTALL) -d $(SODIR)
|
||||
$(INSTALL) -m 644 $(DLLs) $(SODIR)
|
||||
-[ -f $(SODIR)/jiffy.so ] && (cd $(PRIVDIR); ln -s lib/jiffy.so; true)
|
||||
-[ -f $(SODIR)/sqlite3_drv.so ] && (cd $(PRIVDIR); ln -s lib/sqlite3_drv.so; true)
|
||||
#
|
||||
# Translated strings
|
||||
$(INSTALL) -d $(MSGSDIR)
|
||||
$(INSTALL) -m 644 priv/msgs/*.msg $(MSGSDIR)
|
||||
#
|
||||
# Copy lite.sql
|
||||
-[ -d deps/sqlite3 ] && $(INSTALL) -d $(SQLDIR)
|
||||
-[ -d deps/sqlite3 ] && $(INSTALL) -m 644 sql/lite.sql $(SQLDIR)
|
||||
#
|
||||
# Spool directory
|
||||
$(INSTALL) -d -m 750 $(O_USER) $(SPOOLDIR)
|
||||
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT)
|
||||
@ -229,6 +237,8 @@ uninstall-binary:
|
||||
rm -fr $(SODIR)
|
||||
rm -f $(MSGSDIR)/*.msgs
|
||||
rm -fr $(MSGSDIR)
|
||||
rm -f $(SQLDIR)/*.sql
|
||||
rm -fr $(SQLDIR)
|
||||
rm -fr $(PRIVDIR)
|
||||
rm -fr $(EJABBERDDIR)
|
||||
|
||||
@ -310,6 +320,7 @@ test:
|
||||
@echo "************************** NOTICE ***************************************"
|
||||
@cat test/README
|
||||
@echo "*************************************************************************"
|
||||
@cd priv && ln -sf ../sql
|
||||
$(REBAR) skip_deps=true ct
|
||||
|
||||
quicktest:
|
||||
|
15
configure.ac
15
configure.ac
@ -106,10 +106,10 @@ AC_ARG_ENABLE(mssql,
|
||||
esac],[db_type=generic])
|
||||
|
||||
AC_ARG_ENABLE(all,
|
||||
[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-pam --enable-zlib --enable-riak --enable-redis --enable-json --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])],
|
||||
[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-json --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) nif=true odbc=true mysql=true pgsql=true pam=true zlib=true riak=true redis=true json=true elixir=true iconv=true debug=true lager=true tools=true ;;
|
||||
no) nif=false odbc=false mysql=false pgsql=false pam=false zlib=false riak=false redis=false json=false elixir=false iconv=false debug=false lager=false tools=false ;;
|
||||
yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true json=true elixir=true iconv=true debug=true lager=true tools=true ;;
|
||||
no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false json=false elixir=false iconv=false debug=false lager=false tools=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;;
|
||||
esac],[])
|
||||
|
||||
@ -153,6 +153,14 @@ AC_ARG_ENABLE(pgsql,
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-pgsql) ;;
|
||||
esac],[if test "x$pgsql" = "x"; then pgsql=false; fi])
|
||||
|
||||
AC_ARG_ENABLE(sqlite,
|
||||
[AC_HELP_STRING([--enable-sqlite], [enable SQLite support (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) sqlite=true ;;
|
||||
no) sqlite=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-sqlite) ;;
|
||||
esac],[if test "x$sqlite" = "x"; then sqlite=false; fi])
|
||||
|
||||
AC_ARG_ENABLE(pam,
|
||||
[AC_HELP_STRING([--enable-pam], [enable PAM support (default: no)])],
|
||||
[case "${enableval}" in
|
||||
@ -254,6 +262,7 @@ AC_SUBST(db_type)
|
||||
AC_SUBST(odbc)
|
||||
AC_SUBST(mysql)
|
||||
AC_SUBST(pgsql)
|
||||
AC_SUBST(sqlite)
|
||||
AC_SUBST(pam)
|
||||
AC_SUBST(zlib)
|
||||
AC_SUBST(riak)
|
||||
|
@ -343,6 +343,12 @@ auth_method: internal
|
||||
##
|
||||
## pgsql_users_number_estimate: true
|
||||
|
||||
##
|
||||
## SQLite:
|
||||
##
|
||||
## odbc_type: sqlite
|
||||
## odbc_database: "/path/to/database.db"
|
||||
|
||||
##
|
||||
## ODBC compatible or MSSQL server:
|
||||
##
|
||||
|
@ -31,6 +31,12 @@
|
||||
|
||||
-define(MSGS_DIR, filename:join(["priv", "msgs"])).
|
||||
|
||||
-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">>).
|
||||
|
@ -90,6 +90,8 @@ CfgDeps = lists:flatmap(
|
||||
[{p1_mysql, ".*", {git, "git://github.com/processone/mysql"}}];
|
||||
({pgsql, true}) ->
|
||||
[{p1_pgsql, ".*", {git, "git://github.com/processone/pgsql"}}];
|
||||
({sqlite, true}) ->
|
||||
[{sqlite3, ".*", {git, "git://github.com/alexeyr/erlang-sqlite3"}}];
|
||||
({pam, true}) ->
|
||||
[{p1_pam, ".*", {git, "git://github.com/processone/epam"}}];
|
||||
({zlib, true}) ->
|
||||
|
272
sql/lite.sql
Normal file
272
sql/lite.sql
Normal file
@ -0,0 +1,272 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2015 ProcessOne
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU General Public License as
|
||||
-- published by the Free Software Foundation; either version 2 of the
|
||||
-- License, or (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License along
|
||||
-- with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
--
|
||||
|
||||
CREATE TABLE users (
|
||||
username text PRIMARY KEY,
|
||||
password text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE last (
|
||||
username text PRIMARY KEY,
|
||||
seconds text NOT NULL,
|
||||
state text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE rosterusers (
|
||||
username text NOT NULL,
|
||||
jid text NOT NULL,
|
||||
nick text NOT NULL,
|
||||
subscription character(1) NOT NULL,
|
||||
ask character(1) NOT NULL,
|
||||
askmessage text NOT NULL,
|
||||
server character(1) NOT NULL,
|
||||
subscribe text,
|
||||
type text,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX i_rosteru_user_jid ON rosterusers (username, jid);
|
||||
CREATE INDEX i_rosteru_username ON rosterusers (username);
|
||||
CREATE INDEX i_rosteru_jid ON rosterusers (jid);
|
||||
|
||||
|
||||
CREATE TABLE rostergroups (
|
||||
username text NOT NULL,
|
||||
jid text NOT NULL,
|
||||
grp text NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX pk_rosterg_user_jid ON rostergroups (username, jid);
|
||||
|
||||
CREATE TABLE sr_group (
|
||||
name text NOT NULL,
|
||||
opts text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE sr_user (
|
||||
jid text NOT NULL,
|
||||
grp text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX i_sr_user_jid_grp ON sr_user (jid, grp);
|
||||
CREATE INDEX i_sr_user_jid ON sr_user (jid);
|
||||
CREATE INDEX i_sr_user_grp ON sr_user (grp);
|
||||
|
||||
CREATE TABLE spool (
|
||||
username text NOT NULL,
|
||||
xml text NOT NULL,
|
||||
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_despool ON spool (username);
|
||||
|
||||
|
||||
CREATE TABLE vcard (
|
||||
username text PRIMARY KEY,
|
||||
vcard text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE vcard_xupdate (
|
||||
username text PRIMARY KEY,
|
||||
hash text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE vcard_search (
|
||||
username text NOT NULL,
|
||||
lusername text PRIMARY KEY,
|
||||
fn text NOT NULL,
|
||||
lfn text NOT NULL,
|
||||
family text NOT NULL,
|
||||
lfamily text NOT NULL,
|
||||
given text NOT NULL,
|
||||
lgiven text NOT NULL,
|
||||
middle text NOT NULL,
|
||||
lmiddle text NOT NULL,
|
||||
nickname text NOT NULL,
|
||||
lnickname text NOT NULL,
|
||||
bday text NOT NULL,
|
||||
lbday text NOT NULL,
|
||||
ctry text NOT NULL,
|
||||
lctry text NOT NULL,
|
||||
locality text NOT NULL,
|
||||
llocality text NOT NULL,
|
||||
email text NOT NULL,
|
||||
lemail text NOT NULL,
|
||||
orgname text NOT NULL,
|
||||
lorgname text NOT NULL,
|
||||
orgunit text NOT NULL,
|
||||
lorgunit text NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn);
|
||||
CREATE INDEX i_vcard_search_lfamily ON vcard_search(lfamily);
|
||||
CREATE INDEX i_vcard_search_lgiven ON vcard_search(lgiven);
|
||||
CREATE INDEX i_vcard_search_lmiddle ON vcard_search(lmiddle);
|
||||
CREATE INDEX i_vcard_search_lnickname ON vcard_search(lnickname);
|
||||
CREATE INDEX i_vcard_search_lbday ON vcard_search(lbday);
|
||||
CREATE INDEX i_vcard_search_lctry ON vcard_search(lctry);
|
||||
CREATE INDEX i_vcard_search_llocality ON vcard_search(llocality);
|
||||
CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail);
|
||||
CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname);
|
||||
CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
|
||||
|
||||
CREATE TABLE privacy_default_list (
|
||||
username text PRIMARY KEY,
|
||||
name text NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE privacy_list (
|
||||
username text NOT NULL,
|
||||
name text NOT NULL,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_privacy_list_username ON privacy_list (username);
|
||||
CREATE UNIQUE INDEX i_privacy_list_username_name ON privacy_list (username, name);
|
||||
|
||||
CREATE TABLE privacy_list_data (
|
||||
id bigint REFERENCES privacy_list(id) ON DELETE CASCADE,
|
||||
t character(1) NOT NULL,
|
||||
value text NOT NULL,
|
||||
action character(1) NOT NULL,
|
||||
ord NUMERIC NOT NULL,
|
||||
match_all boolean NOT NULL,
|
||||
match_iq boolean NOT NULL,
|
||||
match_message boolean NOT NULL,
|
||||
match_presence_in boolean NOT NULL,
|
||||
match_presence_out boolean NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE private_storage (
|
||||
username text NOT NULL,
|
||||
namespace text NOT NULL,
|
||||
data text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_private_storage_username ON private_storage (username);
|
||||
CREATE UNIQUE INDEX i_private_storage_username_namespace ON private_storage (username, namespace);
|
||||
|
||||
|
||||
CREATE TABLE roster_version (
|
||||
username text PRIMARY KEY,
|
||||
version text NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE pubsub_node (
|
||||
host text,
|
||||
node text,
|
||||
parent text,
|
||||
type text,
|
||||
nodeid INTEGER PRIMARY KEY AUTOINCREMENT
|
||||
);
|
||||
CREATE INDEX i_pubsub_node_parent ON pubsub_node (parent);
|
||||
CREATE UNIQUE INDEX i_pubsub_node_tuple ON pubsub_node (host, node);
|
||||
|
||||
CREATE TABLE pubsub_node_option (
|
||||
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
|
||||
name text,
|
||||
val text
|
||||
);
|
||||
CREATE INDEX i_pubsub_node_option_nodeid ON pubsub_node_option (nodeid);
|
||||
|
||||
CREATE TABLE pubsub_node_owner (
|
||||
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
|
||||
owner text
|
||||
);
|
||||
CREATE INDEX i_pubsub_node_owner_nodeid ON pubsub_node_owner (nodeid);
|
||||
|
||||
CREATE TABLE pubsub_state (
|
||||
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
|
||||
jid text,
|
||||
affiliation character(1),
|
||||
subscriptions text,
|
||||
stateid INTEGER PRIMARY KEY AUTOINCREMENT
|
||||
);
|
||||
CREATE INDEX i_pubsub_state_jid ON pubsub_state (jid);
|
||||
CREATE UNIQUE INDEX i_pubsub_state_tuple ON pubsub_state (nodeid, jid);
|
||||
|
||||
CREATE TABLE pubsub_item (
|
||||
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
|
||||
itemid text,
|
||||
publisher text,
|
||||
creation text,
|
||||
modification text,
|
||||
payload text
|
||||
);
|
||||
CREATE INDEX i_pubsub_item_itemid ON pubsub_item (itemid);
|
||||
CREATE UNIQUE INDEX i_pubsub_item_tuple ON pubsub_item (nodeid, itemid);
|
||||
|
||||
CREATE TABLE pubsub_subscription_opt (
|
||||
subid text,
|
||||
opt_name varchar(32),
|
||||
opt_value text
|
||||
);
|
||||
CREATE UNIQUE INDEX i_pubsub_subscription_opt ON pubsub_subscription_opt (subid, opt_name);
|
||||
|
||||
CREATE TABLE muc_room (
|
||||
name text NOT NULL,
|
||||
host text NOT NULL,
|
||||
opts text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room (name, host);
|
||||
|
||||
CREATE TABLE muc_registered (
|
||||
jid text NOT NULL,
|
||||
host text NOT NULL,
|
||||
nick text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_muc_registered_nick ON muc_registered (nick);
|
||||
CREATE UNIQUE INDEX i_muc_registered_jid_host ON muc_registered (jid, host);
|
||||
|
||||
CREATE TABLE irc_custom (
|
||||
jid text NOT NULL,
|
||||
host text NOT NULL,
|
||||
data text NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX i_irc_custom_jid_host ON irc_custom (jid, host);
|
||||
|
||||
CREATE TABLE motd (
|
||||
username text PRIMARY KEY,
|
||||
xml text,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE caps_features (
|
||||
node text NOT NULL,
|
||||
subnode text NOT NULL,
|
||||
feature text,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX i_caps_features_node_subnode ON caps_features (node, subnode);
|
@ -58,7 +58,7 @@
|
||||
|
||||
-record(state,
|
||||
{db_ref = self() :: pid(),
|
||||
db_type = odbc :: pgsql | mysql | odbc,
|
||||
db_type = odbc :: pgsql | mysql | sqlite | odbc,
|
||||
start_interval = 0 :: non_neg_integer(),
|
||||
host = <<"">> :: binary(),
|
||||
max_pending_requests_len :: non_neg_integer(),
|
||||
@ -224,7 +224,8 @@ init([Host, StartInterval]) ->
|
||||
connecting(connect, #state{host = Host} = State) ->
|
||||
ConnectRes = case db_opts(Host) of
|
||||
[mysql | Args] -> apply(fun mysql_connect/5, Args);
|
||||
[pgsql | Args] -> apply(fun pgsql_connect/5, Args);
|
||||
[pgsql | Args] -> apply(fun pgsql_connect/5, Args);
|
||||
[sqlite | Args] -> apply(fun sqlite_connect/1, Args);
|
||||
[odbc | Args] -> apply(fun odbc_connect/1, Args)
|
||||
end,
|
||||
{_, PendingRequests} = State#state.pending_requests,
|
||||
@ -327,8 +328,9 @@ handle_info(Info, StateName, State) ->
|
||||
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);
|
||||
_ -> ok
|
||||
mysql -> catch p1_mysql_conn:stop(State#state.db_ref);
|
||||
sqlite -> catch sqlite3:close(?SQLITE_DB);
|
||||
_ -> ok
|
||||
end,
|
||||
ok.
|
||||
|
||||
@ -456,7 +458,9 @@ sql_query_internal(Query) ->
|
||||
[{timeout, (?TRANSACTION_TIMEOUT) - 1000},
|
||||
{result_type, binary}])),
|
||||
%% ?INFO_MSG("MySQL, Received result~n~p~n", [R]),
|
||||
R
|
||||
R;
|
||||
sqlite ->
|
||||
sqlite_to_odbc(sqlite3:sql_exec(?SQLITE_DB, Query))
|
||||
end,
|
||||
case Res of
|
||||
{error, <<"No SQL-driver information available.">>} ->
|
||||
@ -488,6 +492,34 @@ odbc_connect(SQLServer) ->
|
||||
ejabberd:start_app(odbc),
|
||||
odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off}]).
|
||||
|
||||
%% == Native SQLite code
|
||||
|
||||
%% part of init/1
|
||||
%% Open a database connection to SQLite
|
||||
|
||||
sqlite_connect(DB) ->
|
||||
process_flag(trap_exit, true),
|
||||
case sqlite3:open(?SQLITE_DB, [{file, binary_to_list(DB)}]) of
|
||||
{ok, Ref} ->
|
||||
{ok, Ref};
|
||||
{error, {already_started, Ref}} ->
|
||||
{ok, Ref};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
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, Rows}]) ->
|
||||
{selected, [list_to_binary(C) || C <- Columns], [tuple_to_list(Row) || Row <- Rows]};
|
||||
sqlite_to_odbc({error, _Code, Reason}) ->
|
||||
{error, Reason};
|
||||
sqlite_to_odbc(_) ->
|
||||
{updated, undefined}.
|
||||
|
||||
%% == Native PostgreSQL code
|
||||
|
||||
%% part of init/1
|
||||
@ -585,6 +617,7 @@ db_opts(Host) ->
|
||||
Type = ejabberd_config:get_option({odbc_type, Host},
|
||||
fun(mysql) -> mysql;
|
||||
(pgsql) -> pgsql;
|
||||
(sqlite) -> sqlite;
|
||||
(odbc) -> odbc
|
||||
end, odbc),
|
||||
Server = ejabberd_config:get_option({odbc_server, Host},
|
||||
@ -593,6 +626,11 @@ db_opts(Host) ->
|
||||
case Type of
|
||||
odbc ->
|
||||
[odbc, Server];
|
||||
sqlite ->
|
||||
DB = ejabberd_config:get_option({odbc_database, Host},
|
||||
fun iolist_to_binary/1,
|
||||
?DEFAULT_SQLITE_DB_PATH),
|
||||
[sqlite, DB];
|
||||
_ ->
|
||||
Port = ejabberd_config:get_option(
|
||||
{odbc_port, Host},
|
||||
|
@ -67,6 +67,22 @@ init([Host]) ->
|
||||
{odbc_start_interval, Host},
|
||||
fun(I) when is_integer(I), I>0 -> I end,
|
||||
?DEFAULT_ODBC_START_INTERVAL),
|
||||
Type = ejabberd_config:get_option({odbc_type, Host},
|
||||
fun(mysql) -> mysql;
|
||||
(pgsql) -> pgsql;
|
||||
(sqlite) -> sqlite;
|
||||
(odbc) -> odbc
|
||||
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);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
|
||||
{ok,
|
||||
{{one_for_one, PoolSize * 10, 1},
|
||||
lists:map(fun (I) ->
|
||||
@ -113,5 +129,75 @@ transform_options({odbc_server, {mysql, Server, DB, User, Pass}}, Opts) ->
|
||||
transform_options({odbc_server, {mysql, Server, ?MYSQL_PORT, DB, User, Pass}}, Opts);
|
||||
transform_options({odbc_server, {pgsql, Server, DB, User, Pass}}, Opts) ->
|
||||
transform_options({odbc_server, {pgsql, Server, ?PGSQL_PORT, DB, User, Pass}}, Opts);
|
||||
transform_options({odbc_server, {sqlite, DB}}, Opts) ->
|
||||
transform_options({odbc_server, {sqlite, DB}}, Opts);
|
||||
transform_options(Opt, Opts) ->
|
||||
[Opt|Opts].
|
||||
|
||||
check_sqlite_db(DB) ->
|
||||
process_flag(trap_exit, true),
|
||||
Ret = case sqlite3:open(?SQLITE_DB, [{file, binary_to_list(DB)}]) of
|
||||
{ok, _Ref} -> ok;
|
||||
{error, {already_started, _Ref}} -> ok;
|
||||
{error, R} -> {error, R}
|
||||
end,
|
||||
case Ret of
|
||||
ok ->
|
||||
case sqlite3:list_tables(?SQLITE_DB) of
|
||||
[] ->
|
||||
create_sqlite_tables(),
|
||||
sqlite3:close(?SQLITE_DB),
|
||||
ok;
|
||||
[_H | _] ->
|
||||
ok
|
||||
end;
|
||||
{error, Reason} ->
|
||||
?INFO_MSG("Failed open sqlite database, reason ~p", [Reason])
|
||||
end.
|
||||
|
||||
create_sqlite_tables() ->
|
||||
SqlDir = case code:priv_dir(ejabberd) of
|
||||
{error, _} ->
|
||||
?SQL_DIR;
|
||||
PrivDir ->
|
||||
filename:join(PrivDir, "sql")
|
||||
end,
|
||||
File = filename:join(SqlDir, "lite.sql"),
|
||||
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");
|
||||
{error, Reason} ->
|
||||
?INFO_MSG("Not found sqlite database schema, reason: ~p", [Reason]),
|
||||
ok
|
||||
end.
|
||||
|
||||
read_lines(Fd, File, Acc) ->
|
||||
case file:read_line(Fd) of
|
||||
{ok, Line} ->
|
||||
NewAcc = case str:strip(str:strip(Line, both, $\r), both, $\n) of
|
||||
<<"--", _/binary>> ->
|
||||
Acc;
|
||||
<<>> ->
|
||||
Acc;
|
||||
_ ->
|
||||
[Line|Acc]
|
||||
end,
|
||||
read_lines(Fd, File, NewAcc);
|
||||
eof ->
|
||||
QueryList = str:tokens(list_to_binary(lists:reverse(Acc)), <<";">>),
|
||||
lists:flatmap(
|
||||
fun(Query) ->
|
||||
case str:strip(str:strip(Query, both, $\r), both, $\n) of
|
||||
<<>> ->
|
||||
[];
|
||||
Q ->
|
||||
[<<Q/binary, $;>>]
|
||||
end
|
||||
end, QueryList);
|
||||
{error, _} = Err ->
|
||||
?ERROR_MSG("Failed read from lite.sql, reason: ~p", [Err]),
|
||||
[]
|
||||
end.
|
||||
|
@ -74,10 +74,12 @@ needs_odbc(Host) ->
|
||||
case ejabberd_config:get_option({odbc_type, LHost},
|
||||
fun(mysql) -> mysql;
|
||||
(pgsql) -> pgsql;
|
||||
(sqlite) -> sqlite;
|
||||
(odbc) -> odbc
|
||||
end, undefined) of
|
||||
mysql -> {true, p1_mysql};
|
||||
pgsql -> {true, p1_pgsql};
|
||||
sqlite -> {true, sqlite3};
|
||||
odbc -> {true, odbc};
|
||||
undefined -> false
|
||||
end.
|
||||
|
@ -940,8 +940,10 @@ ip_to_list(IP) ->
|
||||
binary_to_atom(Bin) ->
|
||||
erlang:binary_to_atom(Bin, utf8).
|
||||
|
||||
binary_to_integer(Bin) ->
|
||||
list_to_integer(binary_to_list(Bin)).
|
||||
binary_to_integer(Bin) when is_binary(Bin) ->
|
||||
list_to_integer(binary_to_list(Bin));
|
||||
binary_to_integer(Bin) when is_integer(Bin) ->
|
||||
Bin.
|
||||
|
||||
binary_to_integer(Bin, Base) ->
|
||||
list_to_integer(binary_to_list(Bin), Base).
|
||||
|
@ -264,6 +264,7 @@ users_number(LServer) ->
|
||||
Type = ejabberd_config:get_option({odbc_type, LServer},
|
||||
fun(pgsql) -> pgsql;
|
||||
(mysql) -> mysql;
|
||||
(sqlite) -> sqlite;
|
||||
(odbc) -> odbc
|
||||
end, odbc),
|
||||
case Type of
|
||||
|
@ -35,6 +35,7 @@ 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.
|
||||
|
||||
@ -65,6 +66,14 @@ init_per_group(pgsql, Config) ->
|
||||
Err ->
|
||||
{skip, {pgsql_not_available, Err}}
|
||||
end;
|
||||
init_per_group(sqlite, Config) ->
|
||||
case catch ejabberd_odbc:sql_query(?SQLITE_VHOST, [<<"select 1;">>]) of
|
||||
{selected, _, _} ->
|
||||
mod_muc:shutdown_rooms(?SQLITE_VHOST),
|
||||
set_opt(server, ?SQLITE_VHOST, Config);
|
||||
Err ->
|
||||
{skip, {sqlite_not_available, Err}}
|
||||
end;
|
||||
init_per_group(ldap, Config) ->
|
||||
set_opt(server, ?LDAP_VHOST, Config);
|
||||
init_per_group(extauth, Config) ->
|
||||
@ -88,6 +97,8 @@ end_per_group(mysql, _Config) ->
|
||||
ok;
|
||||
end_per_group(pgsql, _Config) ->
|
||||
ok;
|
||||
end_per_group(sqlite, _Config) ->
|
||||
ok;
|
||||
end_per_group(no_db, _Config) ->
|
||||
ok;
|
||||
end_per_group(ldap, _Config) ->
|
||||
@ -300,6 +311,7 @@ groups() ->
|
||||
{mnesia, [sequence], db_tests(mnesia)},
|
||||
{mysql, [sequence], db_tests(mysql)},
|
||||
{pgsql, [sequence], db_tests(pgsql)},
|
||||
{sqlite, [sequence], db_tests(sqlite)},
|
||||
{riak, [sequence], db_tests(riak)}].
|
||||
|
||||
all() ->
|
||||
@ -308,6 +320,7 @@ all() ->
|
||||
{group, mnesia},
|
||||
{group, mysql},
|
||||
{group, pgsql},
|
||||
{group, sqlite},
|
||||
{group, extauth},
|
||||
{group, riak},
|
||||
stop_ejabberd].
|
||||
@ -1631,6 +1644,8 @@ socks5_recv(Sock, Data) ->
|
||||
%%%===================================================================
|
||||
%%% SQL stuff
|
||||
%%%===================================================================
|
||||
create_sql_tables(sqlite, _BaseDir) ->
|
||||
ok;
|
||||
create_sql_tables(Type, BaseDir) ->
|
||||
{VHost, File} = case Type of
|
||||
mysql ->
|
||||
|
@ -3,6 +3,7 @@
|
||||
"mnesia.localhost",
|
||||
"mysql.localhost",
|
||||
"pgsql.localhost",
|
||||
"sqlite.localhost",
|
||||
"extauth.localhost",
|
||||
"ldap.localhost"]}.
|
||||
{define_macro, 'CERTFILE', "cert.pem"}.
|
||||
@ -120,6 +121,25 @@
|
||||
{mod_roster, [{db_type, odbc}]},
|
||||
{mod_vcard, [{db_type, odbc}]}]}
|
||||
]}.
|
||||
{host_config, "sqlite.localhost",
|
||||
[{auth_method, odbc},
|
||||
{odbc_pool_size, 1},
|
||||
{odbc_server, {sqlite, "/tmp/ejabberd_test.db"}},
|
||||
{{add, modules}, [{mod_announce, [{db_type, odbc}]},
|
||||
{mod_blocking, [{db_type, odbc}]},
|
||||
{mod_caps, [{db_type, odbc}]},
|
||||
{mod_last, [{db_type, odbc}]},
|
||||
{mod_muc, [{db_type, odbc}]},
|
||||
{mod_offline, [{db_type, odbc}]},
|
||||
{mod_privacy, [{db_type, odbc}]},
|
||||
{mod_private, [{db_type, odbc}]},
|
||||
{mod_pubsub_odbc, [{access_createnode, pubsub_createnode},
|
||||
{ignore_pep_from_offline, true},
|
||||
{last_item_cache, false},
|
||||
{plugins, ["flat", "hometree", "pep"]}]},
|
||||
{mod_roster, [{db_type, odbc}]},
|
||||
{mod_vcard, [{db_type, odbc}]}]}
|
||||
]}.
|
||||
{host_config, "ldap.localhost",
|
||||
[{auth_method, ldap},
|
||||
{ldap_servers, ["localhost"]},
|
||||
|
@ -51,6 +51,57 @@ host_config:
|
||||
welcome_message:
|
||||
subject: "Welcome!"
|
||||
body: "Hi.
|
||||
Welcome to this XMPP server."
|
||||
mod_stats: []
|
||||
mod_time: []
|
||||
mod_version: []
|
||||
"sqlite.localhost":
|
||||
odbc_type: sqlite
|
||||
odbc_database: "/tmp/ejabberd_test.db"
|
||||
auth_method: odbc
|
||||
modules:
|
||||
mod_announce:
|
||||
db_type: odbc
|
||||
access: local
|
||||
mod_blocking:
|
||||
db_type: odbc
|
||||
mod_caps:
|
||||
db_type: odbc
|
||||
mod_last:
|
||||
db_type: odbc
|
||||
mod_muc:
|
||||
db_type: odbc
|
||||
mod_offline:
|
||||
db_type: odbc
|
||||
mod_privacy:
|
||||
db_type: odbc
|
||||
mod_private:
|
||||
db_type: odbc
|
||||
mod_pubsub_odbc:
|
||||
access_createnode: pubsub_createnode
|
||||
ignore_pep_from_offline: true
|
||||
last_item_cache: false
|
||||
plugins:
|
||||
- "flat"
|
||||
- "hometree"
|
||||
- "pep"
|
||||
mod_roster:
|
||||
versioning: true
|
||||
store_current_id: true
|
||||
db_type: odbc
|
||||
mod_vcard:
|
||||
db_type: odbc
|
||||
mod_vcard_xupdate:
|
||||
db_type: odbc
|
||||
mod_adhoc: []
|
||||
mod_configure: []
|
||||
mod_disco: []
|
||||
mod_ping: []
|
||||
mod_proxy65: []
|
||||
mod_register:
|
||||
welcome_message:
|
||||
subject: "Welcome!"
|
||||
body: "Hi.
|
||||
Welcome to this XMPP server."
|
||||
mod_stats: []
|
||||
mod_time: []
|
||||
@ -242,6 +293,7 @@ hosts:
|
||||
- "extauth.localhost"
|
||||
- "ldap.localhost"
|
||||
- "riak.localhost"
|
||||
- "sqlite.localhost"
|
||||
access:
|
||||
announce:
|
||||
admin: allow
|
||||
|
@ -59,6 +59,7 @@
|
||||
-define(MNESIA_VHOST, <<"mnesia.localhost">>).
|
||||
-define(MYSQL_VHOST, <<"mysql.localhost">>).
|
||||
-define(PGSQL_VHOST, <<"pgsql.localhost">>).
|
||||
-define(SQLITE_VHOST, <<"sqlite.localhost">>).
|
||||
-define(LDAP_VHOST, <<"ldap.localhost">>).
|
||||
-define(EXTAUTH_VHOST, <<"extauth.localhost">>).
|
||||
-define(RIAK_VHOST, <<"riak.localhost">>).
|
||||
|
@ -23,6 +23,7 @@
|
||||
{odbc, @odbc@}.
|
||||
{mysql, @mysql@}.
|
||||
{pgsql, @pgsql@}.
|
||||
{sqlite, @sqlite@}.
|
||||
{pam, @pam@}.
|
||||
{zlib, @zlib@}.
|
||||
{riak, @riak@}.
|
||||
|
Loading…
Reference in New Issue
Block a user