mod_storage_sql2: Improve logging when database read fails
[prosody.git] / plugins / mod_storage_sql2.lua
index e02ad68148e22a1ea626b664337312e7f29480f2..74d08801553bcfabd87e4159a5614cd42d8638e2 100644 (file)
@@ -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 "<host>", result);
+               return nil, result;
+       end
+       return result;  
 end
 function keyval_store:set(username, data)
        user,store = username,self.store;
@@ -214,6 +219,8 @@ function keyval_store:users()
        return iterator(result);
 end
 
+--- Archive store API
+
 local archive_store = {}
 archive_store.__index = archive_store
 function archive_store:append(username, key, when, with, value)
@@ -222,9 +229,12 @@ function archive_store:append(username, key, when, with, value)
        end
        local user,store = username,self.store;
        return engine:transaction(function()
-               local key = key or 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:delete("DELETE FROM `prosodyarchive` WHERE `host`=? AND `user`=? AND `store`=? AND `key`=?", host, user or "", store, key);
                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;
        end);
@@ -286,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];
@@ -322,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 "));
@@ -335,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)
@@ -346,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);
@@ -361,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