Merge 0.9->trunk
[prosody.git] / plugins / mod_storage_sql.lua
index 6d19eee6a17de04e9ade93a9797d2927782dadeb..c9a45fca86e4057d6dae5e6948c247d75a666432 100644 (file)
@@ -27,12 +27,28 @@ local next = next;
 local setmetatable = setmetatable;
 local xpcall = xpcall;
 local json = require "util.json";
+local build_url = require"socket.url".build;
 
 local DBI;
 local connection;
 local host,user,store = module.host;
 local params = module:get_option("sql");
 
+local dburi;
+local connections = module:shared "/*/sql/connection-cache";
+
+local function db2uri(params)
+       return build_url{
+               scheme = params.driver,
+               user = params.username,
+               password = params.password,
+               host = params.host,
+               port = params.port,
+               path = params.database,
+       };
+end
+
+
 local resolve_relative_path = require "core.configmanager".resolve_relative_path;
 
 local function test_connection()
@@ -42,6 +58,7 @@ local function test_connection()
        else
                module:log("debug", "Database connection closed");
                connection = nil;
+               connections[dburi] = nil;
        end
 end
 local function connect()
@@ -60,8 +77,10 @@ local function connect()
                module:log("debug", "Successfully connected to database");
                dbh:autocommit(false); -- don't commit automatically
                connection = dbh;
-               return connection;
+
+               connections[dburi] = dbh;
        end
+       return connection;
 end
 
 local function create_table()
@@ -146,6 +165,9 @@ do -- process options to get a db connection
        end
        
        assert(params.driver and params.database, "Both the SQL driver and the database need to be specified");
+
+       dburi = db2uri(params);
+       connection = connections[dburi];
        
        assert(connect());
        
@@ -343,7 +365,7 @@ function list_store:scan(username, from, to, jid, typ)
        return nil, "not-implemented"
 end
 
-local driver = { name = "sql" };
+local driver = {};
 
 function driver:open(store, typ)
        if not typ then -- default key-value store
@@ -352,30 +374,29 @@ function driver:open(store, typ)
        return nil, "unsupported-store";
 end
 
-function driver:list_stores(username) -- Not to be confused with the list store type
-       local sql = (username == true
-               and "SELECT DISTINCT `store` FROM `prosody` WHERE `host`=? AND `user`!=?"
-               or  "SELECT DISTINCT `store` FROM `prosody` WHERE `host`=? AND `user`=?");
+function driver:stores(username)
+       local sql = "SELECT DISTINCT `store` FROM `prosody` WHERE `host`=? AND `user`" ..
+               (username == true and "!=?" or "=?");
        if username == true or not username then
                username = "";
        end
        local stmt, err = dosql(sql, host, username);
        if not stmt then
-               return nil, err;
+               return rollback(nil, err);
        end
-       local stores = {};
-       for row in stmt:rows() do
-               stores[#stores+1] = row[1];
-       end
-       return stores;
+       local next = stmt:rows();
+       return commit(function()
+               local row = next();
+               return row and row[1];
+       end);
 end
 
 function driver:purge(username)
        local stmt, err = dosql("DELETE FROM `prosody` WHERE `host`=? AND `user`=?", host, username);
-       if not stmt then return stmt, err; end
+       if not stmt then return rollback(stmt, err); end
        local changed, err = stmt:affected();
-       if not changed then return changed, err; end
-       return true, changed;
+       if not changed then return rollback(changed, err); end
+       return commit(true, changed);
 end
 
-module:add_item("data-driver", driver);
+module:provides("storage", driver);