-- Basic SQL driver -- This driver stores data as simple key-values local ser = require "util.serialization".serialize; local envload = require "util.envload".envload; local deser = function(data) module:log("debug", "deser: %s", tostring(data)); if not data then return nil; end local f = envload("return "..data, nil, {}); if not f then return nil; end local s, d = pcall(f); if not s then return nil; end return d; end; local driver = {}; driver.__index = driver; driver.item_table = "item"; driver.list_table = "list"; 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.connection:prepare(sql); if not r then error("Unable to prepare SQL statement: "..err); end self.sqlcache[sql] = r; return r; end function driver:load(username, host, datastore) local select = self:prepare("select data from "..self.item_table.." where username=? and host=? and datastore=?"); select:execute(username, host, datastore); local row = select:fetch(); return row and deser(row[1]) or nil; end function driver:store(username, host, datastore, data) if not data or next(data) == nil then local delete = self:prepare("delete from "..self.item_table.." where username=? and host=? and datastore=?"); delete:execute(username, host, datastore); return true; else local d = self:load(username, host, datastore); if d then -- update local update = self:prepare("update "..self.item_table.." set data=? where username=? and host=? and datastore=?"); return update:execute(ser(data), username, host, datastore); else -- insert local insert = self:prepare("insert into "..self.item_table.." values (?, ?, ?, ?)"); return insert:execute(username, host, datastore, ser(data)); end end end function driver:list_append(username, host, datastore, data) if not data then return; end local insert = self:prepare("insert into "..self.list_table.." values (?, ?, ?, ?)"); return insert:execute(username, host, datastore, ser(data)); end function driver:list_store(username, host, datastore, data) -- remove existing data local delete = self:prepare("delete from "..self.list_table.." where username=? and host=? and datastore=?"); delete:execute(username, host, datastore); if data and next(data) ~= nil then -- add data for _, d in ipairs(data) do self:list_append(username, host, datastore, ser(d)); end end return true; end function driver:list_load(username, host, datastore) local select = self:prepare("select data from "..self.list_table.." where username=? and host=? and datastore=?"); select:execute(username, host, datastore); local r = {}; for row in select:rows() do table.insert(r, deser(row[1])); end return r; end local _M = {}; function _M.new(dbtype, dbname, ...) local d = {}; setmetatable(d, driver); local dbh = get_database(dbtype, dbname, ...); --d:set_connection(dbh); d.connection = dbh; return d; end return _M;