Changeset

4082:eeab15f8aa35

Merge 0.8->trunk
author Matthew Wild <mwild1@gmail.com>
date Fri, 07 Jan 2011 03:18:40 +0000
parents 4078:05a58497a903 (current diff) 4081:ce02a56b268f (diff)
children 4088:0e5585910583
files plugins/mod_storage_sql_ejabberd.lua plugins/storage/ejabberd_init.lib.lua plugins/storage/ejabberdstore.lib.lua
diffstat 3 files changed, 0 insertions(+), 674 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/mod_storage_sql_ejabberd.lua	Thu Jan 06 14:46:59 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-
-local setmetatable = setmetatable;
-local error = error;
-local unpack = unpack;
-local module = module;
-local tostring = tostring;
-local pairs, next = pairs, next;
-local prosody = prosody;
-local assert = assert;
-local require = require;
-local st = require "util.stanza";
-local DBI = require "DBI";
-
--- connect to db
-local params = module:get_option("sql_ejabberd") or error("No sql_ejabberd config option");
-local database;
-do
-	module:log("debug", "Opening database: %s", "dbi:"..params.driver..":"..params.database);
-	prosody.unlock_globals();
-	local dbh, err = DBI.Connect(
-		params.driver, params.database,
-		params.username, params.password,
-		params.host, params.port
-	);
-	prosody.lock_globals();
-	assert(dbh, err);
-	dbh:autocommit(true);
-	database = dbh;
-end
-
--- initialize db
-local ejabberd_init = module:require("ejabberd_init");
-ejabberd_init.init(database);
-
-local sqlcache = {};
-local function prepare(sql)
-	module:log("debug", "query: %s", sql);
-	local err;
-	local r = sqlcache[sql];
-	if not r then
-		r, err = database:prepare(sql);
-		if not r then error("Unable to prepare SQL statement: "..err); end
-		sqlcache[sql] = r;
-	end
-	return r;
-end
-
-local _parse_xml = module:require("xmlparse");
-local function parse_xml(str)
-	local s = _parse_xml(str);
-	if s and not s.gsub then
-		return st.preserialize(s);
-	end
-end
-local function unparse_xml(s)
-	return tostring(st.deserialize(s));
-end
-
-
-local handlers = {};
-
-handlers.accounts = {
-	get = function(self, user)
-		local select = self:query("select password from users where username=? and host=?", user, self.host);
-		local row = select and select:fetch();
-		if row then return { password = row[1] }; end
-	end;
-	set = function(self, user, data)
-		if data and data.password then
-			return self:modify("update users set password=? where username=? and host=?", data.password, user, self.host)
-				or self:modify("insert into users (username, host, password) values (?, ?, ?)", user, self.host, data.password);
-		else
-			return self:modify("delete from users where username=? and host=?", user, self.host);
-		end
-	end;
-};
-handlers.vcard = {
-	get = function(self, user)
-		local select = self:query("select vcard from vcard where username=? and host=?", user, self.host);
-		local row = select and select:fetch();
-		if row then return parse_xml(row[1]); end
-	end;
-	set = function(self, user, data)
-		if data then
-			data = unparse_xml(data);
-			return self:modify("update vcard set vcard=? where username=? and host=?", data, user, self.host)
-				or self:modify("insert into vcard (username, host, vcard) values (?, ?, ?)", user, self.host, data);
-		else
-			return self:modify("delete from vcard where username=? and host=?", user, self.host);
-		end
-	end;
-};
-handlers.private = {
-	get = function(self, user)
-		local select = self:query("select namespace,data from private_storage where username=? and host=?", user, self.host);
-		if select then
-			local data = {};
-			for row in select:rows() do
-				data[row[1]] = parse_xml(row[2]);
-			end
-			return data;
-		end
-	end;
-	set = function(self, user, data)
-		if data then
-			self:modify("delete from private_storage where username=? and host=?", user, self.host);
-			for namespace,text in pairs(data) do
-				self:modify("insert into private_storage (username, host, namespace, data) values (?, ?, ?, ?)", user, self.host, namespace, unparse_xml(text));
-			end
-			return true;
-		else
-			return self:modify("delete from private_storage where username=? and host=?", user, self.host);
-		end
-	end;
-	-- TODO map_set, map_get
-};
-local subscription_map = { N = "none", B = "both", F = "from", T = "to" };
-local subscription_map_reverse = { none = "N", both = "B", from = "F", to = "T" };
-handlers.roster = {
-	get = function(self, user)
-		local select = self:query("select jid,nick,subscription,ask,server,subscribe,type from rosterusers where username=?", user);
-		if select then
-			local roster = { pending = {} };
-			for row in select:rows() do
-				local jid,nick,subscription,ask,server,subscribe,typ = unpack(row);
-				local item = { groups = {} };
-				if nick == "" then nick = nil; end
-				item.nick = nick;
-				item.subscription = subscription_map[subscription];
-				if ask == "N" then ask = nil;
-				elseif ask == "O" then ask = "subscribe"
-				elseif ask == "I" then roster.pending[jid] = true; ask = nil;
-				elseif ask == "B" then roster.pending[jid] = true; ask = "subscribe";
-				else module:log("debug", "bad roster_item.ask: %s", ask); ask = nil; end
-				item.ask = ask;
-				roster[jid] = item;
-			end
-			
-			select = self:query("select jid,grp from rostergroups where username=?", user);
-			if select then
-				for row in select:rows() do
-					local jid,grp = unpack(row);
-					if roster[jid] then roster[jid].groups[grp] = true; end
-				end
-			end
-			select = self:query("select version from roster_version where username=?", user);
-			local row = select and select:fetch();
-			if row then
-				roster[false] = { version = row[1]; };
-			end
-			return roster;
-		end
-	end;
-	set = function(self, user, data)
-		if data and next(data) ~= nil then
-			self:modify("delete from rosterusers where username=?", user);
-			self:modify("delete from rostergroups where username=?", user);
-			self:modify("delete from roster_version where username=?", user);
-			local done = {};
-			local pending = data.pending or {};
-			for jid,item in pairs(data) do
-				if jid and jid ~= "pending" then
-					local subscription = subscription_map_reverse[item.subscription];
-					local ask;
-					if pending[jid] then
-						if item.ask then ask = "B"; else ask = "I"; end
-					else
-						if item.ask then ask = "O"; else ask = "N"; end
-					end
-					local r = self:modify("insert into rosterusers (username,jid,nick,subscription,ask,askmessage,server,subscribe) values (?, ?, ?, ?, ?, '', '', '')", user, jid, item.nick or "", subscription, ask);
-					if not r then module:log("debug", "--- :( %s", tostring(r)); end
-					done[jid] = true;
-					for group in pairs(item.groups) do
-						self:modify("insert into rostergroups (username,jid,grp) values (?, ?, ?)", user, jid, group);
-					end
-				end
-			end
-			for jid in pairs(pending) do
-				if not done[jid] then
-					self:modify("insert into rosterusers (username,jid,nick,subscription,ask,askmessage,server,subscribe) values (?, ?, ?, ?, ?. ''. ''. '')", user, jid, "", "N", "I");
-				end
-			end
-			local version = data[false] and data[false].version;
-			if version then
-				self:modify("insert into roster_version (username,version) values (?, ?)", user, version);
-			end
-			return true;
-		else
-			self:modify("delete from rosterusers where username=?", user);
-			self:modify("delete from rostergroups where username=?", user);
-			self:modify("delete from roster_version where username=?", user);
-		end
-	end;
-};
-
------------------------------
-local driver = {};
-driver.__index = driver;
-
-function driver:query(sql, ...)
-	local stmt,err = prepare(sql);
-	if not stmt then
-		module:log("error", "Failed to prepare SQL [[%s]], error: %s", sql, err);
-		return nil, err;
-	end
-	local ok, err = stmt:execute(...);
-	if not ok then
-		module:log("error", "Failed to execute SQL [[%s]], error: %s", sql, err);
-		return nil, err;
-	end
-	return stmt;
-end
-function driver:modify(sql, ...)
-	local stmt, err = self:query(sql, ...);
-	if stmt and stmt:affected() > 0 then return stmt; end
-	return nil, err;
-end
-
-function driver:open(datastore, typ)
-	local instance = setmetatable({ host = module.host, datastore = datastore }, self);
-	local handler = handlers[datastore];
-	if not handler then return nil; end
-	for key,val in pairs(handler) do
-		instance[key] = val;
-	end
-	if instance.init then instance:init(); end
-	return instance;
-end
-
------------------------------
-
-module:add_item("data-driver", driver);
--- a/plugins/storage/ejabberd_init.lib.lua	Thu Jan 06 14:46:59 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-
-local t_concat = table.concat;
-local t_insert = table.insert;
-local pairs = pairs;
-local DBI = require "DBI";
-
-local sqlite = true;
-local q = {};
-
-local function set(key, val)
---	t_insert(q, "SET "..key.."="..val..";\n")
-end
-local function create_table(name, fields)
-	t_insert(q, "CREATE TABLE ".."IF NOT EXISTS "..name.." (\n");
-	for _, field in pairs(fields) do
-		t_insert(q, "\t");
-		field = t_concat(field, " ");
-		if sqlite then
-			if field:lower():match("^primary key *%(") then field = field:gsub("%(%d+%)", ""); end
-		end
-		t_insert(q, field);
-		if _ ~= #fields then t_insert(q, ",\n"); end
-		t_insert(q, "\n");
-	end
-	if sqlite then
-		t_insert(q, ");\n");
-	else
-		t_insert(q, ") CHARACTER SET utf8;\n");
-	end
-end
-local function create_index(name, index)
-	--t_insert(q, "CREATE INDEX "..name.." ON "..index..";\n");
-end
-local function create_unique_index(name, index)
-	--t_insert(q, "CREATE UNIQUE INDEX "..name.." ON "..index..";\n");
-end
-local function insert(target, value)
-	t_insert(q, "INSERT INTO "..target.."\nVALUES "..value..";\n");
-end
-local function foreign_key(name, fkey, fname, fcol)
-	t_insert(q, "ALTER TABLE `"..name.."` ADD FOREIGN KEY (`"..fkey.."`) REFERENCES `"..fname.."` (`"..fcol.."`) ON DELETE CASCADE;\n");
-end
-
-function build_query()
-	q = {};
-	set('table_type', 'InnoDB');
-	create_table('hosts', {
-		{'clusterid','integer','NOT','NULL'};
-		{'host','varchar(250)','NOT','NULL','PRIMARY','KEY'};
-		{'config','text','NOT','NULL'};
-	});
-	insert("hosts (clusterid, host, config)", "(1, 'localhost', '')");
-	create_table('users', {
-		{'host','varchar(250)','NOT','NULL'};
-		{'username','varchar(250)','NOT','NULL'};
-		{'password','text','NOT','NULL'};
-		{'created_at','timestamp','NOT','NULL','DEFAULT','CURRENT_TIMESTAMP'};
-		{'PRIMARY','KEY','(host, username)'};
-	});
-	create_table('last', {
-		{'host','varchar(250)','NOT','NULL'};
-		{'username','varchar(250)','NOT','NULL'};
-		{'seconds','text','NOT','NULL'};
-		{'state','text','NOT','NULL'};
-		{'PRIMARY','KEY','(host, username)'};
-	});
-	create_table('rosterusers', {
-		{'host','varchar(250)','NOT','NULL'};
-		{'username','varchar(250)','NOT','NULL'};
-		{'jid','varchar(250)','NOT','NULL'};
-		{'nick','text','NOT','NULL'};
-		{'subscription','character(1)','NOT','NULL'};
-		{'ask','character(1)','NOT','NULL'};
-		{'askmessage','text','NOT','NULL'};
-		{'server','character(1)','NOT','NULL'};
-		{'subscribe','text','NOT','NULL'};
-		{'type','text'};
-		{'created_at','timestamp','NOT','NULL','DEFAULT','CURRENT_TIMESTAMP'};
-		{'PRIMARY','KEY','(host(75), username(75), jid(75))'};
-	});
-	create_index('i_rosteru_username', 'rosterusers(username)');
-	create_index('i_rosteru_jid', 'rosterusers(jid)');
-	create_table('rostergroups', {
-		{'host','varchar(250)','NOT','NULL'};
-		{'username','varchar(250)','NOT','NULL'};
-		{'jid','varchar(250)','NOT','NULL'};
-		{'grp','text','NOT','NULL'};
-		{'PRIMARY','KEY','(host(75), username(75), jid(75))'};
-	});
-	--[[create_table('spool', {
-		{'host','varchar(250)','NOT','NULL'};
-		{'username','varchar(250)','NOT','NULL'};
-		{'xml','text','NOT','NULL'};
-		{'seq','BIGINT','UNSIGNED','NOT','NULL','AUTO_INCREMENT','UNIQUE'};
-		{'created_at','timestamp','NOT','NULL','DEFAULT','CURRENT_TIMESTAMP'};
-		{'PRIMARY','KEY','(host, username, seq)'};
-	});]]
-	create_table('vcard', {
-		{'host','varchar(250)','NOT','NULL'};
-		{'username','varchar(250)','NOT','NULL'};
-		{'vcard','text','NOT','NULL'};
-		{'created_at','timestamp','NOT','NULL','DEFAULT','CURRENT_TIMESTAMP'};
-		{'PRIMARY','KEY','(host, username)'};
-	});
-	create_table('vcard_search', {
-		{'host','varchar(250)','NOT','NULL'};
-		{'username','varchar(250)','NOT','NULL'};
-		{'lusername','varchar(250)','NOT','NULL'};
-		{'fn','text','NOT','NULL'};
-		{'lfn','varchar(250)','NOT','NULL'};
-		{'family','text','NOT','NULL'};
-		{'lfamily','varchar(250)','NOT','NULL'};
-		{'given','text','NOT','NULL'};
-		{'lgiven','varchar(250)','NOT','NULL'};
-		{'middle','text','NOT','NULL'};
-		{'lmiddle','varchar(250)','NOT','NULL'};
-		{'nickname','text','NOT','NULL'};
-		{'lnickname','varchar(250)','NOT','NULL'};
-		{'bday','text','NOT','NULL'};
-		{'lbday','varchar(250)','NOT','NULL'};
-		{'ctry','text','NOT','NULL'};
-		{'lctry','varchar(250)','NOT','NULL'};
-		{'locality','text','NOT','NULL'};
-		{'llocality','varchar(250)','NOT','NULL'};
-		{'email','text','NOT','NULL'};
-		{'lemail','varchar(250)','NOT','NULL'};
-		{'orgname','text','NOT','NULL'};
-		{'lorgname','varchar(250)','NOT','NULL'};
-		{'orgunit','text','NOT','NULL'};
-		{'lorgunit','varchar(250)','NOT','NULL'};
-		{'PRIMARY','KEY','(host, lusername)'};
-	});
-	create_index('i_vcard_search_lfn      ', 'vcard_search(lfn)');
-	create_index('i_vcard_search_lfamily  ', 'vcard_search(lfamily)');
-	create_index('i_vcard_search_lgiven   ', 'vcard_search(lgiven)');
-	create_index('i_vcard_search_lmiddle  ', 'vcard_search(lmiddle)');
-	create_index('i_vcard_search_lnickname', 'vcard_search(lnickname)');
-	create_index('i_vcard_search_lbday    ', 'vcard_search(lbday)');
-	create_index('i_vcard_search_lctry    ', 'vcard_search(lctry)');
-	create_index('i_vcard_search_llocality', 'vcard_search(llocality)');
-	create_index('i_vcard_search_lemail   ', 'vcard_search(lemail)');
-	create_index('i_vcard_search_lorgname ', 'vcard_search(lorgname)');
-	create_index('i_vcard_search_lorgunit ', 'vcard_search(lorgunit)');
-	create_table('privacy_default_list', {
-		{'host','varchar(250)','NOT','NULL'};
-		{'username','varchar(250)'};
-		{'name','varchar(250)','NOT','NULL'};
-		{'PRIMARY','KEY','(host, username)'};
-	});
-	--[[create_table('privacy_list', {
-		{'host','varchar(250)','NOT','NULL'};
-		{'username','varchar(250)','NOT','NULL'};
-		{'name','varchar(250)','NOT','NULL'};
-		{'id','BIGINT','UNSIGNED','NOT','NULL','AUTO_INCREMENT','UNIQUE'};
-		{'created_at','timestamp','NOT','NULL','DEFAULT','CURRENT_TIMESTAMP'};
-		{'PRIMARY','KEY','(host, username, name)'};
-	});]]
-	create_table('privacy_list_data', {
-		{'id','bigint'};
-		{'t','character(1)','NOT','NULL'};
-		{'value','text','NOT','NULL'};
-		{'action','character(1)','NOT','NULL'};
-		{'ord','NUMERIC','NOT','NULL'};
-		{'match_all','boolean','NOT','NULL'};
-		{'match_iq','boolean','NOT','NULL'};
-		{'match_message','boolean','NOT','NULL'};
-		{'match_presence_in','boolean','NOT','NULL'};
-		{'match_presence_out','boolean','NOT','NULL'};
-	});
-	create_table('private_storage', {
-		{'host','varchar(250)','NOT','NULL'};
-		{'username','varchar(250)','NOT','NULL'};
-		{'namespace','varchar(250)','NOT','NULL'};
-		{'data','text','NOT','NULL'};
-		{'created_at','timestamp','NOT','NULL','DEFAULT','CURRENT_TIMESTAMP'};
-		{'PRIMARY','KEY','(host(75), username(75), namespace(75))'};
-	});
-	create_index('i_private_storage_username USING BTREE', 'private_storage(username)');
-	create_table('roster_version', {
-		{'username','varchar(250)','PRIMARY','KEY'};
-		{'version','text','NOT','NULL'};
-	});
-	--[[create_table('pubsub_node', {
-		{'host','text'};
-		{'node','text'};
-		{'parent','text'};
-		{'type','text'};
-		{'nodeid','bigint','auto_increment','primary','key'};
-	});
-	create_index('i_pubsub_node_parent', 'pubsub_node(parent(120))');
-	create_unique_index('i_pubsub_node_tuple', 'pubsub_node(host(20), node(120))');
-	create_table('pubsub_node_option', {
-		{'nodeid','bigint'};
-		{'name','text'};
-		{'val','text'};
-	});
-	create_index('i_pubsub_node_option_nodeid', 'pubsub_node_option(nodeid)');
-	foreign_key('pubsub_node_option', 'nodeid', 'pubsub_node', 'nodeid');
-	create_table('pubsub_node_owner', {
-		{'nodeid','bigint'};
-		{'owner','text'};
-	});
-	create_index('i_pubsub_node_owner_nodeid', 'pubsub_node_owner(nodeid)');
-	foreign_key('pubsub_node_owner', 'nodeid', 'pubsub_node', 'nodeid');
-	create_table('pubsub_state', {
-		{'nodeid','bigint'};
-		{'jid','text'};
-		{'affiliation','character(1)'};
-		{'subscriptions','text'};
-		{'stateid','bigint','auto_increment','primary','key'};
-	});
-	create_index('i_pubsub_state_jid', 'pubsub_state(jid(60))');
-	create_unique_index('i_pubsub_state_tuple', 'pubsub_state(nodeid, jid(60))');
-	foreign_key('pubsub_state', 'nodeid', 'pubsub_node', 'nodeid');
-	create_table('pubsub_item', {
-		{'nodeid','bigint'};
-		{'itemid','text'};
-		{'publisher','text'};
-		{'creation','text'};
-		{'modification','text'};
-		{'payload','text'};
-	});
-	create_index('i_pubsub_item_itemid', 'pubsub_item(itemid(36))');
-	create_unique_index('i_pubsub_item_tuple', 'pubsub_item(nodeid, itemid(36))');
-	foreign_key('pubsub_item', 'nodeid', 'pubsub_node', 'nodeid');
-	create_table('pubsub_subscription_opt', {
-		{'subid','text'};
-		{'opt_name','varchar(32)'};
-		{'opt_value','text'};
-	});
-	create_unique_index('i_pubsub_subscription_opt', 'pubsub_subscription_opt(subid(32), opt_name(32))');]]
-	return t_concat(q);
-end
-
-local function init(dbh)
-	local q = build_query();
-	for statement in q:gmatch("[^;]*;") do
-		statement = statement:gsub("\n", ""):gsub("\t", " ");
-		if sqlite then
-			statement = statement:gsub("AUTO_INCREMENT", "AUTOINCREMENT");
-			statement = statement:gsub("auto_increment", "autoincrement");
-		end
-		local result, err = DBI.Do(dbh, statement);
-		if not result then
-			print("X", result, err);
-			print("Y", statement);
-		end
-	end
-end
-
-local _M = { init = init };
-return _M;
--- a/plugins/storage/ejabberdstore.lib.lua	Thu Jan 06 14:46:59 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-
-local handlers = {};
-
-handlers.accounts = {
-	get = function(self, user)
-		local select = self:query("select password from users where username=?", user);
-		local row = select and select:fetch();
-		if row then return { password = row[1] }; end
-	end;
-	set = function(self, user, data)
-		if data and data.password then
-			return self:modify("update users set password=? where username=?", data.password, user)
-				or self:modify("insert into users (username, password) values (?, ?)", user, data.password);
-		else
-			return self:modify("delete from users where username=?", user);
-		end
-	end;
-};
-handlers.vcard = {
-	get = function(self, user)
-		local select = self:query("select vcard from vcard where username=?", user);
-		local row = select and select:fetch();
-		if row then return parse_xml(row[1]); end
-	end;
-	set = function(self, user, data)
-		if data then
-			data = unparse_xml(data);
-			return self:modify("update vcard set vcard=? where username=?", data, user)
-				or self:modify("insert into vcard (username, vcard) values (?, ?)", user, data);
-		else
-			return self:modify("delete from vcard where username=?", user);
-		end
-	end;
-};
-handlers.private = {
-	get = function(self, user)
-		local select = self:query("select namespace,data from private_storage where username=?", user);
-		if select then
-			local data = {};
-			for row in select:rows() do
-				data[row[1]] = parse_xml(row[2]);
-			end
-			return data;
-		end
-	end;
-	set = function(self, user, data)
-		if data then
-			self:modify("delete from private_storage where username=?", user);
-			for namespace,text in pairs(data) do
-				self:modify("insert into private_storage (username, namespace, data) values (?, ?, ?)", user, namespace, unparse_xml(text));
-			end
-			return true;
-		else
-			return self:modify("delete from private_storage where username=?", user);
-		end
-	end;
-	-- TODO map_set, map_get
-};
-local subscription_map = { N = "none", B = "both", F = "from", T = "to" };
-local subscription_map_reverse = { none = "N", both = "B", from = "F", to = "T" };
-handlers.roster = {
-	get = function(self, user)
-		local select = self:query("select jid,nick,subscription,ask,server,subscribe,type from rosterusers where username=?", user);
-		if select then
-			local roster = { pending = {} };
-			for row in select:rows() do
-				local jid,nick,subscription,ask,server,subscribe,typ = unpack(row);
-				local item = { groups = {} };
-				if nick == "" then nick = nil; end
-				item.nick = nick;
-				item.subscription = subscription_map[subscription];
-				if ask == "N" then ask = nil;
-				elseif ask == "O" then ask = "subscribe"
-				elseif ask == "I" then roster.pending[jid] = true; ask = nil;
-				elseif ask == "B" then roster.pending[jid] = true; ask = "subscribe";
-				else module:log("debug", "bad roster_item.ask: %s", ask); ask = nil; end
-				item.ask = ask;
-				roster[jid] = item;
-			end
-			
-			select = self:query("select jid,grp from rostergroups where username=?", user);
-			if select then
-				for row in select:rows() do
-					local jid,grp = unpack(rows);
-					if roster[jid] then roster[jid].groups[grp] = true; end
-				end
-			end
-			select = self:query("select version from roster_version where username=?", user);
-			local row = select and select:fetch();
-			if row then
-				roster[false] = { version = row[1]; };
-			end
-			return roster;
-		end
-	end;
-	set = function(self, user, data)
-		if data and next(data) ~= nil then
-			self:modify("delete from rosterusers where username=?", user);
-			self:modify("delete from rostergroups where username=?", user);
-			self:modify("delete from roster_version where username=?", user);
-			local done = {};
-			local pending = data.pending or {};
-			for jid,item in pairs(data) do
-				if jid and jid ~= "pending" then
-					local subscription = subscription_map_reverse[item.subscription];
-					local ask;
-					if pending[jid] then
-						if item.ask then ask = "B"; else ask = "I"; end
-					else
-						if item.ask then ask = "O"; else ask = "N"; end
-					end
-					local r = self:modify("insert into rosterusers (username,jid,nick,subscription,ask,askmessage,server,subscribe) values (?, ?, ?, ?, ?, '', '', '')", user, jid, item.nick or "", subscription, ask);
-					if not r then module:log("debug", "--- :( %s", tostring(r)); end
-					done[jid] = true;
-					for group in pairs(item.groups) do
-						self:modify("insert into rostergroups (username,jid,grp) values (?, ?, ?)", user, jid, group);
-					end
-				end
-			end
-			for jid in pairs(pending) do
-				if not done[jid] then
-					self:modify("insert into rosterusers (username,jid,nick,subscription,ask,askmessage,server,subscribe) values (?, ?, ?, ?, ?. ''. ''. '')", user, jid, "", "N", "I");
-				end
-			end
-			local version = data[false] and data[false].version;
-			if version then
-				self:modify("insert into roster_version (username,version) values (?, ?)", user, version);
-			end
-			return true;
-		else
-			self:modify("delete from rosterusers where username=?", user);
-			self:modify("delete from rostergroups where username=?", user);
-			self:modify("delete from roster_version where username=?", user);
-		end
-	end;
-};
-
------------------------------
-local driver = {};
-driver.__index = driver;
-
-function driver:prepare(sql)
-	module:log("debug", "query: %s", sql);
-	local err;
-	if not self.sqlcache then self.sqlcache = {}; end
-	local r = self.sqlcache[sql];
-	if r then return r; end
-	r, err = self.database:prepare(sql);
-	if not r then error("Unable to prepare SQL statement: "..err); end
-	self.sqlcache[sql] = r;
-	return r;
-end
-
-function driver:query(sql, ...)
-	local stmt = self:prepare(sql);
-	if stmt:execute(...) then return stmt; end
-end
-function driver:modify(sql, ...)
-	local stmt = self:query(sql, ...);
-	if stmt and stmt:affected() > 0 then return stmt; end
-end
-
-function driver:open(host, datastore, typ)
-	local cache_key = host.." "..datastore;
-	if self.ds_cache[cache_key] then return self.ds_cache[cache_key]; end
-	local instance = setmetatable({}, self);
-	instance.host = host;
-	instance.datastore = datastore;
-	local handler = handlers[datastore];
-	if not handler then return nil; end
-	for key,val in pairs(handler) do
-		instance[key] = val;
-	end
-	if instance.init then instance:init(); end
-	self.ds_cache[cache_key] = instance;
-	return instance;
-end
-
------------------------------
-local _M = {};
-
-function _M.new(dbtype, dbname, ...)
-	local instance = setmetatable({}, driver);
-	instance.__index = instance;
-	instance.database = get_database(dbtype, dbname, ...);
-	instance.ds_cache = {};
-	return instance;
-end
-
-return _M;