X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=plugins%2Fmod_storage_sql2.lua;h=74d08801553bcfabd87e4159a5614cd42d8638e2;hb=30afb0dbed5603b802d90a79b78206326e4fea09;hp=e03b1fd61fbf2cddf16e66dbf912a413ff338fb6;hpb=a2fc95c857560f2c3221afcb0967f82fbbf3ce93;p=prosody.git diff --git a/plugins/mod_storage_sql2.lua b/plugins/mod_storage_sql2.lua index e03b1fd6..74d08801 100644 --- a/plugins/mod_storage_sql2.lua +++ b/plugins/mod_storage_sql2.lua @@ -2,7 +2,7 @@ local json = require "util.json"; local xml_parse = require "util.xml".parse; local uuid = require "util.uuid"; -local resolve_relative_path = require "core.configmanager".resolve_relative_path; +local resolve_relative_path = require "util.paths".resolve_relative_path; local stanza_mt = require"util.stanza".stanza_mt; local getmetatable = getmetatable; @@ -113,8 +113,6 @@ do -- process options to get a db connection --local dburi = db2uri(params); engine = mod_sql:create_engine(params); - engine:set_encoding(); - if module:get_option("sql_manage_tables", true) then -- Automatically create table, ignore failure (table probably already exists) create_table(); @@ -194,11 +192,18 @@ local function keyval_store_set(data) return true; end +--- Key/value store API (default store type) + local keyval_store = {}; keyval_store.__index = keyval_store; function keyval_store:get(username) - user,store = username,self.store; - return select(2, engine:transaction(keyval_store_get)); + user, store = username, self.store; + local ok, result = engine:transaction(keyval_store_get); + if not ok then + module:log("error", "Unable to read from database %s store for %s: %s", store, username or "", result); + return nil, result; + end + return result; end function keyval_store:set(username, data) user,store = username,self.store; @@ -214,12 +219,21 @@ function keyval_store:users() return iterator(result); end +--- Archive store API + local archive_store = {} archive_store.__index = archive_store -function archive_store:append(username, when, with, value) +function archive_store:append(username, key, when, with, value) + if value == nil then -- COMPAT early versions + when, with, value, key = key, when, with, value + end local user,store = username,self.store; return engine:transaction(function() - local key = uuid.generate(); + if key then + engine:delete("DELETE FROM `prosodyarchive` WHERE `host`=? AND `user`=? AND `store`=? AND `key`=?", host, user or "", store, key); + else + key = uuid.generate(); + end local t, value = serialize(value); engine:insert("INSERT INTO `prosodyarchive` (`host`, `user`, `store`, `when`, `with`, `key`, `type`, `value`) VALUES (?,?,?,?,?,?,?,?)", host, user or "", store, when, with, key, t, value); return key; @@ -256,14 +270,16 @@ local function archive_where(query, args, where) end end local function archive_where_id_range(query, args, where) + local args_len = #args -- Before or after specific item, exclusive if query.after then -- keys better be unique! - where[#where+1] = "`sort_id` > (SELECT `sort_id` FROM `prosodyarchive` WHERE `key` = ? LIMIT 1)" - args[#args+1] = query.after + where[#where+1] = "`sort_id` > (SELECT `sort_id` FROM `prosodyarchive` WHERE `key` = ? AND `host` = ? AND `user` = ? AND `store` = ? LIMIT 1)" + args[args_len+1], args[args_len+2], args[args_len+3], args[args_len+4] = query.after, args[1], args[2], args[3]; + args_len = args_len + 4 end if query.before then - where[#where+1] = "`sort_id` < (SELECT `sort_id` FROM `prosodyarchive` WHERE `key` = ? LIMIT 1)" - args[#args+1] = query.before + where[#where+1] = "`sort_id` < (SELECT `sort_id` FROM `prosodyarchive` WHERE `key` = ? AND `host` = ? AND `user` = ? AND `store` = ? LIMIT 1)" + args[args_len+1], args[args_len+2], args[args_len+3], args[args_len+4] = query.before, args[1], args[2], args[3]; end end @@ -280,7 +296,7 @@ function archive_store:find(username, query) -- Total matching if query.total then - local stats = engine:select(sql_query:gsub("^(SELECT).-(FROM)", "%1 COUNT(*) %2"):format(t_concat(where, " AND "), "DESC", ""), unpack(args)); + local stats = engine:select("SELECT COUNT(*) FROM `prosodyarchive` WHERE " .. t_concat(where, " AND "), unpack(args)); if stats then local _total = stats() total = _total and _total[1]; @@ -316,6 +332,10 @@ function archive_store:delete(username, query) local sql_query = "DELETE FROM `prosodyarchive` WHERE %s;"; local args = { host, user or "", store, }; local where = { "`host` = ?", "`user` = ?", "`store` = ?", }; + if user == true then + table.remove(args, 2); + table.remove(where, 2); + end archive_where(query, args, where); archive_where_id_range(query, args, where); sql_query = sql_query:format(t_concat(where, " AND ")); @@ -329,6 +349,10 @@ local stores = { archive = archive_store; }; +--- Implement storage driver API + +-- FIXME: Some of these operations need to operate on the archive store(s) too + local driver = {}; function driver:open(store, typ) @@ -340,13 +364,13 @@ function driver:open(store, typ) end function driver:stores(username) - local sql = "SELECT DISTINCT `store` FROM `prosody` WHERE `host`=? AND `user`" .. + local query = "SELECT DISTINCT `store` FROM `prosody` WHERE `host`=? AND `user`" .. (username == true and "!=?" or "=?"); if username == true or not username then username = ""; end local ok, result = engine:transaction(function() - return engine:select(sql, host, username); + return engine:select(query, host, username); end); if not ok then return ok, result end return iterator(result); @@ -355,7 +379,7 @@ end function driver:purge(username) return engine:transaction(function() local stmt,err = engine:delete("DELETE FROM `prosody` WHERE `host`=? AND `user`=?", host, username); - return true,err; + return true, err; end); end