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) |