]> granicus.if.org Git - ejabberd/commitdiff
* src/odbc/ejabberd_odbc.erl: get rid of SERIALIZABLE isolation level on MySQL connec...
authorEvgeniy Khramtsov <xramtsov@gmail.com>
Fri, 26 Dec 2008 09:38:54 +0000 (09:38 +0000)
committerEvgeniy Khramtsov <xramtsov@gmail.com>
Fri, 26 Dec 2008 09:38:54 +0000 (09:38 +0000)
* src/odbc/odbc_queries.erl: replaces all delete->insert chains with update->insert.
* src/mod_privacy_odbc.erl: moved sql queries to odbc_queries.erl.
* src/mod_roster_odbc.erl: changed interface for odbc_queries.erl.

SVN Revision: 1755

ChangeLog
src/mod_privacy_odbc.erl
src/mod_roster_odbc.erl
src/odbc/ejabberd_odbc.erl
src/odbc/odbc_queries.erl

index 27125049c1f875bb6df267c3345a67868fa4b73f..4688874c983d948941045842a454f36153b5814a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-12-26  Evgeniy Khramtsov <ekhramtsov@process-one.net>
+
+       * src/odbc/ejabberd_odbc.erl: get rid of SERIALIZABLE isolation
+       level on MySQL connections.
+       * src/odbc/odbc_queries.erl: replaces all delete->insert chains
+       with update->insert.
+       * src/mod_privacy_odbc.erl: moved sql queries to odbc_queries.erl.
+       * src/mod_roster_odbc.erl: changed interface for odbc_queries.erl.
+
 2008-12-24  Badlop  <badlop@process-one.net>
 
        * src/aclocal.m4: Fixes in configure script: fix
index b5ad6544b86547d2e63074a057c4c945b8faedb7..662ccf506271e1aba42826bc9480364da9d1ccf4 100644 (file)
@@ -768,132 +768,66 @@ item_to_raw(#listitem{type = Type,
     SMatchMessage = if MatchMessage -> "1"; true -> "0" end,
     SMatchPresenceIn = if MatchPresenceIn -> "1"; true -> "0" end,
     SMatchPresenceOut = if MatchPresenceOut -> "1"; true -> "0" end,
-    ["'", SType, "', "
-     "'", SValue, "', "
-     "'", SAction, "', "
-     "'", SOrder, "', "
-     "'", SMatchAll, "', "
-     "'", SMatchIQ, "', "
-     "'", SMatchMessage, "', "
-     "'", SMatchPresenceIn, "', "
-     "'", SMatchPresenceOut, "'"].
-
+    [SType, SValue, SAction, SOrder, SMatchAll, SMatchIQ,
+     SMatchMessage, SMatchPresenceIn, SMatchPresenceOut].
 
 sql_get_default_privacy_list(LUser, LServer) ->
     Username = ejabberd_odbc:escape(LUser),
-    ejabberd_odbc:sql_query(
-      LServer,
-      ["select name from privacy_default_list "
-       "where username='", Username, "';"]).
+    odbc_queries:get_default_privacy_list(LServer, Username).
 
 sql_get_default_privacy_list_t(LUser) ->
     Username = ejabberd_odbc:escape(LUser),
-    ejabberd_odbc:sql_query_t(
-      ["select name from privacy_default_list "
-       "where username='", Username, "';"]).
+    odbc_queries:get_default_privacy_list_t(Username).
 
 sql_get_privacy_list_names(LUser, LServer) ->
     Username = ejabberd_odbc:escape(LUser),
-    ejabberd_odbc:sql_query(
-      LServer,
-      ["select name from privacy_list "
-       "where username='", Username, "';"]).
+    odbc_queries:get_privacy_list_names(LServer, Username).
 
 sql_get_privacy_list_names_t(LUser) ->
     Username = ejabberd_odbc:escape(LUser),
-    ejabberd_odbc:sql_query_t(
-      ["select name from privacy_list "
-       "where username='", Username, "';"]).
+    odbc_queries:get_privacy_list_names_t(Username).
 
 sql_get_privacy_list_id(LUser, LServer, Name) ->
     Username = ejabberd_odbc:escape(LUser),
     SName = ejabberd_odbc:escape(Name),
-    ejabberd_odbc:sql_query(
-      LServer,
-      ["select id from privacy_list "
-       "where username='", Username, "' and name='", SName, "';"]).
+    odbc_queries:get_privacy_list_id(LServer, Username, SName).
 
 sql_get_privacy_list_id_t(LUser, Name) ->
     Username = ejabberd_odbc:escape(LUser),
     SName = ejabberd_odbc:escape(Name),
-    ejabberd_odbc:sql_query_t(
-      ["select id from privacy_list "
-       "where username='", Username, "' and name='", SName, "';"]).
+    odbc_queries:get_privacy_list_id_t(Username, SName).
 
 sql_get_privacy_list_data(LUser, LServer, Name) ->
     Username = ejabberd_odbc:escape(LUser),
     SName = ejabberd_odbc:escape(Name),
-    ejabberd_odbc:sql_query(
-      LServer,
-      ["select t, value, action, ord, match_all, match_iq, "
-       "match_message, match_presence_in, match_presence_out "
-       "from privacy_list_data "
-       "where id = (select id from privacy_list where "
-       "            username='", Username, "' and name='", SName, "') "
-       "order by ord;"]).
+    odbc_queries:get_privacy_list_data(LServer, Username, SName).
 
 sql_get_privacy_list_data_by_id(ID, LServer) ->
-    ejabberd_odbc:sql_query(
-      LServer,
-      ["select t, value, action, ord, match_all, match_iq, "
-       "match_message, match_presence_in, match_presence_out "
-       "from privacy_list_data "
-       "where id='", ID, "' order by ord;"]).
+    odbc_queries:get_privacy_list_data_by_id(LServer, ID).
 
 sql_set_default_privacy_list(LUser, Name) ->
     Username = ejabberd_odbc:escape(LUser),
     SName = ejabberd_odbc:escape(Name),
-    ejabberd_odbc:sql_query_t(
-      ["delete from privacy_default_list "
-       "      where username='", Username, "';"]),
-    ejabberd_odbc:sql_query_t(
-      ["insert into privacy_default_list(username, name) "
-       "values ('", Username, "', '", SName, "');"]).
+    odbc_queries:set_default_privacy_list(Username, SName).
 
 sql_unset_default_privacy_list(LUser, LServer) ->
     Username = ejabberd_odbc:escape(LUser),
-    ejabberd_odbc:sql_query(
-      LServer,
-      ["delete from privacy_default_list "
-       "      where username='", Username, "';"]).
+    odbc_queries:unset_default_privacy_list(LServer, Username).
 
 sql_remove_privacy_list(LUser, Name) ->
     Username = ejabberd_odbc:escape(LUser),
     SName = ejabberd_odbc:escape(Name),
-    ejabberd_odbc:sql_query_t(
-      ["delete from privacy_list "
-       "where username='", Username, "' and name='", SName, "';"]).
+    odbc_queries:remove_privacy_list(Username, SName).
 
 sql_add_privacy_list(LUser, Name) ->
     Username = ejabberd_odbc:escape(LUser),
     SName = ejabberd_odbc:escape(Name),
-    ejabberd_odbc:sql_query_t(
-      ["insert into privacy_list(username, name) "
-       "values ('", Username, "', '", SName, "');"]).
+    odbc_queries:add_privacy_list(Username, SName).
 
 sql_set_privacy_list(ID, RItems) ->
-    ejabberd_odbc:sql_query_t(
-      ["delete from privacy_list_data "
-       "where id='", ID, "';"]),
-    lists:foreach(fun(Items) ->
-                         ejabberd_odbc:sql_query_t(
-                           ["insert into privacy_list_data("
-                            "id, t, value, action, ord, match_all, match_iq, "
-                            "match_message, match_presence_in, "
-                            "match_presence_out "
-                            ") "
-                            "values ('", ID, "', ", Items, ");"])
-                 end, RItems).
+    odbc_queries:set_privacy_list(ID, RItems).
 
 sql_del_privacy_lists(LUser, LServer) ->
     Username = ejabberd_odbc:escape(LUser),
     Server = ejabberd_odbc:escape(LServer),
-    ejabberd_odbc:sql_query(
-      LServer,
-      ["delete from privacy_list where username='", Username, "';"]),
-    ejabberd_odbc:sql_query(
-      LServer,
-      ["delete from privacy_list_data where value='", Username++"@"++Server, "';"]),
-    ejabberd_odbc:sql_query(
-      LServer,
-      ["delete from privacy_default_list where username='", Username, "';"]).
+    odbc_queries:del_privacy_lists(LServer, Server, Username).
index ca1b2e1881ab3154973a2151b0e7424c9cb82074..5b190671f44c68612891b84a29fc134674052f69 100644 (file)
@@ -642,9 +642,9 @@ set_items(User, Server, SubEl) ->
     LServer = jlib:nameprep(Server),
     catch odbc_queries:sql_transaction(
            LServer,
-            lists:flatmap(fun(El) ->
-                              process_item_set_t(LUser, LServer, El)
-                      end, Els)).
+           lists:flatmap(fun(El) ->
+                                 process_item_set_t(LUser, LServer, El)
+                         end, Els)).
 
 process_item_set_t(LUser, LServer, {xmlelement, _Name, Attrs, Els}) ->
     JID1 = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)),
@@ -858,13 +858,7 @@ record_to_string(#roster{us = {User, _Server},
               none        -> "N"
           end,
     SAskMessage = ejabberd_odbc:escape(AskMessage),
-    ["'", Username, "',"
-     "'", SJID, "',"
-     "'", Nick, "',"
-     "'", SSubscription, "',"
-     "'", SAsk, "',"
-     "'", SAskMessage, "',"
-     "'N', '', 'item'"].
+    [Username, SJID, Nick, SSubscription, SAsk, SAskMessage, "N", "", "item"].
 
 groups_to_string(#roster{us = {User, _Server},
                         jid = JID,
@@ -874,12 +868,11 @@ groups_to_string(#roster{us = {User, _Server},
 
     %% Empty groups do not need to be converted to string to be inserted in
     %% the database
-    lists:foldl(fun([], Acc) -> Acc;
-                  (Group, Acc) ->
-                       String = ["'", Username, "',"
-                                 "'", SJID, "',"
-                                 "'", ejabberd_odbc:escape(Group), "'"],
-                       [String|Acc] end, [], Groups).
+    lists:foldl(
+      fun([], Acc) -> Acc;
+        (Group, Acc) ->
+             G = ejabberd_odbc:escape(Group),
+             [[Username, SJID, G]|Acc] end, [], Groups).
 
 webadmin_page(_, Host,
              #request{us = _US,
index 940d94d74eec6c6baf830693087f6bd689c123ef..c675c61c07394f1414a5a79289154b0e44ce676b 100644 (file)
@@ -93,12 +93,12 @@ sql_query_t(Query) ->
        {error, "No SQL-driver information available."} ->
            % workaround for odbc bug
            {updated, 0};
-       {error, _} ->
-           throw(aborted);
+       {error, _} = Err ->
+           exit(Err);
        Rs when is_list(Rs) ->
-           case lists:keymember(error, 1, Rs) of
-               true ->
-                   throw(aborted);
+           case lists:keysearch(error, 1, Rs) of
+               {value, Err} ->
+                   exit(Err);
                _ ->
                    QRes
            end;
@@ -330,11 +330,6 @@ mysql_connect(Server, Port, DB, Username, Password, StartInterval) ->
        {ok, Ref} ->
            erlang:monitor(process, Ref),
             mysql_conn:fetch(Ref, ["set names 'utf8';"], self()),
-           % needed to ensure the order of queries, specifically at
-           % roster subscription time (this can also be set-up in the
-           % MySQL configuration, but not at the database level):
-            mysql_conn:fetch(Ref, ["SET SESSION TRANSACTION ISOLATION LEVEL "
-                                  "SERIALIZABLE;"], self()),
            {ok, #state{db_ref = Ref, db_type = mysql}};
        {error, Reason} ->
            ?ERROR_MSG("MySQL connection failed: ~p~nWaiting ~p seconds before retrying...~n",
index a2fb0ae415227f365e6bc8f7443bcac9284377f5..7fdc2f5ec7ab1957d6181c0b382c71d743b31360 100644 (file)
         set_private_data_sql/3,
         get_private_data/3,
         del_user_private_storage/2,
+        get_default_privacy_list/2,
+        get_default_privacy_list_t/1,
+        get_privacy_list_names/2,
+        get_privacy_list_names_t/1,
+        get_privacy_list_id/3,
+        get_privacy_list_id_t/2,
+        get_privacy_list_data/3,
+        get_privacy_list_data_by_id/2,
+        set_default_privacy_list/2,
+        unset_default_privacy_list/2,
+        remove_privacy_list/2,
+        add_privacy_list/2,
+        set_privacy_list/2,
+        del_privacy_lists/3,
         set_vcard/26,
         get_vcard/2,
         escape/1,
 get_db_type() ->
     generic.
 
+%% Safe atomic update.
+update_t(Table, Fields, Vals, Where) ->
+    UPairs = lists:zipwith(fun(A, B) -> A ++ "='" ++ B ++ "'" end,
+                          Fields, Vals),
+    case ejabberd_odbc:sql_query_t(
+          ["update ", Table, " set ",
+           string:join(UPairs, ", "),
+           " where ", Where, ";"]) of
+       {updated, 1} ->
+           ok;
+       _ ->
+           %% The 'catch' herein is used because mysql returns
+           %% affected rows (not matched as in postgresql).
+           %% FIXME: need to find more suitable solution.
+           catch ejabberd_odbc:sql_query_t(
+                   ["insert into ", Table, "(", string:join(Fields, ", "),
+                    ") values ('", string:join(Vals, "', '"), "');"])
+    end.
+
 %% F can be either a fun or a list of queries
-%% TODO: We should probably move the list of queries transaction wrapper from the ejabberd_odbc module
-%%       to this one (odbc_queries)
+%% TODO: We should probably move the list of queries transaction
+%% wrapper from the ejabberd_odbc module to this one (odbc_queries)
 sql_transaction(LServer, F) ->
     ejabberd_odbc:sql_transaction(LServer, F).
 
@@ -97,9 +130,11 @@ set_last_t(LServer, Username, Seconds, State) ->
     %% MREMOND: I think this should be turn into a non transactional behaviour
     ejabberd_odbc:sql_transaction(
       LServer,
-      [["delete from last where username='", Username, "';"],
-       ["insert into last(username, seconds, state) "
-       "values ('", Username, "', '", Seconds, "', '", State, "');"]]).
+      fun() ->
+             update_t("last", ["username", "seconds", "state"],
+                      [Username, Seconds, State],
+                      ["username='", Username, "'"])
+      end).
 
 del_last(LServer, Username) ->
     ejabberd_odbc:sql_query(
@@ -115,9 +150,11 @@ get_password(LServer, Username) ->
 set_password_t(LServer, Username, Pass) ->
     ejabberd_odbc:sql_transaction(
       LServer,
-      [["delete from users where username='", Username ,"';"],
-       ["insert into users(username, password) "
-       "values ('", Username, "', '", Pass, "');"]]).
+      fun() ->
+             update_t("users", ["username", "password"],
+                      [Username, Pass],
+                      ["username='", Username ,"'"])
+      end).
 
 add_user(LServer, Username, Pass) ->
     ejabberd_odbc:sql_query(
@@ -296,16 +333,11 @@ del_roster_sql(Username, SJID) ->
       "        and jid='", SJID, "';"]].
 
 update_roster(_LServer, Username, SJID, ItemVals, ItemGroups) ->
-    ejabberd_odbc:sql_query_t(
-      ["delete from rosterusers "
-       "      where username='", Username, "' "
-       "        and jid='", SJID, "';"]),
-    ejabberd_odbc:sql_query_t(
-      ["insert into rosterusers("
-       "              username, jid, nick, "
-       "              subscription, ask, askmessage, "
-       "              server, subscribe, type) "
-       " values (", ItemVals, ");"]),
+    update_t("rosterusers",
+            ["username", "jid", "nick", "subscription", "ask",
+             "askmessage", "server", "subscribe", "type"],
+            ItemVals,
+            ["username='", Username, "' and jid='", SJID, "'"]),
     ejabberd_odbc:sql_query_t(
       ["delete from rostergroups "
        "      where username='", Username, "' "
@@ -314,7 +346,7 @@ update_roster(_LServer, Username, SJID, ItemVals, ItemGroups) ->
                          ejabberd_odbc:sql_query_t(
                            ["insert into rostergroups("
                             "              username, jid, grp) "
-                            " values (", ItemGroup, ");"])
+                            " values ('", string:join(ItemGroup, "', '"), "');"])
                  end,
                  ItemGroups).
 
@@ -326,26 +358,21 @@ update_roster_sql(Username, SJID, ItemVals, ItemGroups) ->
       "              username, jid, nick, "
       "              subscription, ask, askmessage, "
       "              server, subscribe, type) "
-      " values (", ItemVals, ");"],
+      " values ('", string:join(ItemVals, "', '"), "');"],
      ["delete from rostergroups "
       "      where username='", Username, "' "
       "        and jid='", SJID, "';"]] ++
      [["insert into rostergroups("
        "              username, jid, grp) "
-       " values (", ItemGroup, ");"] ||
+       " values ('", string:join(ItemGroup, "', '"), "');"] ||
         ItemGroup <- ItemGroups].
 
 roster_subscribe(_LServer, Username, SJID, ItemVals) ->
-    ejabberd_odbc:sql_query_t(
-      ["delete from rosterusers "
-       "      where username='", Username, "' "
-       "        and jid='", SJID, "';"]),
-    ejabberd_odbc:sql_query_t(
-      ["insert into rosterusers("
-       "              username, jid, nick, "
-       "              subscription, ask, askmessage, "
-       "              server, subscribe, type) "
-       " values (", ItemVals, ");"]).
+    update_t("rosterusers",
+            ["username", "jid", "nick", "subscription", "ask",
+             "askmessage", "server", "subscribe", "type"],
+            ItemVals,
+            ["username='", Username, "' and jid='", SJID, "'"]).
 
 get_subscription(LServer, Username, SJID) ->
     ejabberd_odbc:sql_query(
@@ -355,10 +382,10 @@ get_subscription(LServer, Username, SJID) ->
        "and jid='", SJID, "'"]).
 
 set_private_data(_LServer, Username, LXMLNS, SData) ->
-    lists:foreach(fun(Query) ->
-            ejabberd_odbc:sql_query_t(Query)
-        end,
-        set_private_data_sql(Username, LXMLNS, SData)).
+    update_t("private_storage",
+            ["username", "namespace", "data"],
+            [Username, LXMLNS, SData], 
+            ["username='", Username, "' and namespace='", LXMLNS, "'"]).
 
 set_private_data_sql(Username, LXMLNS, SData) ->
     [["delete from private_storage "
@@ -380,35 +407,29 @@ del_user_private_storage(LServer, Username) ->
       LServer,
       ["delete from private_storage where username='", Username, "';"]).
 
-
 set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail, SFN, SFamily, SGiven,
          SLBDay, SLCTRY, SLEMail, SLFN, SLFamily, SLGiven, SLLocality,
          SLMiddle, SLNickname, SLOrgName, SLOrgUnit, SLocality, SMiddle,
          SNickname, SOrgName, SOrgUnit, SVCARD, Username) ->
     ejabberd_odbc:sql_transaction(
       LServer,
-      [["delete from vcard where username='", LUsername, "';"],
-       ["insert into vcard(username, vcard) "
-       "values ('", LUsername, "', '", SVCARD, "');"],
-       ["delete from vcard_search where lusername='", LUsername, "';"],
-       ["insert into vcard_search("
-       "        username, lusername, fn, lfn, family, lfamily,"
-       "        given, lgiven, middle, lmiddle, nickname, lnickname,"
-       "        bday, lbday, ctry, lctry, locality, llocality,"
-       "        email, lemail, orgname, lorgname, orgunit, lorgunit)"
-       "values (",
-       "        '", Username,  "', '", LUsername,  "',"
-       "        '", SFN,       "', '", SLFN,       "',"
-       "        '", SFamily,   "', '", SLFamily,   "',"
-       "        '", SGiven,    "', '", SLGiven,    "',"
-       "        '", SMiddle,   "', '", SLMiddle,   "',"
-       "        '", SNickname, "', '", SLNickname, "',"
-       "        '", SBDay,     "', '", SLBDay,    "',"
-       "        '", SCTRY,     "', '", SLCTRY,    "',"
-       "        '", SLocality, "', '", SLLocality, "',"
-       "        '", SEMail,    "', '", SLEMail,           "',"
-       "        '", SOrgName,  "', '", SLOrgName,  "',"
-       "        '", SOrgUnit,  "', '", SLOrgUnit,  "');"]]).
+      fun() ->
+             update_t("vcard", ["username", "vcard"],
+                      [LUsername, SVCARD],
+                      ["username='", LUsername, "'"]),
+             update_t("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"],
+                      [Username, LUsername, SFN, SLFN, SFamily, SLFamily,
+                       SGiven, SLGiven, SMiddle, SLMiddle, SNickname,
+                       SLNickname, SBDay, SLBDay, SCTRY, SLCTRY,
+                       SLocality, SLLocality, SEMail, SLEMail, SOrgName,
+                       SLOrgName, SOrgUnit, SLOrgUnit],
+                      ["lusername='", LUsername, "'"])
+      end).
 
 get_vcard(LServer, Username) ->
     ejabberd_odbc:sql_query(
@@ -416,6 +437,103 @@ get_vcard(LServer, Username) ->
       ["select vcard from vcard "
        "where username='", Username, "';"]).
 
+get_default_privacy_list(LServer, Username) ->
+    ejabberd_odbc:sql_query(
+      LServer,
+      ["select name from privacy_default_list "
+       "where username='", Username, "';"]).
+
+get_default_privacy_list_t(Username) ->
+    ejabberd_odbc:sql_query_t(
+      ["select name from privacy_default_list "
+       "where username='", Username, "';"]).
+
+get_privacy_list_names(LServer, Username) ->
+    ejabberd_odbc:sql_query(
+      LServer,
+      ["select name from privacy_list "
+       "where username='", Username, "';"]).
+
+get_privacy_list_names_t(Username) ->
+    ejabberd_odbc:sql_query_t(
+      ["select name from privacy_list "
+       "where username='", Username, "';"]).
+
+get_privacy_list_id(LServer, Username, SName) ->
+    ejabberd_odbc:sql_query(
+      LServer,
+      ["select id from privacy_list "
+       "where username='", Username, "' and name='", SName, "';"]).
+
+get_privacy_list_id_t(Username, SName) ->
+    ejabberd_odbc:sql_query_t(
+      ["select id from privacy_list "
+       "where username='", Username, "' and name='", SName, "';"]).
+
+get_privacy_list_data(LServer, Username, SName) ->
+    ejabberd_odbc:sql_query(
+      LServer,
+      ["select t, value, action, ord, match_all, match_iq, "
+       "match_message, match_presence_in, match_presence_out "
+       "from privacy_list_data "
+       "where id = (select id from privacy_list where "
+       "            username='", Username, "' and name='", SName, "') "
+       "order by ord;"]).
+
+get_privacy_list_data_by_id(LServer, ID) ->
+    ejabberd_odbc:sql_query(
+      LServer,
+      ["select t, value, action, ord, match_all, match_iq, "
+       "match_message, match_presence_in, match_presence_out "
+       "from privacy_list_data "
+       "where id='", ID, "' order by ord;"]).
+
+set_default_privacy_list(Username, SName) ->
+    update_t("privacy_default_list", ["username", "name"],
+            [Username, SName], ["username='", Username, "'"]).
+
+unset_default_privacy_list(LServer, Username) ->
+    ejabberd_odbc:sql_query(
+      LServer,
+      ["delete from privacy_default_list "
+       "      where username='", Username, "';"]).
+
+remove_privacy_list(Username, SName) ->
+    ejabberd_odbc:sql_query_t(
+      ["delete from privacy_list "
+       "where username='", Username, "' and name='", SName, "';"]).
+
+add_privacy_list(Username, SName) ->
+    ejabberd_odbc:sql_query_t(
+      ["insert into privacy_list(username, name) "
+       "values ('", Username, "', '", SName, "');"]).
+
+set_privacy_list(ID, RItems) ->
+    ejabberd_odbc:sql_query_t(
+      ["delete from privacy_list_data "
+       "where id='", ID, "';"]),
+    lists:foreach(fun(Items) ->
+                         ejabberd_odbc:sql_query_t(
+                           ["insert into privacy_list_data("
+                            "id, t, value, action, ord, match_all, match_iq, "
+                            "match_message, match_presence_in, "
+                            "match_presence_out "
+                            ") "
+                            "values ('", ID, "', '",
+                            string:join(Items, "', '"), "');"])
+                 end, RItems).
+
+del_privacy_lists(LServer, Server, Username) ->
+    ejabberd_odbc:sql_query(
+      LServer,
+      ["delete from privacy_list where username='", Username, "';"]),
+    ejabberd_odbc:sql_query(
+      LServer,
+      ["delete from privacy_list_data where value='", Username++"@"++Server, "';"]),
+    ejabberd_odbc:sql_query(
+      LServer,
+      ["delete from privacy_default_list where username='", Username, "';"]).
+
 %% Characters to escape
 escape($\0) -> "\\0";
 escape($\n) -> "\\n";