plugins/storage/sqlbasic.lib.lua

1
-- Basic SQL driver
2
-- This driver stores data as simple key-values
3
 
4
local ser = require "util.serialization".serialize;
5
local deser = function(data)
6
	module:log("debug", "deser: %s", tostring(data));
7
	if not data then return nil; end
8
	local f = loadstring("return "..data);
9
	if not f then return nil; end
10
	setfenv(f, {});
11
	local s, d = pcall(f);
12
	if not s then return nil; end
13
	return d;
14
end;
15
 
16
local driver = {};
17
driver.__index = driver;
18
 
19
driver.item_table = "item";
20
driver.list_table = "list";
21
 
22
function driver:prepare(sql)
23
	module:log("debug", "query: %s", sql);
24
	local err;
25
	if not self.sqlcache then self.sqlcache = {}; end
26
	local r = self.sqlcache[sql];
27
	if r then return r; end
28
	r, err = self.connection:prepare(sql);
29
	if not r then error("Unable to prepare SQL statement: "..err); end
30
	self.sqlcache[sql] = r;
31
	return r;
32
end
33
 
34
function driver:load(username, host, datastore)
35
	local select = self:prepare("select data from "..self.item_table.." where username=? and host=? and datastore=?");
36
	select:execute(username, host, datastore);
37
	local row = select:fetch();
38
	return row and deser(row[1]) or nil;
39
end
40
 
41
function driver:store(username, host, datastore, data)
42
	if not data or next(data) == nil then
43
		local delete = self:prepare("delete from "..self.item_table.." where username=? and host=? and datastore=?");
44
		delete:execute(username, host, datastore);
45
		return true;
46
	else
47
		local d = self:load(username, host, datastore);
48
		if d then -- update
49
			local update = self:prepare("update "..self.item_table.." set data=? where username=? and host=? and datastore=?");
50
			return update:execute(ser(data), username, host, datastore);
51
		else -- insert
52
			local insert = self:prepare("insert into "..self.item_table.." values (?, ?, ?, ?)");
53
			return insert:execute(username, host, datastore, ser(data));
54
		end
55
	end
56
end
57
 
58
function driver:list_append(username, host, datastore, data)
59
	if not data then return; end
60
	local insert = self:prepare("insert into "..self.list_table.." values (?, ?, ?, ?)");
61
	return insert:execute(username, host, datastore, ser(data));
62
end
63
 
64
function driver:list_store(username, host, datastore, data)
65
	-- remove existing data
66
	local delete = self:prepare("delete from "..self.list_table.." where username=? and host=? and datastore=?");
67
	delete:execute(username, host, datastore);
68
	if data and next(data) ~= nil then
69
		-- add data
70
		for _, d in ipairs(data) do
71
			self:list_append(username, host, datastore, ser(d));
72
		end
73
	end
74
	return true;
75
end
76
 
77
function driver:list_load(username, host, datastore)
78
	local select = self:prepare("select data from "..self.list_table.." where username=? and host=? and datastore=?");
79
	select:execute(username, host, datastore);
80
	local r = {};
81
	for row in select:rows() do
82
		table.insert(r, deser(row[1]));
83
	end
84
	return r;
85
end
86
 
87
local _M = {};
88
function _M.new(dbtype, dbname, ...)
89
	local d = {};
90
	setmetatable(d, driver);
91
	local dbh = get_database(dbtype, dbname, ...);
92
	--d:set_connection(dbh);
93
	d.connection = dbh;
94
	return d;
95
end
96
return _M;