Comparison

plugins/storage/ejabberdstore.lib.lua @ 2678:c5882e2e12b5

mod_storage, plus a bit of SQL and XML.
author Waqas Hussain <waqas20@gmail.com>
date Fri, 19 Feb 2010 22:32:28 +0500
comparison
equal deleted inserted replaced
2677:467568f1117d 2678:c5882e2e12b5
1
2 local handlers = {};
3
4 handlers.accounts = {
5 get = function(self, user)
6 local select = self:query("select password from users where username=?", user);
7 local row = select and select:fetch();
8 if row then return { password = row[1] }; end
9 end;
10 set = function(self, user, data)
11 if data and data.password then
12 return self:modify("update users set password=? where username=?", data.password, user)
13 or self:modify("insert into users (username, password) values (?, ?)", user, data.password);
14 else
15 return self:modify("delete from users where username=?", user);
16 end
17 end;
18 };
19 handlers.vcard = {
20 get = function(self, user)
21 local select = self:query("select vcard from vcard where username=?", user);
22 local row = select and select:fetch();
23 if row then return parse_xml(row[1]); end
24 end;
25 set = function(self, user, data)
26 if data then
27 data = unparse_xml(data);
28 return self:modify("update vcard set vcard=? where username=?", data, user)
29 or self:modify("insert into vcard (username, vcard) values (?, ?)", user, data);
30 else
31 return self:modify("delete from vcard where username=?", user);
32 end
33 end;
34 };
35 handlers.private = {
36 get = function(self, user)
37 local select = self:query("select namespace,data from private_storage where username=?", user);
38 if select then
39 local data = {};
40 for row in select:rows() do
41 data[row[1]] = parse_xml(row[2]);
42 end
43 return data;
44 end
45 end;
46 set = function(self, user, data)
47 if data then
48 self:modify("delete from private_storage where username=?", user);
49 for namespace,text in pairs(data) do
50 self:modify("insert into private_storage (username, namespace, data) values (?, ?, ?)", user, namespace, unparse_xml(text));
51 end
52 return true;
53 else
54 return self:modify("delete from private_storage where username=?", user);
55 end
56 end;
57 -- TODO map_set, map_get
58 };
59 local subscription_map = { N = "none", B = "both", F = "from", T = "to" };
60 local subscription_map_reverse = { none = "N", both = "B", from = "F", to = "T" };
61 handlers.roster = {
62 get = function(self, user)
63 local select = self:query("select jid,nick,subscription,ask,server,subscribe,type from rosterusers where username=?", user);
64 if select then
65 local roster = { pending = {} };
66 for row in select:rows() do
67 local jid,nick,subscription,ask,server,subscribe,typ = unpack(row);
68 local item = { groups = {} };
69 if nick == "" then nick = nil; end
70 item.nick = nick;
71 item.subscription = subscription_map[subscription];
72 if ask == "N" then ask = nil;
73 elseif ask == "O" then ask = "subscribe"
74 elseif ask == "I" then roster.pending[jid] = true; ask = nil;
75 elseif ask == "B" then roster.pending[jid] = true; ask = "subscribe";
76 else module:log("debug", "bad roster_item.ask: %s", ask); ask = nil; end
77 item.ask = ask;
78 roster[jid] = item;
79 end
80
81 select = self:query("select jid,grp from rostergroups where username=?", user);
82 if select then
83 for row in select:rows() do
84 local jid,grp = unpack(rows);
85 if roster[jid] then roster[jid].groups[grp] = true; end
86 end
87 end
88 select = self:query("select version from roster_version where username=?", user);
89 local row = select and select:fetch();
90 if row then
91 roster[false] = { version = row[1]; };
92 end
93 return roster;
94 end
95 end;
96 set = function(self, user, data)
97 if data and next(data) ~= nil then
98 self:modify("delete from rosterusers where username=?", user);
99 self:modify("delete from rostergroups where username=?", user);
100 self:modify("delete from roster_version where username=?", user);
101 local done = {};
102 local pending = data.pending or {};
103 for jid,item in pairs(data) do
104 if jid and jid ~= "pending" then
105 local subscription = subscription_map_reverse[item.subscription];
106 local ask;
107 if pending[jid] then
108 if item.ask then ask = "B"; else ask = "I"; end
109 else
110 if item.ask then ask = "O"; else ask = "N"; end
111 end
112 local r = self:modify("insert into rosterusers (username,jid,nick,subscription,ask,askmessage,server,subscribe) values (?, ?, ?, ?, ?, '', '', '')", user, jid, item.nick or "", subscription, ask);
113 if not r then module:log("debug", "--- :( %s", tostring(r)); end
114 done[jid] = true;
115 for group in pairs(item.groups) do
116 self:modify("insert into rostergroups (username,jid,grp) values (?, ?, ?)", user, jid, group);
117 end
118 end
119 end
120 for jid in pairs(pending) do
121 if not done[jid] then
122 self:modify("insert into rosterusers (username,jid,nick,subscription,ask,askmessage,server,subscribe) values (?, ?, ?, ?, ?. ''. ''. '')", user, jid, "", "N", "I");
123 end
124 end
125 local version = data[false] and data[false].version;
126 if version then
127 self:modify("insert into roster_version (username,version) values (?, ?)", user, version);
128 end
129 return true;
130 else
131 self:modify("delete from rosterusers where username=?", user);
132 self:modify("delete from rostergroups where username=?", user);
133 self:modify("delete from roster_version where username=?", user);
134 end
135 end;
136 };
137
138 -----------------------------
139 local driver = {};
140 driver.__index = driver;
141
142 function driver:prepare(sql)
143 module:log("debug", "query: %s", sql);
144 local err;
145 if not self.sqlcache then self.sqlcache = {}; end
146 local r = self.sqlcache[sql];
147 if r then return r; end
148 r, err = self.database:prepare(sql);
149 if not r then error("Unable to prepare SQL statement: "..err); end
150 self.sqlcache[sql] = r;
151 return r;
152 end
153
154 function driver:query(sql, ...)
155 local stmt = self:prepare(sql);
156 if stmt:execute(...) then return stmt; end
157 end
158 function driver:modify(sql, ...)
159 local stmt = self:query(sql, ...);
160 if stmt and stmt:affected() > 0 then return stmt; end
161 end
162
163 function driver:open(host, datastore, typ)
164 local cache_key = host.." "..datastore;
165 if self.ds_cache[cache_key] then return self.ds_cache[cache_key]; end
166 local instance = setmetatable({}, self);
167 instance.host = host;
168 instance.datastore = datastore;
169 local handler = handlers[datastore];
170 if not handler then return nil; end
171 for key,val in pairs(handler) do
172 instance[key] = val;
173 end
174 if instance.init then instance:init(); end
175 self.ds_cache[cache_key] = instance;
176 return instance;
177 end
178
179 -----------------------------
180 local _M = {};
181
182 function _M.new(dbtype, dbname, ...)
183 local instance = setmetatable({}, driver);
184 instance.__index = instance;
185 instance.database = get_database(dbtype, dbname, ...);
186 instance.ds_cache = {};
187 return instance;
188 end
189
190 return _M;