1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
local sql = require('lsqlite3')
local db
local function check_db_result(msg)
if db:errcode() > sql.OK then
emu.print_error(string.format('Error: %s (%s - %s)', msg, db:errcode(), db:errmsg()))
return false
end
return true
end
local function settings_path()
return manager.machine.options.entries.homepath:value():match('([^;]+)') .. '/data'
end
local function check_version_table()
local found = false
db:exec(
[[SELECT COUNT(*) FROM sqlite_master WHERE name = 'version' AND type = 'table';]],
function (udata, cols, values, names)
found = tonumber(values[1]) > 0
return 0
end)
if check_db_result('checking for "version" table') and (not found) then
db:exec(
[[CREATE TABLE version (
datfile VARCHAR NOT NULL,
version VARCHAR NOT NULL,
PRIMARY KEY (datfile));]])
found = check_db_result('creating "version" table')
end
if not found then
db:close()
db = nil
end
end
local function open_existing()
db = sql.open(settings_path() .. '/history.db', sql.OPEN_READWRITE)
if db then
check_version_table()
end
return db
end
local function open_create()
-- first try to create settings directory
local dir = settings_path()
local attr = lfs.attributes(dir)
if (not attr) and (not lfs.mkdir(dir)) then
emu.print_error(string.format('Error creating data plugin settings directory "%s"', dir))
elseif attr and (attr.mode ~= 'directory') then
emu.print_error(string.format('Error opening data plugin database: "%s" is not a directory', dir))
else
-- now try to open the database
local dbpath = dir .. '/history.db'
db = sql.open(dbpath, sql.OPEN_READWRITE | sql.OPEN_CREATE)
if not db then
emu.print_error(string.format('Error opening data plugin database "%s"', dbpath))
else
check_version_table()
end
end
return db
end
local dbtable = {
ROW = sql.ROW,
BUSY = sql.BUSY,
DONE = sql.DONE,
check = check_db_result }
function dbtable.sanitize_name(name)
return name:gsub('[^%w%."]', '_')
end
function dbtable.get_version(filename)
-- don't try to create the database here, just return nil if it doesn't exist
if (not db) and (not open_existing()) then
return nil
end
local query = db:prepare([[SELECT version FROM version WHERE datfile = ?;]])
query:bind_values(filename)
local result
while result == nil do
local status = query:step()
if status == sql.ROW then
result = query:get_value(0)
elseif status ~= sql.BUSY then
break
end
end
query:finalize()
return result
end
function dbtable.set_version(filename, version)
if (not db) and (not open_create()) then
return nil
end
local query
if version ~= nil then
query = db:prepare(
[[INSERT INTO version (datfile, version) VALUES (?1, ?2)
ON CONFLICT(datfile) DO UPDATE set version = ?2;]])
query:bind_values(filename, version)
else
query = db:prepare([[DELETE FROM version WHERE datfile = ?1;]])
query:bind_values(filename)
end
local result
while result == nil do
local status = query:step()
if status == sql.DONE then
result = true
elseif result ~= sql.ROW then
result = false
end
end
query:finalize()
return result
end
function dbtable.prepare(...)
if (not db) and open_create() then
dbtable.prepare = function (...) return db:prepare(...) end
end
if db then
return db:prepare(...)
else
return nil
end
end
function dbtable.exec(...)
if (not db) and open_create() then
dbtable.exec = function (...) return db:exec(...) end
end
if db then
return db:exec(...)
else
return nil
end
end
function dbtable.open_data_file(file)
local fh, filepath
for path in mame_manager.ui.options.entries.historypath:value():gmatch('([^;]+)') do
filepath = path .. '/' .. file
fh = io.open(filepath, 'r')
if fh then
break
end
end
return fh, filepath, dbtable.sanitize_name(file), dbtable.get_version(file)
end
return dbtable
|