Fix SQLite3 persistence crashing if loaded twice

This commit is contained in:
Lars Mueller 2022-02-28 01:21:42 +01:00
parent d4d3b456b5
commit 7ef08b8a5c

@ -15,10 +15,9 @@ local sqlite3 = ...
Weak tables are of no use here, as we need to be notified when a reference is dropped Weak tables are of no use here, as we need to be notified when a reference is dropped
]] ]]
local _ENV = {} local ptab = {} -- SQLite3-backed implementation for a persistent Lua table ("ptab")
setfenv(1, _ENV) local metatable = {__index = ptab}
local metatable = {__index = _ENV} ptab.metatable = metatable
_ENV.metatable = metatable
-- Note: keys may not be marked as weak references: wouldn't close the database: see persistence/lua_log_file.lua -- Note: keys may not be marked as weak references: wouldn't close the database: see persistence/lua_log_file.lua
local databases = {} local databases = {}
@ -39,14 +38,14 @@ local function increment_highest_table_id(self)
return self.highest_table_id return self.highest_table_id
end end
function new(file_path, root) function ptab.new(file_path, root)
return setmetatable({ return setmetatable({
database = sqlite3.open(file_path), database = sqlite3.open(file_path),
root = root root = root
}, metatable) }, metatable)
end end
function _ENV.setmetatable(self) function ptab.setmetatable(self)
assert(self.database and self.root) assert(self.database and self.root)
return setmetatable(self, metatable) return setmetatable(self, metatable)
end end
@ -142,7 +141,7 @@ local function exec(self, sql)
end end
end end
function init(self) function ptab:init()
local database = self.database local database = self.database
local function prepare(sql) local function prepare(sql)
local stmt = database:prepare(sql) local stmt = database:prepare(sql)
@ -230,7 +229,7 @@ CREATE TABLE IF NOT EXISTS table_entries (
databases[self] = true databases[self] = true
end end
function rewrite(self) function ptab:rewrite()
exec(self, "DELETE FROM table_entries") exec(self, "DELETE FROM table_entries")
self.highest_table_id = 0 self.highest_table_id = 0
self.table_ids = {} self.table_ids = {}
@ -238,7 +237,7 @@ function rewrite(self)
add_table(self, self.root) add_table(self, self.root)
end end
function _ENV.set(self, table, key, value) function ptab:set(table, key, value)
local previous_value = table[key] local previous_value = table[key]
if previous_value == value then if previous_value == value then
-- no change -- no change
@ -248,11 +247,11 @@ function _ENV.set(self, table, key, value)
table[key] = value table[key] = value
end end
function set_root(self, key, value) function ptab:set_root(key, value)
return _ENV.set(self, self.root, key, value) return self:set(self.root, key, value)
end end
function collectgarbage(self) function ptab:collectgarbage()
local marked = {} local marked = {}
local function mark(table) local function mark(table)
if type(table) ~= "table" or marked[table] then return end if type(table) ~= "table" or marked[table] then return end
@ -270,7 +269,7 @@ function collectgarbage(self)
end end
end end
function defragment_ids(self) function ptab:defragment_ids()
local ids = {} local ids = {}
for _, id in pairs(self.table_ids) do for _, id in pairs(self.table_ids) do
table_insert(ids, id) table_insert(ids, id)
@ -300,7 +299,7 @@ local function finalize_statements(table)
end end
end end
function close(self) function ptab:close()
finalize_statements(self._prepared) finalize_statements(self._prepared)
self.database:close() self.database:close()
databases[self] = nil databases[self] = nil
@ -314,4 +313,4 @@ if minetest then
end) end)
end end
return _ENV return ptab