Comparison

plugins/mod_storage_sql2.lua @ 5741:c7a664e496b3

mod_storage_sql2: Add archive store with append and find methods
author Kim Alvefur <zash@zash.se>
date Fri, 12 Jul 2013 02:53:24 +0200
parent 5740:6fce00f61acf
child 5765:d854c17a45fd
comparison
equal deleted inserted replaced
5740:6fce00f61acf 5741:c7a664e496b3
1 1
2 local json = require "util.json"; 2 local json = require "util.json";
3 local xml_parse = require "util.xml".parse; 3 local xml_parse = require "util.xml".parse;
4 local uuid = require "util.uuid";
4 local resolve_relative_path = require "core.configmanager".resolve_relative_path; 5 local resolve_relative_path = require "core.configmanager".resolve_relative_path;
5 6
6 local stanza_mt = require"util.stanza".stanza_mt; 7 local stanza_mt = require"util.stanza".stanza_mt;
7 local getmetatable = getmetatable; 8 local getmetatable = getmetatable;
9 local t_concat = table.concat;
8 local function is_stanza(x) return getmetatable(x) == stanza_mt; end 10 local function is_stanza(x) return getmetatable(x) == stanza_mt; end
9 11
12 local noop = function() end
10 local unpack = unpack 13 local unpack = unpack
11 local function iterator(result) 14 local function iterator(result)
12 return function(result) 15 return function(result)
13 local row = result(); 16 local row = result();
14 if row ~= nil then 17 if row ~= nil then
241 end); 244 end);
242 if not ok then return ok, result end 245 if not ok then return ok, result end
243 return iterator(result); 246 return iterator(result);
244 end 247 end
245 248
249 local archive_store = {}
250 archive_store.__index = archive_store
251 function archive_store:append(username, when, with, value)
252 local user,store = username,self.store;
253 return engine:transaction(function()
254 local key = uuid.generate();
255 local t, value = serialize(value);
256 engine:insert("INSERT INTO `prosodyarchive` (`host`, `user`, `store`, `when`, `with`, `key`, `type`, `value`) VALUES (?,?,?,?,?,?,?,?)", host, user or "", store, when, with, key, t, value);
257 return key;
258 end);
259 end
260 function archive_store:find(username, query)
261 query = query or {};
262 local user,store = username,self.store;
263 local total;
264 local ok, result = engine:transaction(function()
265 local sql_query = "SELECT `key`, `type`, `value`, `when` FROM `prosodyarchive` WHERE %s ORDER BY `sort_id` %s%s;";
266 local args = { host, user or "", store, };
267 local where = { "`host` = ?", "`user` = ?", "`store` = ?", };
268
269 -- Time range, inclusive
270 if query.start then
271 args[#args+1] = query.start
272 where[#where+1] = "`when` >= ?"
273 end
274 if query["end"] then
275 args[#args+1] = query["end"];
276 if query.start then
277 where[#where] = "`when` BETWEEN ? AND ?" -- is this inclusive?
278 else
279 where[#where+1] = "`when` >= ?"
280 end
281 end
282
283 -- Related name
284 if query.with then
285 where[#where+1] = "`with` = ?";
286 args[#args+1] = query.with
287 end
288
289 -- Unique id
290 if query.key then
291 where[#where+1] = "`key` = ?";
292 args[#args+1] = query.key
293 end
294
295 -- Total matching
296 if query.total then
297 local stats = engine:select(sql_query:gsub("^(SELECT).-(FROM)", "%1 COUNT(*) %2"):format(t_concat(where, " AND "), "DESC", ""), unpack(args));
298 if stats then
299 local _total = stats()
300 total = _total and _total[1];
301 end
302 if query.limit == 0 then -- Skip the real query
303 return noop, total;
304 end
305 end
306
307 -- Before or after specific item, exclusive
308 if query.after then
309 where[#where+1] = "`sort_id` > (SELECT `sort_id` FROM `prosodyarchive` WHERE `key` = ? LIMIT 1)"
310 args[#args+1] = query.after
311 end
312 if query.before then
313 where[#where+1] = "`sort_id` < (SELECT `sort_id` FROM `prosodyarchive` WHERE `key` = ? LIMIT 1)"
314 args[#args+1] = query.before
315 end
316
317 if query.limit then
318 args[#args+1] = query.limit;
319 end
320
321 sql_query = sql_query:format(t_concat(where, " AND "), query.reverse and "DESC" or "ASC", query.limit and " LIMIT ?" or "");
322 module:log("debug", sql_query);
323 return engine:select(sql_query, unpack(args));
324 end);
325 if not ok then return ok, result end
326 return function()
327 local row = result();
328 if row ~= nil then
329 return row[1], deserialize(row[2], row[3]), row[4];
330 end
331 end, total;
332 end
333
246 local stores = { 334 local stores = {
247 keyval = keyval_store; 335 keyval = keyval_store;
336 archive = archive_store;
248 }; 337 };
249 338
250 local driver = {}; 339 local driver = {};
251 340
252 function driver:open(store, typ) 341 function driver:open(store, typ)