Software /
code /
prosody
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) |