]> granicus.if.org Git - ejabberd/commitdiff
Add SQL_INSERT macro and update SQL queries to use server_host field
authorAlexey Shchepin <alexey@process-one.net>
Thu, 2 Nov 2017 14:03:30 +0000 (17:03 +0300)
committerAlexey Shchepin <alexey@process-one.net>
Thu, 2 Nov 2017 15:21:40 +0000 (18:21 +0300)
25 files changed:
configure.ac
include/ejabberd_sql_pt.hrl
rebar.config
sql/pg.new.sql [new file with mode: 0644]
src/ejabberd_auth_mnesia.erl
src/ejabberd_auth_riak.erl
src/ejabberd_auth_sql.erl
src/ejabberd_sm_sql.erl
src/ejabberd_sql_pt.erl
src/mod_admin_update_sql.erl [new file with mode: 0644]
src/mod_announce_sql.erl
src/mod_carboncopy_sql.erl
src/mod_irc_sql.erl
src/mod_last_sql.erl
src/mod_mam_sql.erl
src/mod_muc_sql.erl
src/mod_offline_sql.erl
src/mod_privacy_sql.erl
src/mod_private_sql.erl
src/mod_push_sql.erl
src/mod_roster.erl
src/mod_roster_sql.erl
src/mod_shared_roster_sql.erl
src/mod_vcard_sql.erl
vars.config.in

index 1fdf30293a562c527e981ee8e9754185c7d015b8..17d32ac18740430ab5dc2f6dc68b3cec2adad60c 100644 (file)
@@ -84,6 +84,14 @@ AC_ARG_ENABLE(roster_gateway_workaround,
   *) AC_MSG_ERROR(bad value ${enableval} for --enable-roster-gateway-workaround) ;;
 esac],[roster_gateway_workaround=false])
 
+AC_ARG_ENABLE(new_sql_schema,
+[AC_HELP_STRING([--enable-new-sql-schema], [use new SQL schema (default: no)])],
+[case "${enableval}" in
+  yes) new_sql_schema=true ;;
+  no)  new_sql_schema=false ;;
+  *) AC_MSG_ERROR(bad value ${enableval} for --enable-new-sql-schema) ;;
+esac],[new_sql_schema=false])
+
 AC_ARG_ENABLE(full_xml,
 [AC_HELP_STRING([--enable-full-xml], [use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients)])],
 [case "${enableval}" in
@@ -273,6 +281,7 @@ fi
 
 AC_SUBST(hipe)
 AC_SUBST(roster_gateway_workaround)
+AC_SUBST(new_sql_schema)
 AC_SUBST(full_xml)
 AC_SUBST(db_type)
 AC_SUBST(odbc)
index 8e5e5c38cc6d54996331a6a9286b6402feac9a1e..438a6563d4608191cda5252f411d85e26ef18796 100644 (file)
@@ -27,6 +27,9 @@
 -define(SQL_UPSERT_T(Table, Fields),
         ejabberd_sql:sql_query_t(?SQL_UPSERT_MARK(Table, Fields))).
 
+-define(SQL_INSERT_MARK, sql_insert__mark_).
+-define(SQL_INSERT(Table, Fields), ?SQL_INSERT_MARK(Table, Fields)).
+
 -record(sql_query, {hash, format_query, format_res, args, loc}).
 
 -record(sql_escape, {string, integer, boolean}).
index ce2806e33e11dc5742da75b6f26d114379e554d8..7b03fc8c483e62c97172c969d5e2b8767f346724 100644 (file)
@@ -99,6 +99,7 @@
            {if_have_fun, {rand, uniform, 1}, {d, 'RAND_UNIFORM'}},
            {if_have_fun, {gb_sets, iterator_from, 2}, {d, 'GB_SETS_ITERATOR_FROM'}},
            {if_have_fun, {public_key, short_name_hash, 1}, {d, 'SHORT_NAME_HASH'}},
+            {if_var_true, new_sql_schema, {d, 'NEW_SQL_SCHEMA'}},
             {if_var_true, hipe, native},
             {src_dirs, [asn1, src,
                         {if_var_true, tools, tools},
diff --git a/sql/pg.new.sql b/sql/pg.new.sql
new file mode 100644 (file)
index 0000000..b155a42
--- /dev/null
@@ -0,0 +1,604 @@
+--
+-- ejabberd, Copyright (C) 2002-2017   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.
+--
+
+-- To update from the old schema, replace <HOST> with the host's domain:
+
+-- ALTER TABLE users ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE users DROP CONSTRAINT users_pkey;
+-- ALTER TABLE users ADD PRIMARY KEY (server_host, username);
+-- ALTER TABLE users ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE last ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE last DROP CONSTRAINT last_pkey;
+-- ALTER TABLE last ADD PRIMARY KEY (server_host, username);
+-- ALTER TABLE last ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE rosterusers ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- DROP INDEX i_rosteru_user_jid;
+-- DROP INDEX i_rosteru_username;
+-- DROP INDEX i_rosteru_jid;
+-- CREATE UNIQUE INDEX i_rosteru_sh_user_jid ON rosterusers USING btree (server_host, username, jid);
+-- CREATE INDEX i_rosteru_sh_username ON rosterusers USING btree (server_host, username);
+-- CREATE INDEX i_rosteru_sh_jid ON rosterusers USING btree (server_host, jid);
+-- ALTER TABLE rosterusers ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE rostergroups ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- DROP INDEX pk_rosterg_user_jid;
+-- CREATE INDEX i_rosterg_sh_user_jid ON rostergroups USING btree (server_host, username, jid);
+-- ALTER TABLE rostergroups ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE sr_group ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE sr_group ADD PRIMARY KEY (server_host, name);
+-- ALTER TABLE sr_group ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE sr_user ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- DROP INDEX i_sr_user_jid_grp;
+-- DROP INDEX i_sr_user_jid;
+-- DROP INDEX i_sr_user_grp;
+-- ALTER TABLE sr_user ADD PRIMARY KEY (server_host, jid, grp);
+-- CREATE INDEX i_sr_user_sh_jid ON sr_user USING btree (server_host, jid);
+-- CREATE INDEX i_sr_user_sh_grp ON sr_user USING btree (server_host, grp);
+-- ALTER TABLE sr_user ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE spool ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- DROP INDEX i_despool;
+-- CREATE INDEX i_spool_sh_username ON spool USING btree (server_host, username);
+-- ALTER TABLE spool ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE archive ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- DROP INDEX i_username;
+-- DROP INDEX i_username_timestamp;
+-- DROP INDEX i_timestamp;
+-- DROP INDEX i_peer;
+-- DROP INDEX i_bare_peer;
+-- CREATE INDEX i_archive_sh_username_timestamp ON archive USING btree (server_host, username, timestamp);
+-- CREATE INDEX i_archive_sh_timestamp ON archive USING btree (server_host, timestamp);
+-- CREATE INDEX i_archive_sh_peer ON archive USING btree (server_host, peer);
+-- CREATE INDEX i_archive_sh_bare_peer ON archive USING btree (server_host, bare_peer);
+-- ALTER TABLE archive ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE archive_prefs ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE archive_prefs DROP CONSTRAINT archive_prefs_pkey;
+-- ALTER TABLE archive_prefs ADD PRIMARY KEY (server_host, username);
+-- ALTER TABLE archive_prefs ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE vcard ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE vcard DROP CONSTRAINT vcard_pkey;
+-- ALTER TABLE vcard ADD PRIMARY KEY (server_host, username);
+-- ALTER TABLE vcard ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE vcard_search ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE vcard_search DROP CONSTRAINT vcard_search_pkey;
+-- DROP INDEX i_vcard_search_lfn;
+-- DROP INDEX i_vcard_search_lfamily;
+-- DROP INDEX i_vcard_search_lgiven;
+-- DROP INDEX i_vcard_search_lmiddle;
+-- DROP INDEX i_vcard_search_lnickname;
+-- DROP INDEX i_vcard_search_lbday;
+-- DROP INDEX i_vcard_search_lctry;
+-- DROP INDEX i_vcard_search_llocality;
+-- DROP INDEX i_vcard_search_lemail;
+-- DROP INDEX i_vcard_search_lorgname;
+-- DROP INDEX i_vcard_search_lorgunit;
+-- ALTER TABLE vcard_search ADD PRIMARY KEY (server_host, username);
+-- CREATE INDEX i_vcard_search_sh_lfn       ON vcard_search(server_host, lfn);
+-- CREATE INDEX i_vcard_search_sh_lfamily   ON vcard_search(server_host, lfamily);
+-- CREATE INDEX i_vcard_search_sh_lgiven    ON vcard_search(server_host, lgiven);
+-- CREATE INDEX i_vcard_search_sh_lmiddle   ON vcard_search(server_host, lmiddle);
+-- CREATE INDEX i_vcard_search_sh_lnickname ON vcard_search(server_host, lnickname);
+-- CREATE INDEX i_vcard_search_sh_lbday     ON vcard_search(server_host, lbday);
+-- CREATE INDEX i_vcard_search_sh_lctry     ON vcard_search(server_host, lctry);
+-- CREATE INDEX i_vcard_search_sh_llocality ON vcard_search(server_host, llocality);
+-- CREATE INDEX i_vcard_search_sh_lemail    ON vcard_search(server_host, lemail);
+-- CREATE INDEX i_vcard_search_sh_lorgname  ON vcard_search(server_host, lorgname);
+-- CREATE INDEX i_vcard_search_sh_lorgunit  ON vcard_search(server_host, lorgunit);
+-- ALTER TABLE vcard_search ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE privacy_default_list ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE privacy_default_list DROP CONSTRAINT privacy_default_list_pkey;
+-- ALTER TABLE privacy_default_list ADD PRIMARY KEY (server_host, username);
+-- ALTER TABLE privacy_default_list ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE privacy_list ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- DROP INDEX i_privacy_list_username;
+-- DROP INDEX i_privacy_list_username_name;
+-- CREATE INDEX i_privacy_list_sh_username ON privacy_list USING btree (server_host, username);
+-- CREATE UNIQUE INDEX i_privacy_list_sh_username_name ON privacy_list USING btree (server_host, username, name);
+-- ALTER TABLE privacy_list ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE private_storage ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- DROP INDEX i_private_storage_username;
+-- DROP INDEX i_private_storage_username_namespace;
+-- ALTER TABLE private_storage ADD PRIMARY KEY (server_host, username, namespace);
+-- CREATE INDEX i_private_storage_sh_username ON private_storage USING btree (server_host, username);
+-- ALTER TABLE private_storage ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE roster_version ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE roster_version DROP CONSTRAINT roster_version_pkey;
+-- ALTER TABLE roster_version ADD PRIMARY KEY (server_host, username);
+-- ALTER TABLE roster_version ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE muc_room ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE muc_room ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE muc_registered ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE muc_registered ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE muc_online_room ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE muc_online_room ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE muc_online_users ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE muc_online_users ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE irc_custom ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE irc_custom ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE motd ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- ALTER TABLE motd DROP CONSTRAINT motd_pkey;
+-- ALTER TABLE motd ADD PRIMARY KEY (server_host, username);
+-- ALTER TABLE motd ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE sm ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- DROP INDEX i_sm_sid;
+-- DROP INDEX i_sm_username;
+-- ALTER TABLE sm ADD PRIMARY KEY (usec, pid);
+-- CREATE INDEX i_sm_sh_username ON sm USING btree (server_host, username);
+-- ALTER TABLE sm ALTER COLUMN server_host DROP DEFAULT;
+
+-- ALTER TABLE carboncopy ADD COLUMN server_host text NOT NULL DEFAULT '<HOST>';
+-- DROP INDEX i_carboncopy_ur;
+-- DROP INDEX i_carboncopy_user;
+-- ALTER TABLE carboncopy ADD PRIMARY KEY (server_host, username, resource);
+-- CREATE INDEX i_carboncopy_sh_user ON carboncopy USING btree (server_host, username);
+-- ALTER TABLE carboncopy ALTER COLUMN server_host DROP DEFAULT;
+
+
+CREATE TABLE users (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    "password" text NOT NULL,
+    serverkey text NOT NULL DEFAULT '',
+    salt text NOT NULL DEFAULT '',
+    iterationcount integer NOT NULL DEFAULT 0,
+    created_at TIMESTAMP NOT NULL DEFAULT now(),
+    PRIMARY KEY (server_host, username)
+);
+
+-- Add support for SCRAM auth to a database created before ejabberd 16.03:
+-- ALTER TABLE users ADD COLUMN serverkey text NOT NULL DEFAULT '';
+-- ALTER TABLE users ADD COLUMN salt text NOT NULL DEFAULT '';
+-- ALTER TABLE users ADD COLUMN iterationcount integer NOT NULL DEFAULT 0;
+
+CREATE TABLE last (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    seconds text NOT NULL,
+    state text NOT NULL,
+    PRIMARY KEY (server_host, username)
+);
+
+
+CREATE TABLE rosterusers (
+    username text NOT NULL,
+    server_host 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 NOT NULL,
+    "type" text,
+    created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE UNIQUE INDEX i_rosteru_sh_user_jid ON rosterusers USING btree (server_host, username, jid);
+CREATE INDEX i_rosteru_sh_username ON rosterusers USING btree (server_host, username);
+CREATE INDEX i_rosteru_sh_jid ON rosterusers USING btree (server_host, jid);
+
+
+CREATE TABLE rostergroups (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    jid text NOT NULL,
+    grp text NOT NULL
+);
+
+CREATE INDEX i_rosterg_sh_user_jid ON rostergroups USING btree (server_host, username, jid);
+
+CREATE TABLE sr_group (
+    name text NOT NULL,
+    server_host text NOT NULL,
+    opts text NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now(),
+    PRIMARY KEY (server_host, name)
+);
+
+CREATE TABLE sr_user (
+    jid text NOT NULL,
+    server_host text NOT NULL,
+    grp text NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now(),
+    PRIMARY KEY (server_host, jid, grp)
+);
+
+CREATE INDEX i_sr_user_sh_jid ON sr_user USING btree (server_host, jid);
+CREATE INDEX i_sr_user_sh_grp ON sr_user USING btree (server_host, grp);
+
+CREATE TABLE spool (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    xml text NOT NULL,
+    seq SERIAL,
+    created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_spool_sh_username ON spool USING btree (server_host, username);
+
+CREATE TABLE archive (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    timestamp BIGINT NOT NULL,
+    peer text NOT NULL,
+    bare_peer text NOT NULL,
+    xml text NOT NULL,
+    txt text,
+    id SERIAL,
+    kind text,
+    nick text,
+    created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_archive_sh_username_timestamp ON archive USING btree (server_host, username, timestamp);
+CREATE INDEX i_archive_sh_timestamp ON archive USING btree (server_host, timestamp);
+CREATE INDEX i_archive_sh_peer ON archive USING btree (server_host, peer);
+CREATE INDEX i_archive_sh_bare_peer ON archive USING btree (server_host, bare_peer);
+
+CREATE TABLE archive_prefs (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    def text NOT NULL,
+    always text NOT NULL,
+    never text NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now(),
+    PRIMARY KEY (server_host, username)
+);
+
+CREATE TABLE vcard (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    vcard text NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now(),
+    PRIMARY KEY (server_host, username)
+);
+
+CREATE TABLE vcard_search (
+    username text NOT NULL,
+    lusername text NOT NULL,
+    server_host text NOT NULL,
+    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,
+    PRIMARY KEY (server_host, username)
+);
+
+CREATE INDEX i_vcard_search_sh_lfn       ON vcard_search(server_host, lfn);
+CREATE INDEX i_vcard_search_sh_lfamily   ON vcard_search(server_host, lfamily);
+CREATE INDEX i_vcard_search_sh_lgiven    ON vcard_search(server_host, lgiven);
+CREATE INDEX i_vcard_search_sh_lmiddle   ON vcard_search(server_host, lmiddle);
+CREATE INDEX i_vcard_search_sh_lnickname ON vcard_search(server_host, lnickname);
+CREATE INDEX i_vcard_search_sh_lbday     ON vcard_search(server_host, lbday);
+CREATE INDEX i_vcard_search_sh_lctry     ON vcard_search(server_host, lctry);
+CREATE INDEX i_vcard_search_sh_llocality ON vcard_search(server_host, llocality);
+CREATE INDEX i_vcard_search_sh_lemail    ON vcard_search(server_host, lemail);
+CREATE INDEX i_vcard_search_sh_lorgname  ON vcard_search(server_host, lorgname);
+CREATE INDEX i_vcard_search_sh_lorgunit  ON vcard_search(server_host, lorgunit);
+
+CREATE TABLE privacy_default_list (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    name text NOT NULL,
+    PRIMARY KEY (server_host, username)
+);
+
+CREATE TABLE privacy_list (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    name text NOT NULL,
+    id SERIAL UNIQUE,
+    created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_privacy_list_sh_username ON privacy_list USING btree (server_host, username);
+CREATE UNIQUE INDEX i_privacy_list_sh_username_name ON privacy_list USING btree (server_host, 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 INDEX i_privacy_list_data_id ON privacy_list_data USING btree (id);
+
+CREATE TABLE private_storage (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    namespace text NOT NULL,
+    data text NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now(),
+    PRIMARY KEY (server_host, username, namespace)
+);
+
+CREATE INDEX i_private_storage_sh_username ON private_storage USING btree (server_host, username);
+
+
+CREATE TABLE roster_version (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    version text NOT NULL,
+    PRIMARY KEY (server_host, username)
+);
+
+-- To update from 0.9.8:
+-- CREATE SEQUENCE spool_seq_seq;
+-- ALTER TABLE spool ADD COLUMN seq integer;
+-- ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
+-- UPDATE spool SET seq = DEFAULT;
+-- ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
+
+-- To update from 1.x:
+-- ALTER TABLE rosterusers ADD COLUMN askmessage text;
+-- UPDATE rosterusers SET askmessage = '';
+-- ALTER TABLE rosterusers ALTER COLUMN askmessage SET NOT NULL;
+
+CREATE TABLE pubsub_node (
+  host text NOT NULL,
+  node text NOT NULL,
+  parent text NOT NULL DEFAULT '',
+  "type" text NOT NULL,
+  nodeid SERIAL UNIQUE
+);
+CREATE INDEX i_pubsub_node_parent ON pubsub_node USING btree (parent);
+CREATE UNIQUE INDEX i_pubsub_node_tuple ON pubsub_node USING btree (host, node);
+
+CREATE TABLE pubsub_node_option (
+  nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
+  name text NOT NULL,
+  val text NOT NULL
+);
+CREATE INDEX i_pubsub_node_option_nodeid ON pubsub_node_option USING btree (nodeid);
+
+CREATE TABLE pubsub_node_owner (
+  nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
+  owner text NOT NULL
+);
+CREATE INDEX i_pubsub_node_owner_nodeid ON pubsub_node_owner USING btree (nodeid);
+
+CREATE TABLE pubsub_state (
+  nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
+  jid text NOT NULL,
+  affiliation character(1),
+  subscriptions text NOT NULL DEFAULT '',
+  stateid SERIAL UNIQUE
+);
+CREATE INDEX i_pubsub_state_jid ON pubsub_state USING btree (jid);
+CREATE UNIQUE INDEX i_pubsub_state_tuple ON pubsub_state USING btree (nodeid, jid);
+
+CREATE TABLE pubsub_item (
+  nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
+  itemid text NOT NULL,
+  publisher text NOT NULL,
+  creation text NOT NULL,
+  modification text NOT NULL,
+  payload text NOT NULL DEFAULT ''
+);
+CREATE INDEX i_pubsub_item_itemid ON pubsub_item USING btree (itemid);
+CREATE UNIQUE INDEX i_pubsub_item_tuple ON pubsub_item USING btree (nodeid, itemid);
+
+CREATE TABLE pubsub_subscription_opt (
+  subid text NOT NULL,
+  opt_name varchar(32),
+  opt_value text NOT NULL
+);
+CREATE UNIQUE INDEX i_pubsub_subscription_opt ON pubsub_subscription_opt USING btree (subid, opt_name);
+
+CREATE TABLE muc_room (
+    name text NOT NULL,
+    host text NOT NULL,
+    server_host text NOT NULL,
+    opts text NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room USING btree (name, host);
+
+CREATE TABLE muc_registered (
+    jid text NOT NULL,
+    host text NOT NULL,
+    server_host text NOT NULL,
+    nick text NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_muc_registered_nick ON muc_registered USING btree (nick);
+CREATE UNIQUE INDEX i_muc_registered_jid_host ON muc_registered USING btree (jid, host);
+
+CREATE TABLE muc_online_room (
+    name text NOT NULL,
+    host text NOT NULL,
+    server_host text NOT NULL,
+    node text NOT NULL,
+    pid text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_muc_online_room_name_host ON muc_online_room USING btree (name, host);
+
+CREATE TABLE muc_online_users (
+    username text NOT NULL,
+    server text NOT NULL,
+    resource text NOT NULL,
+    name text NOT NULL,
+    host text NOT NULL,
+    server_host text NOT NULL,
+    node text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_muc_online_users ON muc_online_users USING btree (username, server, resource, name, host);
+CREATE INDEX i_muc_online_users_us ON muc_online_users USING btree (username, server);
+
+CREATE TABLE muc_room_subscribers (
+   room text NOT NULL,
+   host text NOT NULL,
+   jid text NOT NULL,
+   nick text NOT NULL,
+   nodes text NOT NULL,
+   created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers USING btree (host, jid);
+CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers USING btree (host, room, jid);
+
+CREATE TABLE irc_custom (
+    jid text NOT NULL,
+    host text NOT NULL,
+    server_host text NOT NULL,
+    data text NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE UNIQUE INDEX i_irc_custom_jid_host ON irc_custom USING btree (jid, host);
+
+CREATE TABLE motd (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    xml text,
+    created_at TIMESTAMP NOT NULL DEFAULT now(),
+    PRIMARY KEY (server_host, username)
+);
+
+CREATE TABLE caps_features (
+    node text NOT NULL,
+    subnode text NOT NULL,
+    feature text,
+    created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_caps_features_node_subnode ON caps_features USING btree (node, subnode);
+
+CREATE TABLE sm (
+    usec bigint NOT NULL,
+    pid text NOT NULL,
+    node text NOT NULL,
+    username text NOT NULL,
+    resource text NOT NULL,
+    priority text NOT NULL,
+    info text NOT NULL,
+    PRIMARY KEY (usec, pid)
+);
+
+CREATE INDEX i_sm_node ON sm USING btree (node);
+CREATE INDEX i_sm_sh_username ON sm USING btree (server_host, username);
+
+CREATE TABLE oauth_token (
+    token text NOT NULL,
+    jid text NOT NULL,
+    scope text NOT NULL,
+    expire bigint NOT NULL
+);
+
+CREATE UNIQUE INDEX i_oauth_token_token ON oauth_token USING btree (token);
+
+CREATE TABLE route (
+    domain text NOT NULL,
+    server_host text NOT NULL,
+    node text NOT NULL,
+    pid text NOT NULL,
+    local_hint text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_route ON route USING btree (domain, server_host, node, pid);
+CREATE INDEX i_route_domain ON route USING btree (domain);
+
+CREATE TABLE bosh (
+    sid text NOT NULL,
+    node text NOT NULL,
+    pid text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_bosh_sid ON bosh USING btree (sid);
+
+CREATE TABLE carboncopy (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    resource text NOT NULL,
+    namespace text NOT NULL,
+    node text NOT NULL,
+    PRIMARY KEY (server_host, username, resource)
+);
+
+CREATE INDEX i_carboncopy_sh_user ON carboncopy USING btree (server_host, username);
+
+CREATE TABLE proxy65 (
+    sid text NOT NULL,
+    pid_t text NOT NULL,
+    pid_i text NOT NULL,
+    node_t text NOT NULL,
+    node_i text NOT NULL,
+    jid_i text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_proxy65_sid ON proxy65 USING btree (sid);
+CREATE INDEX i_proxy65_jid ON proxy65 USING btree (jid_i);
+
+CREATE TABLE push_session (
+    username text NOT NULL,
+    server_host text NOT NULL,
+    timestamp bigint NOT NULL,
+    service text NOT NULL,
+    node text NOT NULL,
+    xml text NOT NULL,
+    PRIMARY KEY (server_host, username, timestamp)
+);
+
+CREATE UNIQUE INDEX i_push_session_susn ON push_session USING btree (server_host, username, service, node);
index 14b8e5a2dd3b53b41dfdd700ca49af5ed6f50e0a..7705f62e1d5d8b6ec386a6a009a3671acf643dbf 100644 (file)
@@ -40,7 +40,6 @@
 
 -include("ejabberd.hrl").
 -include("logger.hrl").
--include("ejabberd_sql_pt.hrl").
 -include("ejabberd_auth.hrl").
 
 -record(reg_users_counter, {vhost = <<"">> :: binary(),
index 37bd3daf452da32759b8526b51ec9d7f18309def..3cdb7425848b0f5c9e810af0d532678255a39d11 100644 (file)
@@ -106,9 +106,12 @@ export(_Server) ->
     [{passwd,
       fun(Host, #passwd{us = {LUser, LServer}, password = Password})
          when LServer == Host ->
-              [?SQL("delete from users where username=%(LUser)s;"),
-               ?SQL("insert into users(username, password) "
-                    "values (%(LUser)s, %(Password)s);")];
+              [?SQL("delete from users where username=%(LUser)s and %(LServer)H;"),
+               ?SQL_INSERT(
+                  "users",
+                  ["username=%(LUser)s",
+                   "server_host=%(LServer)s",
+                   "password=%(Password)s"])];
          (_Host, _R) ->
               []
       end}].
index 15e5076c930242553e313d701b70a1ce271cb8fb..3f328c4a1a1a889ebd65911393ee4e069cb784e7 100644 (file)
@@ -61,11 +61,11 @@ set_password(User, Server, Password) ->
     F = fun() ->
                if is_record(Password, scram) ->
                        set_password_scram_t(
-                         User,
+                         User, Server,
                          Password#scram.storedkey, Password#scram.serverkey,
                          Password#scram.salt, Password#scram.iterationcount);
                   true ->
-                       set_password_t(User, Password)
+                       set_password_t(User, Server, Password)
                end
        end,
     case ejabberd_sql:sql_transaction(Server, F) of
@@ -133,20 +133,22 @@ remove_user(User, Server) ->
 
 -define(BATCH_SIZE, 1000).
 
-set_password_scram_t(LUser,
+set_password_scram_t(LUser, LServer,
                      StoredKey, ServerKey, Salt, IterationCount) ->
     ?SQL_UPSERT_T(
        "users",
        ["!username=%(LUser)s",
+        "!server_host=%(LServer)s",
         "password=%(StoredKey)s",
         "serverkey=%(ServerKey)s",
         "salt=%(Salt)s",
         "iterationcount=%(IterationCount)d"]).
 
-set_password_t(LUser, Password) ->
+set_password_t(LUser, LServer, Password) ->
     ?SQL_UPSERT_T(
        "users",
        ["!username=%(LUser)s",
+        "!server_host=%(LServer)s",
        "password=%(Password)s"]).
 
 get_password_scram(LServer, LUser) ->
@@ -154,32 +156,39 @@ get_password_scram(LServer, LUser) ->
       LServer,
       ?SQL("select @(password)s, @(serverkey)s, @(salt)s, @(iterationcount)d"
            " from users"
-           " where username=%(LUser)s")).
+           " where username=%(LUser)s and %(LServer)H")).
 
 add_user_scram(LServer, LUser,
                StoredKey, ServerKey, Salt, IterationCount) ->
     ejabberd_sql:sql_query(
       LServer,
-      ?SQL("insert into users(username, password, serverkey, salt, "
-           "iterationcount) "
-           "values (%(LUser)s, %(StoredKey)s, %(ServerKey)s,"
-           " %(Salt)s, %(IterationCount)d)")).
+      ?SQL_INSERT(
+         "users",
+         ["username=%(LUser)s",
+          "server_host=%(LServer)s",
+          "password=%(StoredKey)s",
+          "serverkey=%(ServerKey)s",
+          "salt=%(Salt)s",
+          "iterationcount=%(IterationCount)d"])).
 
 add_user(LServer, LUser, Password) ->
     ejabberd_sql:sql_query(
       LServer,
-      ?SQL("insert into users(username, password) "
-           "values (%(LUser)s, %(Password)s)")).
+      ?SQL_INSERT(
+         "users",
+         ["username=%(LUser)s",
+          "server_host=%(LServer)s",
+          "password=%(Password)s"])).
 
 del_user(LServer, LUser) ->
     ejabberd_sql:sql_query(
       LServer,
-      ?SQL("delete from users where username=%(LUser)s")).
+      ?SQL("delete from users where username=%(LUser)s and %(LServer)H")).
 
 list_users(LServer, []) ->
     ejabberd_sql:sql_query(
       LServer,
-      ?SQL("select @(username)s from users"));
+      ?SQL("select @(username)s from users where %(LServer)H"));
 list_users(LServer, [{from, Start}, {to, End}])
     when is_integer(Start) and is_integer(End) ->
     list_users(LServer,
@@ -196,6 +205,7 @@ list_users(LServer, [{limit, Limit}, {offset, Offset}])
     ejabberd_sql:sql_query(
       LServer,
       ?SQL("select @(username)s from users "
+           "where %(LServer)H "
            "order by username "
            "limit %(Limit)d offset %(Offset)d"));
 list_users(LServer,
@@ -207,7 +217,7 @@ list_users(LServer,
     ejabberd_sql:sql_query(
       LServer,
       ?SQL("select @(username)s from users "
-           "where username like %(SPrefix2)s escape '^' "
+           "where username like %(SPrefix2)s escape '^' and %(LServer)H "
            "order by username "
            "limit %(Limit)d offset %(Offset)d")).
 
@@ -224,11 +234,11 @@ users_number(LServer) ->
                              " where oid = 'users'::regclass::oid"));
                   _ ->
                       ejabberd_sql:sql_query_t(
-                        ?SQL("select @(count(*))d from users"))
+                        ?SQL("select @(count(*))d from users where %(LServer)H"))
          end;
          (_Type, _) ->
               ejabberd_sql:sql_query_t(
-                ?SQL("select @(count(*))d from users"))
+                ?SQL("select @(count(*))d from users where %(LServer)H"))
       end).
 
 users_number(LServer, [{prefix, Prefix}])
@@ -238,7 +248,7 @@ users_number(LServer, [{prefix, Prefix}])
     ejabberd_sql:sql_query(
       LServer,
       ?SQL("select @(count(*))d from users "
-           "where username like %(SPrefix2)s escape '^'"));
+           "where username like %(SPrefix2)s escape '^' and %(LServer)H"));
 users_number(LServer, []) ->
     users_number(LServer).
 
@@ -254,7 +264,7 @@ convert_to_scram(Server) ->
                         case ejabberd_sql:sql_query_t(
                                ?SQL("select @(username)s, @(password)s"
                                     " from users"
-                                    " where iterationcount=0"
+                                    " where iterationcount=0 and %(LServer)H"
                                     " limit %(BatchSize)d")) of
                             {selected, []} ->
                                 ok;
@@ -270,7 +280,7 @@ convert_to_scram(Server) ->
                                              _ ->
                                                  Scram = ejabberd_auth:password_to_scram(Password),
                                                  set_password_scram_t(
-                                                   LUser,
+                                                   LUser, LServer,
                                                    Scram#scram.storedkey,
                                                    Scram#scram.serverkey,
                                                    Scram#scram.salt,
@@ -294,20 +304,27 @@ export(_Server) ->
       fun(Host, #passwd{us = {LUser, LServer}, password = Password})
             when LServer == Host,
                  is_binary(Password) ->
-              [?SQL("delete from users where username=%(LUser)s;"),
-               ?SQL("insert into users(username, password) "
-                    "values (%(LUser)s, %(Password)s);")];
+              [?SQL("delete from users where username=%(LUser)s and %(LServer)H;"),
+               ?SQL_INSERT(
+                  "users",
+                  ["username=%(LUser)s",
+                   "server_host=%(LServer)s",
+                   "password=%(Password)s"])];
          (Host, #passwd{us = {LUser, LServer}, password = #scram{} = Scram})
             when LServer == Host ->
               StoredKey = Scram#scram.storedkey,
               ServerKey = Scram#scram.serverkey,
               Salt = Scram#scram.salt,
               IterationCount = Scram#scram.iterationcount,
-              [?SQL("delete from users where username=%(LUser)s;"),
-               ?SQL("insert into users(username, password, serverkey, salt, "
-                    "iterationcount) "
-                    "values (%(LUser)s, %(StoredKey)s, %(ServerKey)s,"
-                    " %(Salt)s, %(IterationCount)d);")];
+              [?SQL("delete from users where username=%(LUser)s and %(LServer)H;"),
+               ?SQL_INSERT(
+                  "users",
+                  ["username=%(LUser)s",
+                   "server_host=%(LServer)s",
+                   "password=%(StoredKey)s",
+                   "serverkey=%(ServerKey)s",
+                   "salt=%(Salt)s",
+                   "iterationcount=%(IterationCount)d"])];
          (_Host, _R) ->
               []
       end}].
index 2b94064ef20413a54d7f054c37845ac06daedff7..55e21040bc3d2f20e158c2ab5767ab7f6086c75b 100644 (file)
@@ -74,6 +74,7 @@ set_session(#session{sid = {Now, Pid}, usr = {U, LServer, R},
                       "!pid=%(PidS)s",
                       "node=%(Node)s",
                       "username=%(U)s",
+                      "server_host=%(LServer)s",
                       "resource=%(R)s",
                       "priority=%(PrioS)s",
                       "info=%(InfoS)s"]) of
@@ -107,7 +108,8 @@ get_sessions(LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
            ?SQL("select @(usec)d, @(pid)s, @(node)s, @(username)s,"
-                " @(resource)s, @(priority)s, @(info)s from sm")) of
+                " @(resource)s, @(priority)s, @(info)s from sm"
+                " where %(LServer)H")) of
        {selected, Rows} ->
            lists:flatmap(
              fun(Row) ->
@@ -125,7 +127,7 @@ get_sessions(LUser, LServer) ->
           LServer,
            ?SQL("select @(usec)d, @(pid)s, @(node)s, @(username)s,"
                 " @(resource)s, @(priority)s, @(info)s from sm"
-                " where username=%(LUser)s")) of
+                " where username=%(LUser)s and %(LServer)H")) of
        {selected, Rows} ->
            {ok, lists:flatmap(
                   fun(Row) ->
index e90947a5ff87ffbacea11b88ff6386bc488aa507..197e5ee6d85788cadfa2a89e66fc5582ef7915b4 100644 (file)
@@ -26,7 +26,7 @@
 -module(ejabberd_sql_pt).
 
 %% API
--export([parse_transform/2]).
+-export([parse_transform/2, format_error/1]).
 
 -export([parse/2]).
 
@@ -39,7 +39,8 @@
                 args = [],
                 res = [],
                 res_vars = [],
-                res_pos = 0}).
+                res_pos = 0,
+                server_host_used = false}).
 
 -define(QUERY_RECORD, "sql_query").
 
 
 -define(MOD, sql__module_).
 
+-ifdef(NEW_SQL_SCHEMA).
+-define(USE_NEW_SCHEMA, true).
+-else.
+-define(USE_NEW_SCHEMA, false).
+-endif.
+
 %%====================================================================
 %% API
 %%====================================================================
 %%--------------------------------------------------------------------
 parse_transform(AST, _Options) ->
     %io:format("PT: ~p~nOpts: ~p~n", [AST, Options]),
+    put(warnings, []),
     NewAST = top_transform(AST),
     %io:format("NewPT: ~p~n", [NewAST]),
-    NewAST.
+    NewAST ++ get(warnings).
 
 
+format_error(no_server_host) ->
+    "server_host field is not used".
 
 %%====================================================================
 %% Internal functions
@@ -80,6 +90,12 @@ transform(Form) ->
                                     S = erl_syntax:string_value(Arg),
                                     Pos = erl_syntax:get_pos(Arg),
                                     ParseRes = parse(S, Pos),
+                                    if
+                                        ParseRes#state.server_host_used ->
+                                            ok;
+                                        true ->
+                                            add_warning(Pos, no_server_host)
+                                    end,
                                     set_pos(make_sql_query(ParseRes), Pos);
                                 _ ->
                                     throw({error, erl_syntax:get_pos(Form),
@@ -101,8 +117,17 @@ transform(Form) ->
                                         parse_upsert(
                                           erl_syntax:list_elements(FieldsArg)),
                                     Pos = erl_syntax:get_pos(Form),
+                                    case lists:keymember(
+                                           "server_host", 1, ParseRes) of
+                                        true ->
+                                            ok;
+                                        false ->
+                                            add_warning(Pos, no_server_host)
+                                    end,
+                                    ParseRes2 =
+                                        filter_upsert_sh(Table, ParseRes),
                                     set_pos(
-                                      make_sql_upsert(Table, ParseRes, Pos),
+                                      make_sql_upsert(Table, ParseRes2, Pos),
                                       Pos);
                                 _ ->
                                     throw({error, erl_syntax:get_pos(Form),
@@ -113,6 +138,38 @@ transform(Form) ->
                             throw({error, erl_syntax:get_pos(Form),
                                    "wrong number of ?SQL_UPSERT args"})
                     end;
+                {?SQL_INSERT_MARK, 2} ->
+                    case erl_syntax:application_arguments(Form) of
+                        [TableArg, FieldsArg] ->
+                            case {erl_syntax:type(TableArg),
+                                  erl_syntax:is_proper_list(FieldsArg)}of
+                                {string, true} ->
+                                    Table = erl_syntax:string_value(TableArg),
+                                    ParseRes =
+                                        parse_insert(
+                                          erl_syntax:list_elements(FieldsArg)),
+                                    Pos = erl_syntax:get_pos(Form),
+                                    case lists:keymember(
+                                           "server_host", 1, ParseRes) of
+                                        true ->
+                                            ok;
+                                        false ->
+                                            add_warning(Pos, no_server_host)
+                                    end,
+                                    ParseRes2 =
+                                        filter_upsert_sh(Table, ParseRes),
+                                    set_pos(
+                                      make_sql_insert(Table, ParseRes2),
+                                      Pos);
+                                _ ->
+                                    throw({error, erl_syntax:get_pos(Form),
+                                           "?SQL_INSERT arguments must be "
+                                           "a constant string and a list"})
+                            end;
+                        _ ->
+                            throw({error, erl_syntax:get_pos(Form),
+                                   "wrong number of ?SQL_INSERT args"})
+                    end;
                 _ ->
                     Form
             end;
@@ -168,7 +225,7 @@ parse1([], Acc, State) ->
                 };
 parse1([$@, $( | S], Acc, State) ->
     State1 = append_string(lists:reverse(Acc), State),
-    {Name, Type, S1, State2} = parse_name(S, State1),
+    {Name, Type, S1, State2} = parse_name(S, false, State1),
     Var = "__V" ++ integer_to_list(State2#state.res_pos),
     EVar = erl_syntax:variable(Var),
     Convert =
@@ -192,21 +249,43 @@ parse1([$@, $( | S], Acc, State) ->
     parse1(S1, [], State4);
 parse1([$%, $( | S], Acc, State) ->
     State1 = append_string(lists:reverse(Acc), State),
-    {Name, Type, S1, State2} = parse_name(S, State1),
+    {Name, Type, S1, State2} = parse_name(S, true, State1),
     Var = State2#state.param_pos,
-    Convert =
-        erl_syntax:application(
-          erl_syntax:record_access(
-            erl_syntax:variable(?ESCAPE_VAR),
-            erl_syntax:atom(?ESCAPE_RECORD),
-            erl_syntax:atom(Type)),
-          [erl_syntax:variable(Name)]),
-    State3 = State2,
     State4 =
-        State3#state{'query' = [{var, Var} | State3#state.'query'],
-                     args = [Convert | State3#state.args],
-                     params = [Var | State3#state.params],
-                     param_pos = State3#state.param_pos + 1},
+        case Type of
+            host ->
+                State3 = State2#state{server_host_used = true},
+                case ?USE_NEW_SCHEMA of
+                    true ->
+                        Convert =
+                            erl_syntax:application(
+                              erl_syntax:record_access(
+                                erl_syntax:variable(?ESCAPE_VAR),
+                                erl_syntax:atom(?ESCAPE_RECORD),
+                                erl_syntax:atom(string)),
+                              [erl_syntax:variable(Name)]),
+                        State3#state{'query' = [{var, Var},
+                                                {str, "server_host="} |
+                                                State3#state.'query'],
+                                     args = [Convert | State3#state.args],
+                                     params = [Var | State3#state.params],
+                                     param_pos = State3#state.param_pos + 1};
+                    false ->
+                        append_string("0=0", State3)
+                end;
+            _ ->
+                Convert =
+                    erl_syntax:application(
+                      erl_syntax:record_access(
+                        erl_syntax:variable(?ESCAPE_VAR),
+                        erl_syntax:atom(?ESCAPE_RECORD),
+                        erl_syntax:atom(Type)),
+                      [erl_syntax:variable(Name)]),
+                State2#state{'query' = [{var, Var} | State2#state.'query'],
+                             args = [Convert | State2#state.args],
+                             params = [Var | State2#state.params],
+                             param_pos = State2#state.param_pos + 1}
+        end,
     parse1(S1, [], State4);
 parse1([C | S], Acc, State) ->
     parse1(S, [C | Acc], State).
@@ -216,32 +295,33 @@ append_string([], State) ->
 append_string(S, State) ->
     State#state{query = [{str, S} | State#state.query]}.
 
-parse_name(S, State) ->
-    parse_name(S, [], 0, State).
+parse_name(S, IsArg, State) ->
+    parse_name(S, [], 0, IsArg, State).
 
-parse_name([], _Acc, _Depth, State) ->
+parse_name([], _Acc, _Depth, _IsArg, State) ->
     throw({error, State#state.loc,
            "expected ')', found end of string"});
-parse_name([$), T | S], Acc, 0, State) ->
+parse_name([$), T | S], Acc, 0, IsArg, State) ->
     Type =
         case T of
             $d -> integer;
             $s -> string;
             $b -> boolean;
+            $H when IsArg -> host;
             _ ->
                 throw({error, State#state.loc,
                        ["unknown type specifier '", T, "'"]})
         end,
     {lists:reverse(Acc), Type, S, State};
-parse_name([$)], _Acc, 0, State) ->
+parse_name([$)], _Acc, 0, _IsArg, State) ->
     throw({error, State#state.loc,
            "expected type specifier, found end of string"});
-parse_name([$( = C | S], Acc, Depth, State) ->
-    parse_name(S, [C | Acc], Depth + 1, State);
-parse_name([$) = C | S], Acc, Depth, State) ->
-    parse_name(S, [C | Acc], Depth - 1, State);
-parse_name([C | S], Acc, Depth, State) ->
-    parse_name(S, [C | Acc], Depth, State).
+parse_name([$( = C | S], Acc, Depth, IsArg, State) ->
+    parse_name(S, [C | Acc], Depth + 1, IsArg, State);
+parse_name([$) = C | S], Acc, Depth, IsArg, State) ->
+    parse_name(S, [C | Acc], Depth - 1, IsArg, State);
+parse_name([C | S], Acc, Depth, IsArg, State) ->
+    parse_name(S, [C | Acc], Depth, IsArg, State).
 
 
 make_var(V) ->
@@ -444,7 +524,7 @@ make_sql_upsert_insert(Table, ParseRes) ->
            join_states(Fields, ", "),
            #state{'query' = [{str, ") VALUES ("}]},
            join_states(Vals, ", "),
-           #state{'query' = [{str, ")"}]}
+           #state{'query' = [{str, ");"}]}
           ]),
     State.
 
@@ -498,6 +578,49 @@ check_upsert(ParseRes, Pos) ->
     ok.
 
 
+parse_insert(Fields) ->
+    {Fs, _} =
+        lists:foldr(
+          fun(F, {Acc, Param}) ->
+                  case erl_syntax:type(F) of
+                      string ->
+                          V = erl_syntax:string_value(F),
+                          {_, _, State} = Res =
+                              parse_insert_field(
+                                V, Param, erl_syntax:get_pos(F)),
+                          {[Res | Acc], State#state.param_pos};
+                      _ ->
+                          throw({error, erl_syntax:get_pos(F),
+                                 "?SQL_INSERT field must be "
+                                 "a constant string"})
+                  end
+          end, {[], 0}, Fields),
+    Fs.
+
+parse_insert_field([$! | _S], _ParamPos, Loc) ->
+    throw({error, Loc,
+           "?SQL_INSERT fields must not start with \"!\""});
+parse_insert_field([$- | _S], _ParamPos, Loc) ->
+    throw({error, Loc,
+           "?SQL_INSERT fields must not start with \"-\""});
+parse_insert_field(S, ParamPos, Loc) ->
+    {Name, ParseState} = parse_insert_field1(S, [], ParamPos, Loc),
+    {Name, {true}, ParseState}.
+
+parse_insert_field1([], _Acc, _ParamPos, Loc) ->
+    throw({error, Loc,
+           "?SQL_INSERT fields must have the "
+           "following form: \"name=value\""});
+parse_insert_field1([$= | S], Acc, ParamPos, Loc) ->
+    {lists:reverse(Acc), parse(S, ParamPos, Loc)};
+parse_insert_field1([C | S], Acc, ParamPos, Loc) ->
+    parse_insert_field1(S, [C | Acc], ParamPos, Loc).
+
+
+make_sql_insert(Table, ParseRes) ->
+    make_sql_query(make_sql_upsert_insert(Table, ParseRes)).
+
+
 concat_states(States) ->
     lists:foldr(
       fun(ST11, ST2) ->
@@ -566,3 +689,20 @@ set_pos(Tree, Pos) ->
                   _ -> Node
               end
       end, Tree).
+
+filter_upsert_sh(Table, ParseRes) ->
+    case ?USE_NEW_SCHEMA of
+        true ->
+            ParseRes;
+        false ->
+            lists:filter(
+              fun({Field, _Match, _ST}) ->
+                      Field /= "server_host" orelse Table == "route"
+              end, ParseRes)
+    end.
+
+add_warning(Pos, Warning) ->
+    Marker = erl_syntax:revert(
+               erl_syntax:warning_marker({Pos, ?MODULE, Warning})),
+    put(warnings, [Marker | get(warnings)]),
+    ok.
diff --git a/src/mod_admin_update_sql.erl b/src/mod_admin_update_sql.erl
new file mode 100644 (file)
index 0000000..2f105d9
--- /dev/null
@@ -0,0 +1,365 @@
+%%%-------------------------------------------------------------------
+%%% File    : mod_admin_update_sql.erl
+%%% Author  : Alexey Shchepin <alexey@process-one.net>
+%%% Purpose : Convert SQL DB to the new format
+%%% Created :  9 Aug 2017 by Alexey Shchepin <alexey@process-one.net>
+%%%
+%%%
+%%% ejabberd, Copyright (C) 2002-2017   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.
+%%%
+%%%-------------------------------------------------------------------
+
+-module(mod_admin_update_sql).
+-author('alexey@process-one.net').
+
+-behaviour(gen_mod).
+
+-export([start/2, stop/1, reload/3, mod_opt_type/1,
+         get_commands_spec/0, depends/2]).
+
+% Commands API
+-export([update_sql/0]).
+
+
+-include("logger.hrl").
+-include("ejabberd.hrl").
+-include("ejabberd_commands.hrl").
+-include("xmpp.hrl").
+-include("ejabberd_sql_pt.hrl").
+
+%%%
+%%% gen_mod
+%%%
+
+start(_Host, _Opts) ->
+    ejabberd_commands:register_commands(get_commands_spec()).
+
+stop(_Host) ->
+    ejabberd_commands:unregister_commands(get_commands_spec()).
+
+reload(_Host, _NewOpts, _OldOpts) ->
+    ok.
+
+depends(_Host, _Opts) ->
+    [].
+
+%%%
+%%% Register commands
+%%%
+
+get_commands_spec() ->
+    [#ejabberd_commands{name = update_sql, tags = [sql],
+                        desc = "Convert SQL DB to the new format",
+                        module = ?MODULE, function = update_sql,
+                        args = [],
+                        args_example = [],
+                        args_desc = [],
+                        result = {res, rescode},
+                        result_example = ok,
+                        result_desc = "Status code: 0 on success, 1 otherwise"}
+    ].
+
+update_sql() ->
+    lists:foreach(
+      fun(Host) ->
+              case ejabberd_sql_sup:get_pids(Host) of
+                  [] ->
+                      ok;
+                  _ ->
+                      update_sql(Host)
+              end
+      end, ?MYHOSTS),
+    ok.
+
+-record(state, {host :: binary(),
+                dbtype :: mysql | pgsql | sqlite | mssql | odbc,
+                escape}).
+
+update_sql(Host) ->
+    LHost = jid:nameprep(Host),
+    DBType = ejabberd_config:get_option({sql_type, LHost}, undefined),
+    IsSupported =
+        case DBType of
+            pgsql -> true;
+            _ -> false
+        end,
+    if
+        not IsSupported ->
+            io:format("Converting ~p DB is not supported~n", [DBType]),
+            error;
+        true ->
+            Escape =
+                case DBType of
+                    mssql -> fun ejabberd_sql:standard_escape/1;
+                    sqlite -> fun ejabberd_sql:standard_escape/1;
+                    _ -> fun ejabberd_sql:escape/1
+                end,
+            State = #state{host = LHost,
+                           dbtype = DBType,
+                           escape = Escape},
+            update_tables(State)
+    end.
+
+update_tables(State) ->
+    add_sh_column(State, "users"),
+    drop_pkey(State, "users"),
+    add_pkey(State, "users", ["server_host", "username"]),
+    drop_sh_default(State, "users"),
+
+    add_sh_column(State, "last"),
+    drop_pkey(State, "last"),
+    add_pkey(State, "last", ["server_host", "username"]),
+    drop_sh_default(State, "last"),
+
+    add_sh_column(State, "rosterusers"),
+    drop_index(State, "i_rosteru_user_jid"),
+    drop_index(State, "i_rosteru_username"),
+    drop_index(State, "i_rosteru_jid"),
+    create_unique_index(State, "rosterusers", "i_rosteru_sh_user_jid", ["server_host", "username", "jid"]),
+    create_index(State, "rosterusers", "i_rosteru_sh_username", ["server_host", "username"]),
+    create_index(State, "rosterusers", "i_rosteru_sh_jid", ["server_host", "jid"]),
+    drop_sh_default(State, "rosterusers"),
+
+    add_sh_column(State, "rostergroups"),
+    drop_index(State, "pk_rosterg_user_jid"),
+    create_index(State, "rostergroups", "i_rosterg_sh_user_jid", ["server_host", "username", "jid"]),
+    drop_sh_default(State, "rostergroups"),
+
+    add_sh_column(State, "sr_group"),
+    add_pkey(State, "sr_group", ["server_host", "name"]),
+    drop_sh_default(State, "sr_group"),
+
+    add_sh_column(State, "sr_user"),
+    drop_index(State, "i_sr_user_jid_grp"),
+    drop_index(State, "i_sr_user_jid"),
+    drop_index(State, "i_sr_user_grp"),
+    add_pkey(State, "sr_user", ["server_host", "jid", "grp"]),
+    create_index(State, "sr_user", "i_sr_user_sh_jid", ["server_host", "jid"]),
+    create_index(State, "sr_user", "i_sr_user_sh_grp", ["server_host", "grp"]),
+    drop_sh_default(State, "sr_user"),
+
+    add_sh_column(State, "spool"),
+    drop_index(State, "i_despool"),
+    create_index(State, "spool", "i_spool_sh_username", ["server_host", "username"]),
+    drop_sh_default(State, "spool"),
+
+    add_sh_column(State, "archive"),
+    drop_index(State, "i_username"),
+    drop_index(State, "i_username_timestamp"),
+    drop_index(State, "i_timestamp"),
+    drop_index(State, "i_peer"),
+    drop_index(State, "i_bare_peer"),
+    create_index(State, "archive", "i_archive_sh_username_timestamp", ["server_host", "username", "timestamp"]),
+    create_index(State, "archive", "i_archive_sh_timestamp", ["server_host", "timestamp"]),
+    create_index(State, "archive", "i_archive_sh_peer", ["server_host", "peer"]),
+    create_index(State, "archive", "i_archive_sh_bare_peer", ["server_host", "bare_peer"]),
+    drop_sh_default(State, "archive"),
+
+    add_sh_column(State, "archive_prefs"),
+    drop_pkey(State, "archive_prefs"),
+    add_pkey(State, "archive_prefs", ["server_host", "username"]),
+    drop_sh_default(State, "archive_prefs"),
+
+    add_sh_column(State, "vcard"),
+    drop_pkey(State, "vcard"),
+    add_pkey(State, "vcard", ["server_host", "username"]),
+    drop_sh_default(State, "vcard"),
+
+    add_sh_column(State, "vcard_search"),
+    drop_pkey(State, "vcard_search"),
+    drop_index(State, "i_vcard_search_lfn"),
+    drop_index(State, "i_vcard_search_lfamily"),
+    drop_index(State, "i_vcard_search_lgiven"),
+    drop_index(State, "i_vcard_search_lmiddle"),
+    drop_index(State, "i_vcard_search_lnickname"),
+    drop_index(State, "i_vcard_search_lbday"),
+    drop_index(State, "i_vcard_search_lctry"),
+    drop_index(State, "i_vcard_search_llocality"),
+    drop_index(State, "i_vcard_search_lemail"),
+    drop_index(State, "i_vcard_search_lorgname"),
+    drop_index(State, "i_vcard_search_lorgunit"),
+    add_pkey(State, "vcard_search", ["server_host", "username"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_lfn",       ["server_host", "lfn"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_lfamily",   ["server_host", "lfamily"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_lgiven",    ["server_host", "lgiven"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_lmiddle",   ["server_host", "lmiddle"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_lnickname", ["server_host", "lnickname"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_lbday",     ["server_host", "lbday"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_lctry",     ["server_host", "lctry"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_llocality", ["server_host", "llocality"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_lemail",    ["server_host", "lemail"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_lorgname",  ["server_host", "lorgname"]),
+    create_index(State, "vcard_search", "i_vcard_search_sh_lorgunit",  ["server_host", "lorgunit"]),
+    drop_sh_default(State, "vcard_search"),
+
+    add_sh_column(State, "privacy_default_list"),
+    drop_pkey(State, "privacy_default_list"),
+    add_pkey(State, "privacy_default_list", ["server_host", "username"]),
+    drop_sh_default(State, "privacy_default_list"),
+
+    add_sh_column(State, "privacy_list"),
+    drop_index(State, "i_privacy_list_username"),
+    drop_index(State, "i_privacy_list_username_name"),
+    create_index(State, "privacy_list", "i_privacy_list_sh_username", ["server_host", "username"]),
+    create_unique_index(State, "privacy_list", "i_privacy_list_sh_username_name", ["server_host", "username", "name"]),
+    drop_sh_default(State, "privacy_list"),
+
+    add_sh_column(State, "private_storage"),
+    drop_index(State, "i_private_storage_username"),
+    drop_index(State, "i_private_storage_username_namespace"),
+    add_pkey(State, "private_storage", ["server_host", "username", "namespace"]),
+    create_index(State, "private_storage", "i_private_storage_sh_username", ["server_host", "username"]),
+    drop_sh_default(State, "private_storage"),
+
+    add_sh_column(State, "roster_version"),
+    drop_pkey(State, "roster_version"),
+    add_pkey(State, "roster_version", ["server_host", "username"]),
+    drop_sh_default(State, "roster_version"),
+
+    add_sh_column(State, "muc_room"),
+    drop_sh_default(State, "muc_room"),
+
+    add_sh_column(State, "muc_registered"),
+    drop_sh_default(State, "muc_registered"),
+
+    add_sh_column(State, "muc_online_room"),
+    drop_sh_default(State, "muc_online_room"),
+
+    add_sh_column(State, "muc_online_users"),
+    drop_sh_default(State, "muc_online_users"),
+
+    add_sh_column(State, "irc_custom"),
+    drop_sh_default(State, "irc_custom"),
+
+    add_sh_column(State, "motd"),
+    drop_pkey(State, "motd"),
+    add_pkey(State, "motd", ["server_host", "username"]),
+    drop_sh_default(State, "motd"),
+
+    add_sh_column(State, "sm"),
+    drop_index(State, "i_sm_sid"),
+    drop_index(State, "i_sm_username"),
+    add_pkey(State, "sm", ["usec", "pid"]),
+    create_index(State, "sm", "i_sm_sh_username", ["server_host", "username"]),
+    drop_sh_default(State, "sm"),
+
+    add_sh_column(State, "carboncopy"),
+    drop_index(State, "i_carboncopy_ur"),
+    drop_index(State, "i_carboncopy_user"),
+    add_pkey(State, "carboncopy", ["server_host", "username", "resource"]),
+    create_index(State, "carboncopy", "i_carboncopy_sh_user", ["server_host", "username"]),
+    drop_sh_default(State, "carboncopy"),
+
+    add_sh_column(State, "push_session"),
+    drop_index(State, "i_push_usn"),
+    drop_index(State, "i_push_ut"),
+    add_pkey(State, "push_session", ["server_host", "username", "timestamp"]),
+    create_index(State, "push_session", "i_push_session_susn", ["server_host", "username", "service", "node"]),
+    drop_sh_default(State, "push_session"),
+
+    ok.
+
+add_sh_column(#state{dbtype = pgsql} = State, Table) ->
+    sql_query(
+      State#state.host,
+      ["ALTER TABLE ", Table, " ADD COLUMN server_host text NOT NULL DEFAULT '",
+       (State#state.escape)(State#state.host),
+       "';"]);
+add_sh_column(#state{dbtype = mysql} = State, Table) ->
+    sql_query(
+      State#state.host,
+      ["ALTER TABLE ", Table, " ADD COLUMN server_host text NOT NULL DEFAULT '",
+       (State#state.escape)(State#state.host),
+       "';"]).
+
+drop_pkey(#state{dbtype = pgsql} = State, Table) ->
+    sql_query(
+      State#state.host,
+      ["ALTER TABLE ", Table, " DROP CONSTRAINT ", Table, "_pkey;"]);
+drop_pkey(#state{dbtype = mysql} = State, Table) ->
+    sql_query(
+      State#state.host,
+      ["ALTER TABLE ", Table, " DROP PRIMARY KEY;"]).
+
+add_pkey(#state{dbtype = pgsql} = State, Table, Cols) ->
+    SCols = string:join(Cols, ", "),
+    sql_query(
+      State#state.host,
+      ["ALTER TABLE ", Table, " ADD PRIMARY KEY (", SCols, ");"]);
+add_pkey(#state{dbtype = mysql} = State, Table, Cols) ->
+    SCols = string:join(Cols, ", "),
+    sql_query(
+      State#state.host,
+      ["ALTER TABLE ", Table, " ADD PRIMARY KEY (", SCols, ");"]).
+
+drop_sh_default(#state{dbtype = pgsql} = State, Table) ->
+    sql_query(
+      State#state.host,
+      ["ALTER TABLE ", Table, " ALTER COLUMN server_host DROP DEFAULT;"]);
+drop_sh_default(#state{dbtype = mysql} = State, Table) ->
+    sql_query(
+      State#state.host,
+      ["ALTER TABLE ", Table, " ALTER COLUMN server_host DROP DEFAULT;"]).
+
+drop_index(#state{dbtype = pgsql} = State, Index) ->
+    sql_query(
+      State#state.host,
+      ["DROP INDEX ", Index, ";"]);
+drop_index(#state{dbtype = mysql} = State, Index) ->
+    sql_query(
+      State#state.host,
+      ["DROP INDEX ", Index, ";"]).
+
+create_unique_index(#state{dbtype = pgsql} = State, Table, Index, Cols) ->
+    SCols = string:join(Cols, ", "),
+    sql_query(
+      State#state.host,
+      ["CREATE UNIQUE INDEX ", Index, " ON ", Table, " USING btree (",
+       SCols, ");"]);
+create_unique_index(#state{dbtype = mysql} = State, Table, Index, Cols) ->
+    Cols2 = [C ++ "(75)" || C <- Cols],
+    SCols = string:join(Cols2, ", "),
+    sql_query(
+      State#state.host,
+      ["CREATE UNIQUE INDEX ", Index, " ON ", Table, "(",
+       SCols, ");"]).
+
+create_index(#state{dbtype = pgsql} = State, Table, Index, Cols) ->
+    SCols = string:join(Cols, ", "),
+    sql_query(
+      State#state.host,
+      ["CREATE INDEX ", Index, " ON ", Table, " USING btree (",
+       SCols, ");"]);
+create_index(#state{dbtype = mysql} = State, Table, Index, Cols) ->
+    Cols2 = [C ++ "(75)" || C <- Cols],
+    SCols = string:join(Cols2, ", "),
+    sql_query(
+      State#state.host,
+      ["CREATE INDEX ", Index, " ON ", Table, "(",
+       SCols, ");"]).
+
+sql_query(Host, Query) ->
+    io:format("executing \"~s\" on ~s~n", [Query, Host]),
+    case ejabberd_sql:sql_query(Host, Query) of
+        {error, Error} ->
+            io:format("error: ~p~n", [Error]),
+            ok;
+        _ ->
+            ok
+    end.
+
+mod_opt_type(_) -> [].
index 1dea0ba751779f2b9aa16e4af6f8bf8ba5a0d741..c5c9eb58f6290103e7ea94b86c9de355ef09669f 100644 (file)
@@ -51,6 +51,7 @@ set_motd_users(LServer, USRs) ->
                           ?SQL_UPSERT_T(
                              "motd",
                              ["!username=%(U)s",
+                              "!server_host=%(LServer)s",
                               "xml=''"])
                  end, USRs)
        end,
@@ -62,20 +63,23 @@ set_motd(LServer, Packet) ->
                 ?SQL_UPSERT_T(
                    "motd",
                    ["!username=''",
+                    "!server_host=%(LServer)s",
                     "xml=%(XML)s"])
        end,
     transaction(LServer, F).
 
 delete_motd(LServer) ->
     F = fun() ->
-                ejabberd_sql:sql_query_t(?SQL("delete from motd"))
+                ejabberd_sql:sql_query_t(
+                  ?SQL("delete from motd where %(LServer)H"))
        end,
     transaction(LServer, F).
 
 get_motd(LServer) ->
     case catch ejabberd_sql:sql_query(
                  LServer,
-                 ?SQL("select @(xml)s from motd where username=''")) of
+                 ?SQL("select @(xml)s from motd"
+                      " where username='' and %(LServer)H")) of
         {selected, [{XML}]} ->
            parse_element(XML);
        {selected, []} ->
@@ -88,7 +92,7 @@ is_motd_user(LUser, LServer) ->
     case catch ejabberd_sql:sql_query(
                  LServer,
                  ?SQL("select @(username)s from motd"
-                      " where username=%(LUser)s")) of
+                      " where username=%(LUser)s and %(LServer)H")) of
         {selected, [_|_]} ->
            {ok, true};
        {selected, []} ->
@@ -102,6 +106,7 @@ set_motd_user(LUser, LServer) ->
                 ?SQL_UPSERT_T(
                    "motd",
                    ["!username=%(LUser)s",
+                    "!server_host=%(LServer)s",
                     "xml=''"])
         end,
     transaction(LServer, F).
@@ -111,16 +116,24 @@ export(_Server) ->
       fun(Host, #motd{server = LServer, packet = El})
             when LServer == Host ->
               XML = fxml:element_to_binary(El),
-              [?SQL("delete from motd where username='';"),
-               ?SQL("insert into motd(username, xml) values ('', %(XML)s);")];
+              [?SQL("delete from motd where username='' and %(LServer)H;"),
+               ?SQL_INSERT(
+                  "motd",
+                  ["username=''",
+                   "server_host=%(LServer)s",
+                   "xml=%(XML)s"])];
          (_Host, _R) ->
               []
       end},
      {motd_users,
       fun(Host, #motd_users{us = {LUser, LServer}})
             when LServer == Host, LUser /= <<"">> ->
-              [?SQL("delete from motd where username=%(LUser)s;"),
-               ?SQL("insert into motd(username, xml) values (%(LUser)s, '');")];
+              [?SQL("delete from motd where username=%(LUser)s and %(LServer)H;"),
+               ?SQL_INSERT(
+                  "motd",
+                  ["username=%(LUser)s",
+                   "server_host=%(LServer)s",
+                   "xml=''"])];
          (_Host, _R) ->
               []
       end}].
index 3271d8a1cff69c3787a11580f83d107372d2c106..1b8e1e11186a2875ed9e3c7894838cfc8f1b774f 100644 (file)
@@ -42,6 +42,7 @@ enable(LUser, LServer, LResource, NS) ->
     NodeS = erlang:atom_to_binary(node(), latin1),
     case ?SQL_UPSERT(LServer, "carboncopy",
                     ["!username=%(LUser)s",
+                      "!server_host=%(LServer)s",
                      "!resource=%(LResource)s",
                      "namespace=%(NS)s",
                      "node=%(NodeS)s"]) of
@@ -56,7 +57,7 @@ disable(LUser, LServer, LResource) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("delete from carboncopy where username=%(LUser)s "
-               "and resource=%(LResource)s")) of
+               "and %(LServer)H and resource=%(LResource)s")) of
        {updated, _} ->
            ok;
        Err ->
@@ -68,7 +69,7 @@ list(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(resource)s, @(namespace)s, @(node)s from carboncopy "
-               "where username=%(LUser)s")) of
+               "where username=%(LUser)s and %(LServer)H")) of
        {selected, Rows} ->
            {ok, [{Resource, NS, binary_to_atom(Node, latin1)}
                  || {Resource, NS, Node} <- Rows]};
index f9a7d716fc62d5f0cab271156d03100dbb0427b9..1f8d7d16ac44a9a16471dc473c0c304c4c5688a1 100644 (file)
@@ -46,7 +46,7 @@ get_data(LServer, Host, From) ->
     case catch ejabberd_sql:sql_query(
                  LServer,
                  ?SQL("select @(data)s from irc_custom"
-                      " where jid=%(SJID)s and host=%(Host)s")) of
+                      " where jid=%(SJID)s and host=%(Host)s and %(LServer)H")) of
         {selected, [{SData}]} ->
             mod_irc:data_to_binary(From, ejabberd_sql:decode_term(SData));
         {'EXIT', _} -> error;
@@ -61,6 +61,7 @@ set_data(LServer, Host, From, Data) ->
                    "irc_custom",
                    ["!jid=%(SJID)s",
                     "!host=%(Host)s",
+                    "server_host=%(LServer)s",
                     "data=%(SData)s"]),
                ok
        end,
@@ -73,11 +74,16 @@ export(_Server) ->
               case str:suffix(Host, IRCHost) of
                   true ->
                       SJID = jid:encode(jid:make(U, S)),
+                      LServer = ejabberd_router:host_of_route(IRCHost),
                       SData = misc:term_to_expr(Data),
                       [?SQL("delete from irc_custom"
-                            " where jid=%(SJID)s and host=%(IRCHost)s;"),
-                       ?SQL("insert into irc_custom(jid, host, data)"
-                            " values (%(SJID)s, %(IRCHost)s, %(SData)s);")];
+                            " where jid=%(SJID)s and host=%(IRCHost)s and %(LServer)H;"),
+                       ?SQL_INSERT(
+                          "irc_custom",
+                          ["jid=%(SJID)s",
+                           "host=%(Host)s",
+                           "server_host=%(LServer)s",
+                           "data=%(SData)s"])];
                   false ->
                       []
               end
index b777ba30d4476458b4c73edb3a0bda98e56fe962..f0889e4ecefc69bee7123f62612c68e4a7075747 100644 (file)
@@ -46,7 +46,7 @@ get_last(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(seconds)d, @(state)s from last"
-               " where username=%(LUser)s")) of
+               " where username=%(LUser)s and %(LServer)H")) of
         {selected, []} ->
            error;
         {selected, [{TimeStamp, Status}]} ->
@@ -60,6 +60,7 @@ get_last(LUser, LServer) ->
 store_last_info(LUser, LServer, TimeStamp, Status) ->
     case ?SQL_UPSERT(LServer, "last",
                     ["!username=%(LUser)s",
+                      "!server_host=%(LServer)s",
                      "seconds=%(TimeStamp)d",
                      "state=%(Status)s"]) of
        ok ->
@@ -73,16 +74,19 @@ store_last_info(LUser, LServer, TimeStamp, Status) ->
 remove_user(LUser, LServer) ->
     ejabberd_sql:sql_query(
       LServer,
-      ?SQL("delete from last where username=%(LUser)s")).
+      ?SQL("delete from last where username=%(LUser)s and %(LServer)H")).
 
 export(_Server) ->
     [{last_activity,
       fun(Host, #last_activity{us = {LUser, LServer},
                                timestamp = TimeStamp, status = Status})
             when LServer == Host ->
-              [?SQL("delete from last where username=%(LUser)s;"),
-               ?SQL("insert into last(username, seconds, state)"
-                    " values (%(LUser)s, %(TimeStamp)d, %(Status)s);")];
+              [?SQL("delete from last where username=%(LUser)s and %(LServer)H;"),
+               ?SQL_INSERT("last",
+                           ["username=%(LUser)s",
+                            "server_host=%(LServer)s",
+                            "seconds=%(TimeStamp)d",
+                            "state=%(Status)s"])];
          (_Host, _R) ->
               []
       end}].
index 7e02b5791dcaa5f817eeccfc96b45912465053ef..53ccd94a4dacd26555c187caa55a74182da9ec08 100644 (file)
 -include("logger.hrl").
 -include("ejabberd_sql_pt.hrl").
 
+-ifdef(NEW_SQL_SCHEMA).
+-define(USE_NEW_SCHEMA, true).
+-else.
+-define(USE_NEW_SCHEMA, false).
+-endif.
+
 %%%===================================================================
 %%% API
 %%%===================================================================
@@ -47,23 +53,32 @@ init(_Host, _Opts) ->
 remove_user(LUser, LServer) ->
     ejabberd_sql:sql_query(
       LServer,
-      ?SQL("delete from archive where username=%(LUser)s")),
+      ?SQL("delete from archive where username=%(LUser)s and %(LServer)H")),
     ejabberd_sql:sql_query(
       LServer,
-      ?SQL("delete from archive_prefs where username=%(LUser)s")).
+      ?SQL("delete from archive_prefs where username=%(LUser)s and %(LServer)H")).
 
 remove_room(LServer, LName, LHost) ->
     LUser = jid:encode({LName, LHost, <<>>}),
     remove_user(LUser, LServer).
 
 delete_old_messages(ServerHost, TimeStamp, Type) ->
-    TypeClause = if Type == all -> <<"">>;
-                   true -> [<<" and kind='">>, misc:atom_to_binary(Type), <<"'">>]
-                end,
-    TS = integer_to_binary(now_to_usec(TimeStamp)),
-    ejabberd_sql:sql_query(
-      ServerHost, [<<"delete from archive where timestamp<">>,
-                  TS, TypeClause, <<";">>]),
+    TS = now_to_usec(TimeStamp),
+    case Type of
+        all ->
+            ejabberd_sql:sql_query(
+              ServerHost,
+              ?SQL("delete from archive"
+                   " where timestamp < %(TS)d and %(ServerHost)H"));
+        _ ->
+            SType = misc:atom_to_binary(Type),
+            ejabberd_sql:sql_query(
+              ServerHost,
+              ?SQL("delete from archive"
+                   " where timestamp < %(TS)d"
+                   " and kind=%(SType)s"
+                   " and %(ServerHost)H"))
+    end,
     ok.
 
 extended_fields() ->
@@ -86,16 +101,17 @@ store(Pkt, LServer, {LUser, LHost}, Type, Peer, Nick, _Dir) ->
     SType = misc:atom_to_binary(Type),
     case ejabberd_sql:sql_query(
            LServer,
-           ?SQL("insert into archive (username, timestamp,"
-                " peer, bare_peer, xml, txt, kind, nick) values ("
-               "%(SUser)s, "
-               "%(TSinteger)d, "
-               "%(LPeer)s, "
-               "%(BarePeer)s, "
-               "%(XML)s, "
-               "%(Body)s, "
-               "%(SType)s, "
-               "%(Nick)s)")) of
+           ?SQL_INSERT(
+              "archive",
+              ["username=%(SUser)s",
+               "server_host=%(LServer)s",
+               "timestamp=%(TSinteger)d",
+               "peer=%(LPeer)s",
+               "bare_peer=%(BarePeer)s",
+               "xml=%(XML)s",
+               "txt=%(Body)s",
+               "kind=%(SType)s",
+               "nick=%(Nick)s"])) of
        {updated, _} ->
            {ok, ID};
        Err ->
@@ -113,6 +129,7 @@ write_prefs(LUser, _LServer, #archive_prefs{default = Default,
             ServerHost,
             "archive_prefs",
             ["!username=%(LUser)s",
+             "!server_host=%(ServerHost)s",
              "def=%(SDefault)s",
              "always=%(SAlways)s",
              "never=%(SNever)s"]) of
@@ -126,7 +143,7 @@ get_prefs(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(def)s, @(always)s, @(never)s from archive_prefs"
-                " where username=%(LUser)s")) of
+                " where username=%(LUser)s and %(LServer)H")) of
        {selected, [{SDefault, SAlways, SNever}]} ->
            Default = erlang:binary_to_existing_atom(SDefault, utf8),
            Always = ejabberd_sql:decode_term(SAlways),
@@ -192,8 +209,13 @@ export(_Server) ->
                 SDefault = erlang:atom_to_binary(Default, utf8),
                 SAlways = misc:term_to_expr(Always),
                 SNever = misc:term_to_expr(Never),
-                [?SQL("insert into archive_prefs (username, def, always, never) values"
-                "(%(LUser)s, %(SDefault)s, %(SAlways)s, %(SNever)s);")];
+                [?SQL_INSERT(
+                    "archive_prefs",
+                    ["username=%(LUser)s",
+                     "server_host=%(LServer)s",
+                     "def=%(SDefault)s",
+                     "always=%(SAlways)s",
+                     "never=%(SNever)s"])];
           (_Host, _R) ->
               []
       end},
@@ -212,11 +234,17 @@ export(_Server) ->
                 XML = fxml:element_to_binary(Pkt),
                 Body = fxml:get_subtag_cdata(Pkt, <<"body">>),
                 SType = misc:atom_to_binary(Type),
-                [?SQL("insert into archive (username, timestamp, "
-                                "peer, bare_peer, xml, txt, kind, nick) "
-                                "values (%(SUser)s, %(TStmp)d, %(LPeer)s, "
-                                "%(BarePeer)s, %(XML)s, %(Body)s, %(SType)s, "
-                                "%(Nick)s);")];
+                [?SQL_INSERT(
+                    "archive",
+                    ["username=%(SUser)s",
+                     "server_host=%(LServer)s",
+                     "timestamp=%(TStmp)d",
+                     "peer=%(LPeer)s",
+                     "bare_peer=%(BarePeer)s",
+                     "xml=%(XML)s",
+                     "txt=%(Body)s",
+                     "kind=%(SType)s",
+                     "nick=%(Nick)s"])];
          (_Host, _R) ->
               []
       end}].
@@ -303,11 +331,24 @@ make_sql_query(User, LServer, MAMQuery, RSM) ->
                        []
                end,
     SUser = Escape(User),
+    SServer = Escape(LServer),
 
-    Query = [<<"SELECT ">>, TopClause, <<" timestamp, xml, peer, kind, nick"
-             " FROM archive WHERE username='">>,
-            SUser, <<"'">>, WithClause, WithTextClause, StartClause, EndClause,
-            PageClause],
+    Query =
+        case ?USE_NEW_SCHEMA of
+            true ->
+                [<<"SELECT ">>, TopClause,
+                 <<" timestamp, xml, peer, kind, nick"
+                  " FROM archive WHERE username='">>,
+                 SUser, <<"' and server_host='">>,
+                 SServer, <<"'">>, WithClause, WithTextClause,
+                 StartClause, EndClause, PageClause];
+            false ->
+                [<<"SELECT ">>, TopClause,
+                 <<" timestamp, xml, peer, kind, nick"
+                  " FROM archive WHERE username='">>,
+                 SUser, <<"'">>, WithClause, WithTextClause,
+                 StartClause, EndClause, PageClause]
+        end,
 
     QueryPage =
        case Direction of
@@ -322,9 +363,19 @@ make_sql_query(User, LServer, MAMQuery, RSM) ->
                [Query, <<" ORDER BY timestamp ASC ">>,
                 LimitClause, <<";">>]
        end,
-    {QueryPage,
-     [<<"SELECT COUNT(*) FROM archive WHERE username='">>,
-      SUser, <<"'">>, WithClause, WithTextClause, StartClause, EndClause, <<";">>]}.
+    case ?USE_NEW_SCHEMA of
+        true ->
+            {QueryPage,
+             [<<"SELECT COUNT(*) FROM archive WHERE username='">>,
+              SUser, <<"' and server_host='">>,
+              SServer, <<"'">>, WithClause, WithTextClause,
+              StartClause, EndClause, <<";">>]};
+        false ->
+            {QueryPage,
+             [<<"SELECT COUNT(*) FROM archive WHERE username='">>,
+              SUser, <<"'">>, WithClause, WithTextClause,
+              StartClause, EndClause, <<";">>]}
+    end.
 
 -spec get_max_direction_id(rsm_set() | undefined) ->
                                  {integer() | undefined,
index 7ec598bf32be653c7e48bbe831aed500fff49ab4..41ad92bf9765a8b86624bb1e605f937eb1a0c792 100644 (file)
@@ -68,16 +68,18 @@ store_room(LServer, Host, Name, Opts, ChangesHints) ->
                    "muc_room",
                    ["!name=%(Name)s",
                     "!host=%(Host)s",
-           "opts=%(SOpts)s"]),
-       case ChangesHints of
-           Changes when is_list(Changes) ->
-               [change_room(Host, Name, Change) || Change <- Changes];
-           _ ->
-               ejabberd_sql:sql_query_t(?SQL("delete from muc_room_subscribers where "
-                                             "room=%(Name)s and host=%(Host)s")),
-               [change_room(Host, Name, {add_subscription, JID, Nick, Nodes})
-                || {JID, Nick, Nodes} <- Subs]
-       end
+                    "server_host=%(LServer)s",
+                    "opts=%(SOpts)s"]),
+                case ChangesHints of
+                    Changes when is_list(Changes) ->
+                        [change_room(Host, Name, Change) || Change <- Changes];
+                    _ ->
+                        ejabberd_sql:sql_query_t(
+                          ?SQL("delete from muc_room_subscribers where "
+                               "room=%(Name)s and host=%(Host)s")),
+                        [change_room(Host, Name, {add_subscription, JID, Nick, Nodes})
+                         || {JID, Nick, Nodes} <- Subs]
+                end
        end,
     ejabberd_sql:sql_transaction(LServer, F).
 
@@ -226,6 +228,7 @@ set_nick(LServer, Host, From, Nick) ->
                                   "muc_registered",
                                   ["!jid=%(JID)s",
                                    "!host=%(Host)s",
+                                   "server_host=%(LServer)s",
                                    "nick=%(Nick)s"]),
                                ok;
                           true ->
@@ -257,6 +260,7 @@ register_online_room(ServerHost, Room, Host, Pid) ->
                     "muc_online_room",
                     ["!name=%(Room)s",
                      "!host=%(Host)s",
+                      "server_host=%(ServerHost)s",
                      "node=%(NodeS)s",
                      "pid=%(PidS)s"]) of
        ok ->
@@ -331,6 +335,7 @@ register_online_user(ServerHost, {U, S, R}, Room, Host) ->
                      "!resource=%(R)s",
                      "!name=%(Room)s",
                      "!host=%(Host)s",
+                      "server_host=%(ServerHost)s",
                      "node=%(NodeS)s"]) of
        ok ->
            ok;
@@ -379,9 +384,12 @@ export(_Server) ->
                       SOpts = misc:term_to_expr(Opts),
                       [?SQL("delete from muc_room where name=%(Name)s"
                             " and host=%(RoomHost)s;"),
-                       ?SQL("insert into muc_room(name, host, opts) "
-                            "values ("
-                            "%(Name)s, %(RoomHost)s, %(SOpts)s);")];
+                       ?SQL_INSERT(
+                          "muc_room",
+                          ["name=%(Name)s",
+                           "host=%(Host)s",
+                           "server_host=%(Host)s",
+                           "opts=%(SOpts)s"])];
                   false ->
                       []
               end
@@ -394,9 +402,12 @@ export(_Server) ->
                       SJID = jid:encode(jid:make(U, S)),
                       [?SQL("delete from muc_registered where"
                             " jid=%(SJID)s and host=%(RoomHost)s;"),
-                       ?SQL("insert into muc_registered(jid, host, "
-                            "nick) values ("
-                            "%(SJID)s, %(RoomHost)s, %(Nick)s);")];
+                       ?SQL_INSERT(
+                          "muc_registered",
+                          ["jid=%(SJID)s",
+                           "host=%(Host)s",
+                           "server_host=%(Host)s",
+                           "nick=%(Nick)s"])];
                   false ->
                       []
               end
index f43f4c929b1cd519f44f5819032a5b68a9cf3b34..53a0d3451e0b55496348f93f87bced59293f2be2 100644 (file)
@@ -56,8 +56,11 @@ store_message(#offline_msg{us = {LUser, LServer}} = M) ->
            xmpp:encode(NewPacket)),
     case ejabberd_sql:sql_query(
           LServer,
-          ?SQL("insert into spool(username, xml) values "
-               "(%(LUser)s, %(XML)s)")) of
+           ?SQL_INSERT(
+              "spool",
+              ["username=%(LUser)s",
+               "server_host=%(LServer)s",
+               "xml=%(XML)s"])) of
        {updated, _} ->
            ok;
        _ ->
@@ -87,10 +90,8 @@ remove_expired_messages(_LServer) ->
 remove_old_messages(Days, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
-          [<<"DELETE FROM spool"
-             " WHERE created_at < "
-             "NOW() - INTERVAL '">>,
-           integer_to_list(Days), <<"' DAY;">>]) of
+          ?SQL("DELETE FROM spool"
+                " WHERE created_at < NOW() - INTERVAL %(Days)d DAY")) of
        {updated, N} ->
            ?INFO_MSG("~p message(s) deleted from offline spool", [N]);
        _Error ->
@@ -101,13 +102,13 @@ remove_old_messages(Days, LServer) ->
 remove_user(LUser, LServer) ->
     ejabberd_sql:sql_query(
       LServer,
-      ?SQL("delete from spool where username=%(LUser)s")).
+      ?SQL("delete from spool where username=%(LUser)s and %(LServer)H")).
 
 read_message_headers(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(xml)s, @(seq)d from spool"
-               " where username=%(LUser)s order by seq")) of
+               " where username=%(LUser)s and %(LServer)H order by seq")) of
        {selected, Rows} ->
            lists:flatmap(
              fun({XML, Seq}) ->
@@ -129,6 +130,7 @@ read_message(LUser, LServer, Seq) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(xml)s from spool where username=%(LUser)s"
+                " and %(LServer)H"
                 " and seq=%(Seq)d")) of
        {selected, [{RawXML}|_]} ->
            case xml_to_offline_msg(RawXML) of
@@ -144,7 +146,7 @@ read_message(LUser, LServer, Seq) ->
 remove_message(LUser, LServer, Seq) ->
     ejabberd_sql:sql_query(
       LServer,
-      ?SQL("delete from spool where username=%(LUser)s"
+      ?SQL("delete from spool where username=%(LUser)s and %(LServer)H"
            " and seq=%(Seq)d")),
     ok.
 
@@ -152,7 +154,7 @@ read_all_messages(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(xml)s from spool where "
-               "username=%(LUser)s order by seq")) of
+               "username=%(LUser)s and %(LServer)H order by seq")) of
         {selected, Rs} ->
             lists:flatmap(
               fun({XML}) ->
@@ -173,7 +175,7 @@ count_messages(LUser, LServer) ->
     case catch ejabberd_sql:sql_query(
                  LServer,
                  ?SQL("select @(count(*))d from spool "
-                      "where username=%(LUser)s")) of
+                      "where username=%(LUser)s and %(LServer)H")) of
         {selected, [{Res}]} ->
             Res;
         _ -> 0
@@ -183,7 +185,8 @@ export(_Server) ->
     [{offline_msg,
       fun(Host, #offline_msg{us = {LUser, LServer}})
             when LServer == Host ->
-                     [?SQL("delete from spool where username=%(LUser)s;")];
+                     [?SQL("delete from spool where username=%(LUser)s"
+                            " and %(LServer)H;")];
          (_Host, _R) ->
               []
       end},
@@ -199,8 +202,11 @@ export(_Server) ->
                                  Packet1, jid:make(LServer),
                                  TimeStamp, <<"Offline Storage">>),
                      XML = fxml:element_to_binary(xmpp:encode(Packet2)),
-                     [?SQL("insert into spool(username, xml) values ("
-                           "%(LUser)s, %(XML)s);")]
+                     [?SQL_INSERT(
+                          "spool",
+                          ["username=%(LUser)s",
+                           "server_host=%(LServer)s",
+                           "xml=%(XML)s"])]
              catch _:{xmpp_codec, Why} ->
                      ?ERROR_MSG("failed to decode packet ~p of user ~s@~s: ~s",
                                 [El, LUser, LServer, xmpp:format_error(Why)]),
@@ -249,9 +255,10 @@ get_and_del_spool_msg_t(LServer, LUser) ->
                Result =
                    ejabberd_sql:sql_query_t(
                       ?SQL("select @(username)s, @(xml)s from spool where "
-                           "username=%(LUser)s order by seq;")),
+                           "username=%(LUser)s and %(LServer)H order by seq;")),
                ejabberd_sql:sql_query_t(
-                  ?SQL("delete from spool where username=%(LUser)s;")),
+                  ?SQL("delete from spool where"
+                       " username=%(LUser)s and %(LServer)H;")),
                Result
        end,
     ejabberd_sql:sql_transaction(LServer, F).
index b19c95fe50c22850e1c6ca5b31e54aa6e07c10a7..7939cbb264eaab8260e1c254f6291b3c2cc6a3b5 100644 (file)
@@ -56,13 +56,13 @@ unset_default(LUser, LServer) ->
 
 set_default(LUser, LServer, Name) ->
     F = fun () ->
-               case get_privacy_list_names_t(LUser) of
+               case get_privacy_list_names_t(LUser, LServer) of
                    {selected, []} ->
                        {error, notfound};
                    {selected, Names} ->
                        case lists:member({Name}, Names) of
                            true ->
-                               set_default_privacy_list(LUser, Name);
+                               set_default_privacy_list(LUser, LServer, Name);
                            false ->
                                {error, notfound}
                        end
@@ -72,14 +72,14 @@ set_default(LUser, LServer, Name) ->
 
 remove_list(LUser, LServer, Name) ->
     F = fun () ->
-               case get_default_privacy_list_t(LUser) of
+               case get_default_privacy_list_t(LUser, LServer) of
                    {selected, []} ->
-                       remove_privacy_list_t(LUser, Name);
+                       remove_privacy_list_t(LUser, LServer, Name);
                    {selected, [{Default}]} ->
                        if Name == Default ->
                                {error, conflict};
                           true ->
-                               remove_privacy_list_t(LUser, Name)
+                               remove_privacy_list_t(LUser, LServer, Name)
                        end
                end
        end,
@@ -91,13 +91,14 @@ set_lists(#privacy{us = {LUser, LServer},
     F = fun() ->
                lists:foreach(
                  fun({Name, List}) ->
-                         add_privacy_list(LUser, Name),
+                         add_privacy_list(LUser, LServer, Name),
                          {selected, [<<"id">>], [[I]]} =
-                             get_privacy_list_id_t(LUser, Name),
+                             get_privacy_list_id_t(LUser, LServer, Name),
                          RItems = lists:map(fun item_to_raw/1, List),
                          set_privacy_list(I, RItems),
                          if is_binary(Default) ->
-                                 set_default_privacy_list(LUser, Default);
+                                 set_default_privacy_list(
+                                    LUser, LServer, Default);
                             true ->
                                  ok
                          end
@@ -108,11 +109,11 @@ set_lists(#privacy{us = {LUser, LServer},
 set_list(LUser, LServer, Name, List) ->
     RItems = lists:map(fun item_to_raw/1, List),
     F = fun () ->
-               ID = case get_privacy_list_id_t(LUser, Name) of
+               ID = case get_privacy_list_id_t(LUser, LServer, Name) of
                          {selected, []} ->
-                            add_privacy_list(LUser, Name),
+                            add_privacy_list(LUser, LServer, Name),
                             {selected, [{I}]} =
-                                get_privacy_list_id_t(LUser, Name),
+                                get_privacy_list_id_t(LUser, LServer, Name),
                             I;
                         {selected, [{I}]} -> I
                     end,
@@ -199,9 +200,12 @@ export(Server) ->
             when LServer == Host ->
               if Default /= none ->
                       [?SQL("delete from privacy_default_list where"
-                            " username=%(LUser)s;"),
-                       ?SQL("insert into privacy_default_list(username, name) "
-                            "values (%(LUser)s, %(Default)s);")];
+                            " username=%(LUser)s and %(LServer)H;"),
+                       ?SQL_INSERT(
+                          "privacy_default_list",
+                          ["username=%(LUser)s",
+                           "server_host=%(LServer)s",
+                           "name=%(Default)s"])];
                  true ->
                       []
               end ++
@@ -210,11 +214,14 @@ export(Server) ->
                             RItems = lists:map(fun item_to_raw/1, List),
                             ID = get_id(),
                             [?SQL("delete from privacy_list where"
-                                  " username=%(LUser)s and"
+                                  " username=%(LUser)s and %(LServer)H and"
                                   " name=%(Name)s;"),
-                             ?SQL("insert into privacy_list(username, "
-                                  "name, id) values ("
-                                  "%(LUser)s, %(Name)s, %(ID)d);"),
+                             ?SQL_INSERT(
+                                "privacy_list",
+                                ["username=%(LUser)s",
+                                 "server_host=%(LServer)s",
+                                 "name=%(Name)s",
+                                 "id=%(ID)d"]),
                              ?SQL("delete from privacy_list_data where"
                                   " id=%(ID)d;")] ++
                                 [?SQL("insert into privacy_list_data(id, t, "
@@ -312,28 +319,28 @@ get_default_privacy_list(LUser, LServer) ->
     ejabberd_sql:sql_query(
       LServer,
       ?SQL("select @(name)s from privacy_default_list "
-           "where username=%(LUser)s")).
+           "where username=%(LUser)s and %(LServer)H")).
 
-get_default_privacy_list_t(LUser) ->
+get_default_privacy_list_t(LUser, LServer) ->
     ejabberd_sql:sql_query_t(
       ?SQL("select @(name)s from privacy_default_list "
-           "where username=%(LUser)s")).
+           "where username=%(LUser)s and %(LServer)H")).
 
 get_privacy_list_names(LUser, LServer) ->
     ejabberd_sql:sql_query(
       LServer,
       ?SQL("select @(name)s from privacy_list"
-           " where username=%(LUser)s")).
+           " where username=%(LUser)s and %(LServer)H")).
 
-get_privacy_list_names_t(LUser) ->
+get_privacy_list_names_t(LUser, LServer) ->
     ejabberd_sql:sql_query_t(
       ?SQL("select @(name)s from privacy_list"
-           " where username=%(LUser)s")).
+           " where username=%(LUser)s and %(LServer)H")).
 
-get_privacy_list_id_t(LUser, Name) ->
+get_privacy_list_id_t(LUser, LServer, Name) ->
     ejabberd_sql:sql_query_t(
       ?SQL("select @(id)d from privacy_list"
-           " where username=%(LUser)s and name=%(Name)s")).
+           " where username=%(LUser)s and %(LServer)H and name=%(Name)s")).
 
 get_privacy_list_data(LUser, LServer, Name) ->
     ejabberd_sql:sql_query(
@@ -343,37 +350,41 @@ get_privacy_list_data(LUser, LServer, Name) ->
            "@(match_presence_out)b from privacy_list_data "
            "where id ="
            " (select id from privacy_list"
-           " where username=%(LUser)s and name=%(Name)s) "
+           " where username=%(LUser)s and %(LServer)H and name=%(Name)s) "
            "order by ord")).
 
-set_default_privacy_list(LUser, Name) ->
+set_default_privacy_list(LUser, LServer, Name) ->
     ?SQL_UPSERT_T(
        "privacy_default_list",
        ["!username=%(LUser)s",
+        "!server_host=%(LServer)s",
         "name=%(Name)s"]).
 
 unset_default_privacy_list(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("delete from privacy_default_list"
-               " where username=%(LUser)s")) of
+               " where username=%(LUser)s and %(LServer)H")) of
        {updated, _} -> ok;
        Err -> Err
     end.
 
-remove_privacy_list_t(LUser, Name) ->
+remove_privacy_list_t(LUser, LServer, Name) ->
     case ejabberd_sql:sql_query_t(
           ?SQL("delete from privacy_list where"
-               " username=%(LUser)s and name=%(Name)s")) of
+               " username=%(LUser)s and %(LServer)H and name=%(Name)s")) of
        {updated, 0} -> {error, notfound};
        {updated, _} -> ok;
        Err -> Err
     end.
 
-add_privacy_list(LUser, Name) ->
+add_privacy_list(LUser, LServer, Name) ->
     ejabberd_sql:sql_query_t(
-      ?SQL("insert into privacy_list(username, name) "
-           "values (%(LUser)s, %(Name)s)")).
+      ?SQL_INSERT(
+         "privacy_list",
+         ["username=%(LUser)s",
+          "server_host=%(LServer)s",
+          "name=%(Name)s"])).
 
 set_privacy_list(ID, RItems) ->
     ejabberd_sql:sql_query_t(
@@ -395,12 +406,12 @@ set_privacy_list(ID, RItems) ->
 del_privacy_lists(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
-          ?SQL("delete from privacy_list where username=%(LUser)s")) of
+          ?SQL("delete from privacy_list where username=%(LUser)s and %(LServer)H")) of
        {updated, _} ->
            case ejabberd_sql:sql_query(
                   LServer,
                   ?SQL("delete from privacy_default_list "
-                       "where username=%(LUser)s")) of
+                       "where username=%(LUser)s and %(LServer)H")) of
                {updated, _} -> ok;
                Err -> Err
            end;
index 907eeaf3a3178ad1a26da2b9f56873d5b1cde131..5ed584c3034068b2a597b047766255669cc5a9c4 100644 (file)
@@ -49,6 +49,7 @@ set_data(LUser, LServer, Data) ->
                          ?SQL_UPSERT_T(
                             "private_storage",
                             ["!username=%(LUser)s",
+                              "!server_host=%(LServer)s",
                              "!namespace=%(XMLNS)s",
                              "data=%(SData)s"])
                  end, Data)
@@ -64,7 +65,8 @@ get_data(LUser, LServer, XMLNS) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(data)s from private_storage"
-               " where username=%(LUser)s and namespace=%(XMLNS)s")) of
+               " where username=%(LUser)s and %(LServer)H"
+                " and namespace=%(XMLNS)s")) of
        {selected, [{SData}]} ->
            parse_element(LUser, LServer, SData);
        {selected, []} ->
@@ -77,7 +79,7 @@ get_all_data(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(namespace)s, @(data)s from private_storage"
-               " where username=%(LUser)s")) of
+               " where username=%(LUser)s and %(LServer)H")) of
        {selected, []} ->
            error;
         {selected, Res} ->
@@ -95,7 +97,8 @@ get_all_data(LUser, LServer) ->
 del_data(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
-          ?SQL("delete from private_storage where username=%(LUser)s")) of
+          ?SQL("delete from private_storage"
+                " where username=%(LUser)s and %(LServer)H")) of
        {updated, _} ->
            ok;
        _ ->
@@ -109,10 +112,13 @@ export(_Server) ->
             when LServer == Host ->
               SData = fxml:element_to_binary(Data),
              [?SQL("delete from private_storage where"
-                   " username=%(LUser)s and namespace=%(XMLNS)s;"),
-              ?SQL("insert into private_storage(username, "
-                   "namespace, data) values ("
-                   "%(LUser)s, %(XMLNS)s, %(SData)s);")];
+                   " username=%(LUser)s and %(LServer)H and namespace=%(XMLNS)s;"),
+               ?SQL_INSERT(
+                  "private_storage",
+                  ["username=%(LUser)s",
+                   "server_host=%(LServer)s",
+                   "namespace=%(XMLNS)s",
+                   "data=%(SData)s"])];
          (_Host, _R) ->
               []
       end}].
index e4634a34e4a5f9a16888d9eec499ad1aaec2a96d..a94b686fcdf2bb10cfd54dcb79746b660ccbd919 100644 (file)
@@ -43,6 +43,7 @@ store_session(LUser, LServer, NowTS, PushJID, Node, XData) ->
     Service = jid:encode(PushLJID),
     case ?SQL_UPSERT(LServer, "push_session",
                     ["!username=%(LUser)s",
+                      "!server_host=%(LServer)s",
                      "!timestamp=%(TS)d",
                      "!service=%(Service)s",
                      "!node=%(Node)s",
@@ -60,7 +61,8 @@ lookup_session(LUser, LServer, PushJID, Node) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(timestamp)d, @(xml)s from push_session "
-               "where username=%(LUser)s and service=%(Service)s "
+               "where username=%(LUser)s and %(LServer)H "
+                "and service=%(Service)s "
                "and node=%(Node)s")) of
        {selected, [{TS, XML}]} ->
            NowTS = misc:usec_to_now(TS),
@@ -78,7 +80,7 @@ lookup_session(LUser, LServer, NowTS) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(service)s, @(node)s, @(xml)s "
-               "from push_session where username=%(LUser)s "
+               "from push_session where username=%(LUser)s and %(LServer)H "
                "and timestamp=%(TS)d")) of
        {selected, [{Service, Node, XML}]} ->
            PushLJID = jid:tolower(jid:decode(Service)),
@@ -97,7 +99,8 @@ lookup_sessions(LUser, LServer, PushJID) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(timestamp)d, @(xml)s, @(node)s from push_session "
-               "where username=%(LUser)s and service=%(Service)s")) of
+               "where username=%(LUser)s and %(LServer)H "
+                "and service=%(Service)s")) of
        {selected, Rows} ->
            {ok, lists:map(
                   fun({TS, XML, Node}) ->
@@ -114,7 +117,8 @@ lookup_sessions(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(timestamp)d, @(xml)s, @(node)s, @(service)s "
-               "from push_session where username=%(LUser)s")) of
+               "from push_session "
+                "where username=%(LUser)s and %(LServer)H")) of
        {selected, Rows} ->
            {ok, lists:map(
                   fun({TS, XML, Node, Service}) ->
@@ -132,7 +136,8 @@ lookup_sessions(LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(username)s, @(timestamp)d, @(xml)s, "
-               "@(node)s, @(service)s from push_session")) of
+               "@(node)s, @(service)s from push_session "
+                "where %(LServer)H")) of
        {selected, Rows} ->
            {ok, lists:map(
                   fun({LUser, TS, XML, Node, Service}) ->
@@ -151,7 +156,7 @@ delete_session(LUser, LServer, NowTS) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("delete from push_session where "
-               "username=%(LUser)s and timestamp=%(TS)d")) of
+               "username=%(LUser)s and %(LServer)H and timestamp=%(TS)d")) of
        {updated, _} ->
            ok;
        Err ->
@@ -163,7 +168,8 @@ delete_old_sessions(LServer, Time) ->
     TS = misc:now_to_usec(Time),
     case ejabberd_sql:sql_query(
           LServer,
-          ?SQL("delete from push_session where timestamp<%(TS)d")) of
+          ?SQL("delete from push_session where timestamp<%(TS)d "
+                "and %(LServer)H")) of
        {updated, _} ->
            ok;
        Err ->
@@ -183,12 +189,18 @@ export(_Server) ->
              Service = jid:encode(PushLJID),
              XML = encode_xdata(XData),
              [?SQL("delete from push_session where "
-                   "username=%(LUser)s and timestamp=%(TS)d and "
+                   "username=%(LUser)s and %(LServer)H and "
+                    "timestamp=%(TS)d and "
                    "service=%(Service)s and node=%(Node)s and "
                    "xml=%(XML)s;"),
-              ?SQL("insert into push_session(username, timestamp, "
-                   "service, node, xml) values ("
-                   "%(LUser)s, %(TS)d, %(Service)s, %(Node)s, %(XML)s);")];
+              ?SQL_INSERT(
+                  "push_session",
+                  ["username=%(LUser)s",
+                   "server_host=%(LServer)s",
+                   "timestamp=%(TS)d",
+                   "service=%(Service)s",
+                   "node=%(Node)s",
+                   "xml=%(XML)s"])];
         (_Host, _R) ->
              []
       end}].
index c03ea11549ca3cd2693549c13c0c6696251d8be7..a86b50d98af0aace5be145ce4a7fb6f07e91b84e 100644 (file)
@@ -1180,12 +1180,18 @@ import_stop(_LServer, _DBType) ->
     ets:delete(rostergroups_tmp),
     ok.
 
+-ifdef(NEW_SQL_SCHEMA).
+-define(ROW_LENGTH, 10).
+-else.
+-define(ROW_LENGTH, 9).
+-endif.
+
 import(LServer, {sql, _}, _DBType, <<"rostergroups">>, [LUser, SJID, Group]) ->
     LJID = jid:tolower(jid:decode(SJID)),
     ets:insert(rostergroups_tmp, {{LUser, LServer, LJID}, Group}),
     ok;
 import(LServer, {sql, _}, DBType, <<"rosterusers">>, Row) ->
-    I = mod_roster_sql:raw_to_record(LServer, lists:sublist(Row, 9)),
+    I = mod_roster_sql:raw_to_record(LServer, lists:sublist(Row, ?ROW_LENGTH)),
     Groups = [G || {_, G} <- ets:lookup(rostergroups_tmp, I#roster.usj)],
     RosterItem = I#roster{groups = Groups},
     Mod = gen_mod:db_mod(DBType, ?MODULE),
index 77899624ab3b0c39be82f89e2142267ea19acdb5..82a3c495102a165a01e9a3ce100e137c9cf56903 100644 (file)
@@ -49,7 +49,7 @@ read_roster_version(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
           ?SQL("select @(version)s from roster_version"
-               " where username = %(LUser)s")) of
+               " where username = %(LUser)s and %(LServer)H")) of
        {selected, [{Version}]} -> {ok, Version};
        {selected, []} -> error;
        _ -> {error, db_failure}
@@ -57,11 +57,11 @@ read_roster_version(LUser, LServer) ->
 
 write_roster_version(LUser, LServer, InTransaction, Ver) ->
     if InTransaction ->
-           set_roster_version(LUser, Ver);
+           set_roster_version(LUser, LServer, Ver);
        true ->
            transaction(
              LServer,
-             fun () -> set_roster_version(LUser, Ver) end)
+             fun () -> set_roster_version(LUser, LServer, Ver) end)
     end.
 
 get_roster(LUser, LServer) ->
@@ -69,7 +69,8 @@ get_roster(LUser, LServer) ->
           LServer,
           ?SQL("select @(username)s, @(jid)s, @(nick)s, @(subscription)s, "
                "@(ask)s, @(askmessage)s, @(server)s, @(subscribe)s, "
-               "@(type)s from rosterusers where username=%(LUser)s")) of
+               "@(type)s from rosterusers "
+                "where username=%(LUser)s and %(LServer)H")) of
         {selected, Items} when is_list(Items) ->
             JIDGroups = case get_roster_jid_groups(LServer, LUser) of
                             {selected, JGrps} when is_list(JGrps) ->
@@ -130,36 +131,42 @@ remove_user(LUser, LServer) ->
       LServer,
       fun () ->
               ejabberd_sql:sql_query_t(
-                ?SQL("delete from rosterusers where username=%(LUser)s")),
+                ?SQL("delete from rosterusers"
+                     " where username=%(LUser)s and %(LServer)H")),
               ejabberd_sql:sql_query_t(
-                ?SQL("delete from rostergroups where username=%(LUser)s"))
+                ?SQL("delete from rostergroups"
+                     " where username=%(LUser)s and %(LServer)H"))
       end),
     ok.
 
-update_roster(LUser, _LServer, LJID, Item) ->
+update_roster(LUser, LServer, LJID, Item) ->
     SJID = jid:encode(LJID),
     ItemVals = record_to_row(Item),
     ItemGroups = Item#roster.groups,
     roster_subscribe(ItemVals),
     ejabberd_sql:sql_query_t(
       ?SQL("delete from rostergroups"
-           " where username=%(LUser)s and jid=%(SJID)s")),
+           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")),
     lists:foreach(
       fun(ItemGroup) ->
               ejabberd_sql:sql_query_t(
-                ?SQL("insert into rostergroups(username, jid, grp) "
-                     "values (%(LUser)s, %(SJID)s, %(ItemGroup)s)"))
+                ?SQL_INSERT(
+                   "rostergroups",
+                   ["username=%(LUser)s",
+                    "server_host=%(LServer)s",
+                    "jid=%(SJID)s",
+                    "grp=%(ItemGroup)s"]))
       end,
       ItemGroups).
 
-del_roster(LUser, _LServer, LJID) ->
+del_roster(LUser, LServer, LJID) ->
     SJID = jid:encode(LJID),
     ejabberd_sql:sql_query_t(
       ?SQL("delete from rosterusers"
-           " where username=%(LUser)s and jid=%(SJID)s")),
+           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")),
     ejabberd_sql:sql_query_t(
       ?SQL("delete from rostergroups"
-           " where username=%(LUser)s and jid=%(SJID)s")).
+           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")).
 
 read_subscription_and_groups(LUser, LServer, LJID) ->
     SJID = jid:encode(LJID),
@@ -200,9 +207,13 @@ export(_Server) ->
      {roster_version,
       fun(Host, #roster_version{us = {LUser, LServer}, version = Ver})
             when LServer == Host ->
-              [?SQL("delete from roster_version where username=%(LUser)s;"),
-               ?SQL("insert into roster_version(username, version) values("
-                    " %(LUser)s, %(Ver)s);")];
+              [?SQL("delete from roster_version"
+                    " where username=%(LUser)s and %(LServer)H;"),
+               ?SQL_INSERT(
+                  "roster_version",
+                  ["username=%(LUser)s",
+                   "server_host=%(LServer)s",
+                   "version=%(Ver)s"])];
          (_Host, _R) ->
               []
       end}].
@@ -213,27 +224,29 @@ import(_, _, _) ->
 %%%===================================================================
 %%% Internal functions
 %%%===================================================================
-set_roster_version(LUser, Version) ->
+set_roster_version(LUser, LServer, Version) ->
     ?SQL_UPSERT_T(
        "roster_version",
        ["!username=%(LUser)s",
+        "!server_host=%(LServer)s",
         "version=%(Version)s"]).
 
 get_roster_jid_groups(LServer, LUser) ->
     ejabberd_sql:sql_query(
       LServer,
       ?SQL("select @(jid)s, @(grp)s from rostergroups where "
-           "username=%(LUser)s")).
+           "username=%(LUser)s and %(LServer)H")).
 
-get_roster_groups(_LServer, LUser, SJID) ->
+get_roster_groups(LServer, LUser, SJID) ->
     ejabberd_sql:sql_query_t(
       ?SQL("select @(grp)s from rostergroups"
-           " where username=%(LUser)s and jid=%(SJID)s")).
+           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")).
 
-roster_subscribe({LUser, SJID, Name, SSubscription, SAsk, AskMessage}) ->
+roster_subscribe({LUser, LServer, SJID, Name, SSubscription, SAsk, AskMessage}) ->
     ?SQL_UPSERT_T(
        "rosterusers",
        ["!username=%(LUser)s",
+        "!server_host=%(LServer)s",
         "!jid=%(SJID)s",
         "nick=%(Name)s",
         "subscription=%(SSubscription)s",
@@ -243,57 +256,67 @@ roster_subscribe({LUser, SJID, Name, SSubscription, SAsk, AskMessage}) ->
         "subscribe=''",
         "type='item'"]).
 
-get_roster_by_jid(_LServer, LUser, SJID) ->
+get_roster_by_jid(LServer, LUser, SJID) ->
     ejabberd_sql:sql_query_t(
       ?SQL("select @(username)s, @(jid)s, @(nick)s, @(subscription)s,"
            " @(ask)s, @(askmessage)s, @(server)s, @(subscribe)s,"
            " @(type)s from rosterusers"
-           " where username=%(LUser)s and jid=%(SJID)s")).
+           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")).
 
 get_rostergroup_by_jid(LServer, LUser, SJID) ->
     ejabberd_sql:sql_query(
       LServer,
       ?SQL("select @(grp)s from rostergroups"
-           " where username=%(LUser)s and jid=%(SJID)s")).
+           " where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")).
 
 get_subscription(LServer, LUser, SJID) ->
     ejabberd_sql:sql_query(
       LServer,
       ?SQL("select @(subscription)s from rosterusers "
-           "where username=%(LUser)s and jid=%(SJID)s")).
+           "where username=%(LUser)s and %(LServer)H and jid=%(SJID)s")).
 
-update_roster_sql({LUser, SJID, Name, SSubscription, SAsk, AskMessage},
+update_roster_sql({LUser, LServer, SJID, Name, SSubscription, SAsk, AskMessage},
                  ItemGroups) ->
     [?SQL("delete from rosterusers where"
-          " username=%(LUser)s and jid=%(SJID)s;"),
-     ?SQL("insert into rosterusers("
-          " username, jid, nick,"
-          " subscription, ask, askmessage,"
-          " server, subscribe, type) "
-          "values ("
-          "%(LUser)s, "
-          "%(SJID)s, "
-          "%(Name)s, "
-          "%(SSubscription)s, "
-          "%(SAsk)s, "
-          "%(AskMessage)s, "
-          "'N', '', 'item');"),
+          " username=%(LUser)s and %(LServer)H and jid=%(SJID)s;"),
+     ?SQL_INSERT(
+        "rosterusers",
+        ["username=%(LUser)s",
+         "server_host=%(LServer)s",
+         "jid=%(SJID)s",
+         "nick=%(Name)s",
+         "subscription=%(SSubscription)s",
+         "ask=%(SAsk)s",
+         "askmessage=%(AskMessage)s",
+         "server='N'",
+         "subscribe=''",
+         "type='item'"]),
      ?SQL("delete from rostergroups where"
-          " username=%(LUser)s and jid=%(SJID)s;")]
+          " username=%(LUser)s and %(LServer)H and jid=%(SJID)s;")]
       ++
-      [?SQL("insert into rostergroups(username, jid, grp) "
-            "values (%(LUser)s, %(SJID)s, %(ItemGroup)s);")
+      [?SQL_INSERT(
+          "rostergroups",
+          ["username=%(LUser)s",
+           "server_host=%(LServer)s",
+           "jid=%(SJID)s",
+           "grp=%(ItemGroup)s"])
        || ItemGroup <- ItemGroups].
 
 raw_to_record(LServer,
-             [User, SJID, Nick, SSubscription, SAsk, SAskMessage,
+             [User, LServer, SJID, Nick, SSubscription, SAsk, SAskMessage,
               _SServer, _SSubscribe, _SType]) ->
     raw_to_record(LServer,
-                  {User, SJID, Nick, SSubscription, SAsk, SAskMessage,
+                  {User, LServer, SJID, Nick, SSubscription, SAsk, SAskMessage,
                    _SServer, _SSubscribe, _SType});
 raw_to_record(LServer,
              {User, SJID, Nick, SSubscription, SAsk, SAskMessage,
               _SServer, _SSubscribe, _SType}) ->
+    raw_to_record(LServer,
+                  {User, LServer, SJID, Nick, SSubscription, SAsk, SAskMessage,
+                   _SServer, _SSubscribe, _SType});
+raw_to_record(LServer,
+             {User, LServer, SJID, Nick, SSubscription, SAsk, SAskMessage,
+              _SServer, _SSubscribe, _SType}) ->
     try jid:decode(SJID) of
       JID ->
          LJID = jid:tolower(JID),
@@ -331,7 +354,7 @@ raw_to_record(LServer,
     end.
 
 record_to_row(
-  #roster{us = {LUser, _LServer},
+  #roster{us = {LUser, LServer},
           jid = JID, name = Name, subscription = Subscription,
           ask = Ask, askmessage = AskMessage}) ->
     SJID = jid:encode(jid:tolower(JID)),
@@ -349,7 +372,7 @@ record_to_row(
             in -> <<"I">>;
             none -> <<"N">>
           end,
-    {LUser, SJID, Name, SSubscription, SAsk, AskMessage}.
+    {LUser, LServer, SJID, Name, SSubscription, SAsk, AskMessage}.
 
 format_row_error(User, Server, Why) ->
     [case Why of
index 51b3324559dfc80024a5d4df6b67a597ce3d0eed..488e0ec761c9eab047270557e319407977cdb1d3 100644 (file)
@@ -50,7 +50,7 @@ init(_Host, _Opts) ->
 list_groups(Host) ->
     case ejabberd_sql:sql_query(
           Host,
-           ?SQL("select @(name)s from sr_group")) of
+           ?SQL("select @(name)s from sr_group where %(Host)H")) of
        {selected, Rs} -> [G || {G} <- Rs];
        _ -> []
     end.
@@ -58,7 +58,7 @@ list_groups(Host) ->
 groups_with_opts(Host) ->
     case ejabberd_sql:sql_query(
            Host,
-           ?SQL("select @(name)s, @(opts)s from sr_group"))
+           ?SQL("select @(name)s, @(opts)s from sr_group where %(Host)H"))
        of
       {selected, Rs} ->
          [{G, mod_shared_roster:opts_to_binary(ejabberd_sql:decode_term(Opts))}
@@ -72,6 +72,7 @@ create_group(Host, Group, Opts) ->
                ?SQL_UPSERT_T(
                    "sr_group",
                    ["!name=%(Group)s",
+                    "!server_host=%(Host)s",
                     "opts=%(SOpts)s"])
        end,
     ejabberd_sql:sql_transaction(Host, F).
@@ -79,9 +80,9 @@ create_group(Host, Group, Opts) ->
 delete_group(Host, Group) ->
     F = fun () ->
                ejabberd_sql:sql_query_t(
-                  ?SQL("delete from sr_group where name=%(Group)s")),
+                  ?SQL("delete from sr_group where name=%(Group)s and %(Host)H")),
                ejabberd_sql:sql_query_t(
-                  ?SQL("delete from sr_user where grp=%(Group)s"))
+                  ?SQL("delete from sr_user where grp=%(Group)s and %(Host)H"))
        end,
     case ejabberd_sql:sql_transaction(Host, F) of
         {atomic,{updated,_}} -> {atomic, ok};
@@ -91,7 +92,8 @@ delete_group(Host, Group) ->
 get_group_opts(Host, Group) ->
     case catch ejabberd_sql:sql_query(
                 Host,
-                ?SQL("select @(opts)s from sr_group where name=%(Group)s")) of
+                ?SQL("select @(opts)s from sr_group"
+                      " where name=%(Group)s and %(Host)H")) of
        {selected, [{SOpts}]} ->
            mod_shared_roster:opts_to_binary(ejabberd_sql:decode_term(SOpts));
        _ -> error
@@ -103,6 +105,7 @@ set_group_opts(Host, Group, Opts) ->
                ?SQL_UPSERT_T(
                    "sr_group",
                    ["!name=%(Group)s",
+                    "!server_host=%(Host)s",
                     "opts=%(SOpts)s"])
        end,
     ejabberd_sql:sql_transaction(Host, F).
@@ -111,7 +114,8 @@ get_user_groups(US, Host) ->
     SJID = make_jid_s(US),
     case catch ejabberd_sql:sql_query(
                 Host,
-                ?SQL("select @(grp)s from sr_user where jid=%(SJID)s")) of
+                ?SQL("select @(grp)s from sr_user"
+                      " where jid=%(SJID)s and %(Host)H")) of
        {selected, Rs} -> [G || {G} <- Rs];
        _ -> []
     end.
@@ -119,7 +123,8 @@ get_user_groups(US, Host) ->
 get_group_explicit_users(Host, Group) ->
     case catch ejabberd_sql:sql_query(
                 Host,
-                ?SQL("select @(jid)s from sr_user where grp=%(Group)s")) of
+                ?SQL("select @(jid)s from sr_user"
+                      " where grp=%(Group)s and %(Host)H")) of
        {selected, Rs} ->
            lists:map(
              fun({JID}) ->
@@ -134,7 +139,8 @@ get_user_displayed_groups(LUser, LServer, GroupsOpts) ->
     SJID = make_jid_s(LUser, LServer),
     case catch ejabberd_sql:sql_query(
                 LServer,
-                ?SQL("select @(grp)s from sr_user where jid=%(SJID)s")) of
+                ?SQL("select @(grp)s from sr_user"
+                      " where jid=%(SJID)s and %(LServer)H")) of
        {selected, Rs} ->
            [{Group, proplists:get_value(Group, GroupsOpts, [])}
             || {Group} <- Rs];
@@ -146,7 +152,7 @@ is_user_in_group(US, Group, Host) ->
     case catch ejabberd_sql:sql_query(
                  Host,
                  ?SQL("select @(jid)s from sr_user where jid=%(SJID)s"
-                      " and grp=%(Group)s")) of
+                      " and %(Host)H and grp=%(Group)s")) of
        {selected, []} -> false;
        _ -> true
     end.
@@ -155,15 +161,18 @@ add_user_to_group(Host, US, Group) ->
     SJID = make_jid_s(US),
     ejabberd_sql:sql_query(
       Host,
-      ?SQL("insert into sr_user(jid, grp) values ("
-           "%(SJID)s, %(Group)s)")).
+      ?SQL_INSERT(
+         "sr_user",
+         ["jid=%(SJID)s",
+          "server_host=%(Host)s",
+          "grp=%(Group)s"])).
 
 remove_user_from_group(Host, US, Group) ->
     SJID = make_jid_s(US),
     F = fun () ->
                ejabberd_sql:sql_query_t(
-                  ?SQL("delete from sr_user where jid=%(SJID)s and"
-                       " grp=%(Group)s")),
+                  ?SQL("delete from sr_user where jid=%(SJID)s and %(Host)H"
+                       " and grp=%(Group)s")),
                ok
        end,
     ejabberd_sql:sql_transaction(Host, F).
@@ -173,9 +182,12 @@ export(_Server) ->
       fun(Host, #sr_group{group_host = {Group, LServer}, opts = Opts})
             when LServer == Host ->
               SOpts = misc:term_to_expr(Opts),
-              [?SQL("delete from sr_group where name=%(Group)s;"),
-               ?SQL("insert into sr_group(name, opts) values ("
-                    "%(Group)s, %(SOpts)s);")];
+              [?SQL("delete from sr_group where name=%(Group)s and %(Host)H;"),
+               ?SQL_INSERT(
+                  "sr_group",
+                  ["name=%(Group)s",
+                   "server_host=%(Host)s",
+                   "opts=%(SOpts)s"])];
          (_Host, _R) ->
               []
       end},
@@ -184,9 +196,12 @@ export(_Server) ->
             when LServer == Host ->
               SJID = make_jid_s(U, S),
               [?SQL("select @(jid)s from sr_user where jid=%(SJID)s"
-                    " and grp=%(Group)s;"),
-               ?SQL("insert into sr_user(jid, grp) values ("
-                    "%(SJID)s, %(Group)s);")];
+                    " and %(Host)H and grp=%(Group)s;"),
+               ?SQL_INSERT(
+                  "sr_user",
+                  ["jid=%(SJID)s",
+                   "server_host=%(Host)s",
+                   "grp=%(Group)s"])];
          (_Host, _R) ->
               []
       end}].
index 6092c3500b1c8942aeddf10013be55ab55fc1686..07d90b69ebc9e1e17c7bb7e685ebdadd25065a8a 100644 (file)
 -include("ejabberd_sql_pt.hrl").
 -include("translate.hrl").
 
+-ifdef(NEW_SQL_SCHEMA).
+-define(USE_NEW_SCHEMA, true).
+-else.
+-define(USE_NEW_SCHEMA, false).
+-endif.
+
 %%%===================================================================
 %%% API
 %%%===================================================================
@@ -54,7 +60,8 @@ is_search_supported(_LServer) ->
 get_vcard(LUser, LServer) ->
     case ejabberd_sql:sql_query(
           LServer,
-          ?SQL("select @(vcard)s from vcard where username=%(LUser)s")) of
+          ?SQL("select @(vcard)s from vcard"
+                " where username=%(LUser)s and %(LServer)H")) of
        {selected, [{SVCARD}]} ->
            case fxml_stream:parse_element(SVCARD) of
                {error, _Reason} -> error;
@@ -94,10 +101,12 @@ set_vcard(LUser, LServer, VCARD,
       fun() ->
               ?SQL_UPSERT(LServer, "vcard",
                           ["!username=%(LUser)s",
+                           "!server_host=%(LServer)s",
                            "vcard=%(SVCARD)s"]),
               ?SQL_UPSERT(LServer, "vcard_search",
                           ["username=%(User)s",
                            "!lusername=%(LUser)s",
+                           "!server_host=%(LServer)s",
                            "fn=%(FN)s",
                            "lfn=%(LFN)s",
                            "family=%(Family)s",
@@ -183,9 +192,11 @@ remove_user(LUser, LServer) ->
       LServer,
       fun() ->
               ejabberd_sql:sql_query_t(
-                ?SQL("delete from vcard where username=%(LUser)s")),
+                ?SQL("delete from vcard"
+                     " where username=%(LUser)s and %(LServer)H")),
               ejabberd_sql:sql_query_t(
-                ?SQL("delete from vcard_search where lusername=%(LUser)s"))
+                ?SQL("delete from vcard_search"
+                     " where lusername=%(LUser)s and %(LServer)H"))
       end).
 
 export(_Server) ->   
@@ -193,9 +204,12 @@ export(_Server) ->
       fun(Host, #vcard{us = {LUser, LServer}, vcard = VCARD})
             when LServer == Host ->
               SVCARD = fxml:element_to_binary(VCARD),
-              [?SQL("delete from vcard where username=%(LUser)s;"),
-               ?SQL("insert into vcard(username, vcard) values ("
-                    "%(LUser)s, %(SVCARD)s);")];
+              [?SQL("delete from vcard"
+                    " where username=%(LUser)s and %(LServer)H;"),
+               ?SQL_INSERT("vcard",
+                           ["username=%(LUser)s",
+                            "server_host=%(LServer)s",
+                            "vcard=%(SVCARD)s"])];
          (_Host, _R) ->
               []
       end},
@@ -212,26 +226,34 @@ export(_Server) ->
                               orgname = OrgName, lorgname = LOrgName,
                               orgunit = OrgUnit, lorgunit = LOrgUnit})
             when LServer == Host ->
-              [?SQL("delete from vcard_search where lusername=%(LUser)s;"),
-               ?SQL("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 ("
-                    " %(LUser)s, %(User)s,"
-                    " %(FN)s, %(LFN)s,"
-                    " %(Family)s, %(LFamily)s,"
-                    " %(Given)s, %(LGiven)s,"
-                    " %(Middle)s, %(LMiddle)s,"
-                    " %(Nickname)s, %(LNickname)s,"
-                    " %(BDay)s, %(LBDay)s,"
-                    " %(CTRY)s, %(LCTRY)s,"
-                    " %(Locality)s, %(LLocality)s,"
-                    " %(EMail)s, %(LEMail)s,"
-                    " %(OrgName)s, %(LOrgName)s,"
-                    " %(OrgUnit)s, %(LOrgUnit)s);")];
+              [?SQL("delete from vcard_search"
+                    " where lusername=%(LUser)s and %(LServer)H;"),
+               ?SQL_INSERT("vcard_search",
+                           ["username=%(User)s",
+                            "lusername=%(LUser)s",
+                            "server_host=%(LServer)s",
+                            "fn=%(FN)s",
+                            "lfn=%(LFN)s",
+                            "family=%(Family)s",
+                            "lfamily=%(LFamily)s",
+                            "given=%(Given)s",
+                            "lgiven=%(LGiven)s",
+                            "middle=%(Middle)s",
+                            "lmiddle=%(LMiddle)s",
+                            "nickname=%(Nickname)s",
+                            "lnickname=%(LNickname)s",
+                            "bday=%(BDay)s",
+                            "lbday=%(LBDay)s",
+                            "ctry=%(CTRY)s",
+                            "lctry=%(LCTRY)s",
+                            "locality=%(Locality)s",
+                            "llocality=%(LLocality)s",
+                            "email=%(EMail)s",
+                            "lemail=%(LEMail)s",
+                            "orgname=%(OrgName)s",
+                            "lorgname=%(LOrgName)s",
+                            "orgunit=%(OrgUnit)s",
+                            "lorgunit=%(LOrgUnit)s"])];
          (_Host, _R) ->
               []
       end}].
@@ -245,10 +267,19 @@ import(_, _, _) ->
 make_matchspec(LServer, Data) ->
     filter_fields(Data, <<"">>, LServer).
 
-filter_fields([], Match, _LServer) ->
-    case Match of
-       <<"">> -> <<"">>;
-       _ -> [<<" where ">>, Match]
+filter_fields([], Match, LServer) ->
+    case ?USE_NEW_SCHEMA of
+        true ->
+            SServer = ejabberd_sql:escape(LServer),
+            case Match of
+                <<"">> -> [<<"where server_host='">>, SServer, <<"'">>];
+                _ -> [<<" where server_host='">>, SServer, <<"' and ">>, Match]
+            end;
+        false ->
+            case Match of
+                <<"">> -> <<"">>;
+                _ -> [<<" where ">>, Match]
+            end
     end;
 filter_fields([{SVar, [Val]} | Ds], Match, LServer)
   when is_binary(Val) and (Val /= <<"">>) ->
index 47fc5dd44ce6e424a25eb471cadd34b85031ac3e..ff549242ddc20fbda63dcee0de40e5a54b1d8689 100644 (file)
@@ -25,6 +25,7 @@
 {debug, @debug@}.
 {hipe, @hipe@}.
 {erlang_deprecated_types, @erlang_deprecated_types@}.
+{new_sql_schema, @new_sql_schema@}.
 
 %% Ad-hoc directories with source files
 {tools, @tools@}.