Database Library
Comprehensive database management system with SQLite support for the Lilia framework.
Overview
The database library provides comprehensive database management functionality for the Lilia framework. It handles all database operations including connection management, table creation and modification, data insertion, updates, queries, and schema management. The library supports SQLite as the primary database engine with extensible module support for other database systems. It includes advanced features such as prepared statements, transactions, bulk operations, data type conversion, and database snapshots for backup and restore operations. The library ensures data persistence across server restarts and provides robust error handling with deferred promise-based operations for asynchronous database queries. It manages core gamemode tables for players, characters, inventories, items, configuration, logs, and administrative data while supporting dynamic schema modifications.
connect
Purpose
Establishes a connection to the database using the configured database module
When Called
During server startup, module initialization, or when reconnecting to database
Parameters
callback(function, optional): Function to call after successful connectionreconnect(boolean, optional): Force reconnection even if already connected
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Connect to database with callback
lia.db.connect(function()
print("Database connected successfully!")
end)
Medium Complexity:
-- Medium: Connect with error handling and reconnection
lia.db.connect(function()
lia.log.add("Database connection established")
lia.db.loadTables()
end, true)
High Complexity:
-- High: Connect with conditional logic and module validation
if lia.db.module and lia.db.modules[lia.db.module] then
lia.db.connect(function()
lia.bootstrap("Database", "Connected to " .. lia.db.module)
hook.Run("OnDatabaseConnected")
end, not lia.db.connected)
else
lia.error("Invalid database module: " .. tostring(lia.db.module))
end
wipeTables
Purpose
Removes all Lilia database tables and their data from the database
When Called
During database reset operations, development testing, or administrative cleanup
Parameters
callback(function, optional): Function to call after all tables are wiped
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Wipe all tables with confirmation
lia.db.wipeTables(function()
print("All database tables have been wiped!")
end)
Medium Complexity:
-- Medium: Wipe tables with logging and backup
lia.log.add("Starting database wipe operation")
lia.db.wipeTables(function()
lia.log.add("Database wipe completed successfully")
hook.Run("OnDatabaseWiped")
end)
High Complexity:
-- High: Wipe tables with confirmation and error handling
local function confirmWipe()
lia.db.wipeTables(function()
lia.bootstrap("Database", "All tables wiped successfully")
lia.db.loadTables() -- Reload empty tables
hook.Run("OnDatabaseReset")
end)
end
if lia.config.get("allowDatabaseWipe", false) then
confirmWipe()
else
lia.error("Database wipe not allowed by configuration")
end
loadTables
Purpose
Creates all core Lilia database tables if they don't exist and initializes the database schema
When Called
During server startup after database connection, or when initializing a new database
Returns
- None
Realm
Server
Example Usage
Low Complexity:
Medium Complexity:
-- Medium: Load tables with hook integration
lia.db.connect(function()
lia.db.loadTables()
lia.log.add("Database tables loaded successfully")
end)
High Complexity:
-- High: Load tables with conditional logic and error handling
local function initializeDatabase()
lia.db.connect(function()
lia.db.loadTables()
hook.Run("OnDatabaseInitialized")
lia.bootstrap("Database", "Schema loaded and ready")
end, true)
end
if lia.db.module and lia.db.modules[lia.db.module] then
initializeDatabase()
else
lia.error("Cannot initialize database: invalid module")
end
waitForTablesToLoad
Purpose
Returns a deferred promise that resolves when database tables have finished loading
When Called
Before performing database operations that require tables to be loaded
Returns
- Deferred promise object
Realm
Server
Example Usage
Low Complexity:
-- Simple: Wait for tables to load before proceeding
lia.db.waitForTablesToLoad():next(function()
print("Tables are ready!")
end)
Medium Complexity:
-- Medium: Wait for tables with error handling
lia.db.waitForTablesToLoad():next(function()
lia.log.add("Database tables loaded, proceeding with initialization")
hook.Run("OnTablesReady")
end):catch(function(err)
lia.error("Failed to load database tables: " .. tostring(err))
end)
High Complexity:
-- High: Wait for tables with timeout and fallback
local function initializeAfterTables()
lia.db.waitForTablesToLoad():next(function()
lia.char.loadCharacters()
lia.inventory.loadInventories()
lia.bootstrap("Database", "All systems initialized")
end):catch(function(err)
lia.error("Critical database initialization failure: " .. tostring(err))
lia.db.connect(function()
lia.db.loadTables()
initializeAfterTables()
end, true)
end)
end
initializeAfterTables()
convertDataType
Purpose
Converts Lua values to SQL-compatible format with proper escaping and type handling
When Called
Internally by database functions when preparing data for SQL queries
Parameters
value(any): The value to convert to SQL formatnoEscape(boolean, optional): Skip escaping for raw SQL values
Returns
- String representation of the value in SQL format
Realm
Server
Example Usage
Low Complexity:
-- Simple: Convert basic data types
local sqlString = lia.db.convertDataType("Hello World")
local sqlNumber = lia.db.convertDataType(42)
local sqlBool = lia.db.convertDataType(true)
Medium Complexity:
-- Medium: Convert complex data with escaping
local playerData = {
name = "John Doe",
level = 25,
isActive = true,
inventory = {weapon = "pistol", ammo = 100}
}
local sqlData = {}
for key, value in pairs(playerData) do
sqlData[key] = lia.db.convertDataType(value)
end
High Complexity:
-- High: Convert with conditional logic and error handling
local function safeConvert(value, fieldName)
if value == nil then
return "NULL"
elseif type(value) == "table" then
local success, json = pcall(util.TableToJSON, value)
if success then
return "'" .. lia.db.escape(json) .. "'"
else
lia.log.add("Failed to convert table for field: " .. fieldName)
return "NULL"
end
else
return lia.db.convertDataType(value)
end
end
insertTable
Purpose
Inserts a new record into a specified database table
When Called
When creating new database records for players, characters, items, etc.
Parameters
value(table): Key-value pairs representing the data to insertcallback(function, optional): Function to call after successful insertiondbTable(string, optional): Table name without 'lia_' prefix (defaults to 'characters')
Returns
- Deferred promise object with results and lastID
Realm
Server
Example Usage
Low Complexity:
-- Simple: Insert a new character
lia.db.insertTable({
steamID = "STEAM_0:1:12345678",
name = "John Doe",
model = "models/player/kleiner.mdl"
}, function(results, lastID)
print("Character created with ID:", lastID)
end, "characters")
Medium Complexity:
-- Medium: Insert with error handling and validation
local characterData = {
steamID = player:SteamID(),
name = player:Name(),
model = player:GetModel(),
faction = "citizen",
money = "0"
}
lia.db.insertTable(characterData, function(results, lastID)
if lastID then
lia.log.add("Character created for " .. player:Name())
hook.Run("OnCharacterCreated", player, lastID)
end
end, "characters")
High Complexity:
-- High: Insert with validation, error handling, and rollback
local function createCharacterWithValidation(playerData)
local validation = lia.char.validateData(playerData)
if not validation.valid then
return deferred.new():reject("Validation failed: " .. validation.error)
end
return lia.db.insertTable(playerData, function(results, lastID)
if lastID then
lia.char.cache[lastID] = playerData
hook.Run("OnCharacterCreated", lastID, playerData)
end
end, "characters")
end
updateTable
Purpose
Updates existing records in a specified database table based on conditions
When Called
When modifying existing database records for players, characters, items, etc.
Parameters
value(table): Key-value pairs representing the data to updatecallback(function, optional): Function to call after successful updatedbTable(string, optional): Table name without 'lia_' prefix (defaults to 'characters')condition(table/string, optional): WHERE clause conditions for the update
Returns
- Deferred promise object with results and lastID
Realm
Server
Example Usage
Low Complexity:
-- Simple: Update character money
lia.db.updateTable({
money = "1000"
}, function(results, lastID)
print("Character updated successfully!")
end, "characters", {id = 1})
Medium Complexity:
-- Medium: Update with complex conditions and logging
local updateData = {
lastJoinTime = os.date("%Y-%m-%d %H:%M:%S"),
money = tostring(character:getMoney())
}
lia.db.updateTable(updateData, function(results, lastID)
if results then
lia.log.add("Character " .. character:getName() .. " updated")
hook.Run("OnCharacterUpdated", character)
end
end, "characters", {id = character:getID()})
High Complexity:
-- High: Update with validation, transaction, and rollback
local function updateCharacterWithValidation(charID, updateData)
return lia.db.transaction({
"BEGIN TRANSACTION",
"UPDATE lia_characters SET " ..
table.concat(lia.util.map(updateData, function(k, v)
return k .. " = " .. lia.db.convertDataType(v)
end), ", ") ..
" WHERE id = " .. charID,
"COMMIT"
}):next(function()
lia.char.cache[charID] = lia.util.merge(lia.char.cache[charID] or {}, updateData)
hook.Run("OnCharacterUpdated", charID, updateData)
end):catch(function(err)
lia.error("Failed to update character " .. charID .. ": " .. tostring(err))
end)
end
select
Purpose
Performs a SELECT query on a specified database table with optional conditions and limits
When Called
When retrieving data from database tables for players, characters, items, etc.
Parameters
fields(string/table): Field names to select (string or table of strings)dbTable(string, optional): Table name without 'lia_' prefix (defaults to 'characters')condition(table/string, optional): WHERE clause conditions for the querylimit(number, optional): Maximum number of records to return
Returns
- Deferred promise object with results array
Realm
Server
Example Usage
Low Complexity:
-- Simple: Select all characters
lia.db.select("*", "characters"):next(function(results)
print("Found " .. #results .. " characters")
end)
Medium Complexity:
-- Medium: Select with conditions and specific fields
lia.db.select({"name", "money", "faction"}, "characters", {
steamID = "STEAM_0:1:12345678"
}, 10):next(function(results)
for _, char in ipairs(results) do
print(char.name .. " has $" .. char.money)
end
end)
High Complexity:
-- High: Select with complex conditions, pagination, and error handling
local function getCharactersByFaction(faction, page, pageSize)
local offset = (page - 1) * pageSize
return lia.db.select("*", "characters", {
faction = faction,
lastJoinTime = {operator = ">", value = os.date("%Y-%m-%d", os.time() - 86400)}
}, pageSize):next(function(results)
local characters = {}
for _, char in ipairs(results) do
table.insert(characters, lia.char.new(char))
end
return characters
end):catch(function(err)
lia.error("Failed to load characters: " .. tostring(err))
return {}
end)
end
selectWithCondition
Purpose
Performs a SELECT query with advanced condition handling and optional ordering
When Called
When retrieving data with complex WHERE clauses and ORDER BY requirements
Parameters
fields(string/table): Field names to select (string or table of strings)dbTable(string, optional): Table name without 'lia_' prefix (defaults to 'characters')conditions(table/string, optional): WHERE clause conditions with operator supportlimit(number, optional): Maximum number of records to returnorderBy(string, optional): ORDER BY clause for sorting results
Returns
- Deferred promise object with results array
Realm
Server
Example Usage
Low Complexity:
-- Simple: Select with basic condition
lia.db.selectWithCondition("*", "characters", {
faction = "citizen"
}):next(function(results)
print("Found " .. #results .. " citizens")
end)
Medium Complexity:
-- Medium: Select with operators and ordering
lia.db.selectWithCondition({"name", "money"}, "characters", {
money = {operator = ">", value = "1000"},
faction = "citizen"
}, 5, "money DESC"):next(function(results)
for _, char in ipairs(results) do
print(char.name .. " has $" .. char.money)
end
end)
High Complexity:
-- High: Select with complex conditions, pagination, and error handling
local function searchCharacters(searchTerm, faction, minMoney, maxResults)
local conditions = {}
if searchTerm then
conditions.name = {operator = "LIKE", value = "%" .. searchTerm .. "%"}
end
if faction then
conditions.faction = faction
end
if minMoney then
conditions.money = {operator = ">=", value = tostring(minMoney)}
end
return lia.db.selectWithCondition("*", "characters", conditions,
maxResults, "lastJoinTime DESC"):next(function(results)
local characters = {}
for _, char in ipairs(results) do
table.insert(characters, lia.char.new(char))
end
return characters
end):catch(function(err)
lia.error("Character search failed: " .. tostring(err))
return {}
end)
end
count
Purpose
Counts the number of records in a database table matching specified conditions
When Called
When checking record counts for statistics, validation, or pagination
Parameters
dbTable(string): Table name without 'lia_' prefixcondition(table/string, optional): WHERE clause conditions for counting
Returns
- Deferred promise object resolving to the count number
Realm
Server
Example Usage
Low Complexity:
-- Simple: Count all characters
lia.db.count("characters"):next(function(count)
print("Total characters: " .. count)
end)
Medium Complexity:
-- Medium: Count with conditions
lia.db.count("characters", {
faction = "citizen",
money = {operator = ">", value = "1000"}
}):next(function(count)
print("Rich citizens: " .. count)
end)
High Complexity:
-- High: Count with validation and error handling
local function getPlayerStats(steamID)
return lia.db.count("characters", {steamID = steamID}):next(function(charCount)
return lia.db.count("players", {steamID = steamID}):next(function(playerCount)
return {
characters = charCount,
playerRecords = playerCount,
isNewPlayer = playerCount == 0
}
end)
end):catch(function(err)
lia.error("Failed to get player stats: " .. tostring(err))
return {characters = 0, playerRecords = 0, isNewPlayer = true}
end)
end
addDatabaseFields
Purpose
Dynamically adds new columns to the lia_characters table based on character variables
When Called
During database initialization to ensure character table has all required fields
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Add fields after table creation
lia.db.loadTables() -- This automatically calls addDatabaseFields()
Medium Complexity:
-- Medium: Add fields with logging
lia.db.addDatabaseFields()
lia.log.add("Database fields updated for character variables")
High Complexity:
-- High: Add fields with validation and error handling
local function ensureCharacterFields()
if not istable(lia.char.vars) then
lia.log.add("Character variables not defined, skipping field addition")
return
end
lia.db.addDatabaseFields()
lia.log.add("Character database fields synchronized")
hook.Run("OnCharacterFieldsUpdated")
end
ensureCharacterFields()
exists
Purpose
Checks if any records exist in a database table matching specified conditions
When Called
When validating data existence before operations or for conditional logic
Parameters
dbTable(string): Table name without 'lia_' prefixcondition(table/string, optional): WHERE clause conditions for checking existence
Returns
- Deferred promise object resolving to boolean (true if records exist)
Realm
Server
Example Usage
Low Complexity:
-- Simple: Check if player exists
lia.db.exists("players", {steamID = "STEAM_0:1:12345678"}):next(function(exists)
if exists then
print("Player found in database")
else
print("New player")
end
end)
Medium Complexity:
-- Medium: Check with complex conditions
lia.db.exists("characters", {
steamID = player:SteamID(),
faction = "citizen",
money = {operator = ">", value = "1000"}
}):next(function(exists)
if exists then
lia.log.add("Player has wealthy citizen character")
end
end)
High Complexity:
-- High: Check with validation and error handling
local function validatePlayerData(steamID)
return lia.db.exists("players", {steamID = steamID}):next(function(playerExists)
if not playerExists then
return lia.db.insertTable({
steamID = steamID,
steamName = "Unknown",
firstJoin = os.date("%Y-%m-%d %H:%M:%S"),
userGroup = "user"
}, nil, "players")
end
return playerExists
end):catch(function(err)
lia.error("Failed to validate player data: " .. tostring(err))
return false
end)
end
selectOne
Purpose
Retrieves a single record from a database table matching specified conditions
When Called
When fetching unique records like player data, character info, or single items
Parameters
fields(string/table): Field names to select (string or table of strings)dbTable(string): Table name without 'lia_' prefixcondition(table/string, optional): WHERE clause conditions for the query
Returns
- Deferred promise object resolving to the first matching record or nil
Realm
Server
Example Usage
Low Complexity:
-- Simple: Get character by ID
lia.db.selectOne("*", "characters", {id = 1}):next(function(char)
if char then
print("Character name: " .. char.name)
end
end)
Medium Complexity:
-- Medium: Get player data with specific fields
lia.db.selectOne({"steamName", "userGroup", "lastJoin"}, "players", {
steamID = player:SteamID()
}):next(function(playerData)
if playerData then
player:SetUserGroup(playerData.userGroup)
lia.log.add("Loaded player: " .. playerData.steamName)
end
end)
High Complexity:
-- High: Get with validation and error handling
local function loadCharacter(charID)
return lia.db.selectOne("*", "characters", {id = charID}):next(function(charData)
if not charData then
return deferred.new():reject("Character not found")
end
local character = lia.char.new(charData)
lia.char.cache[charID] = character
hook.Run("OnCharacterLoaded", character)
return character
end):catch(function(err)
lia.error("Failed to load character " .. charID .. ": " .. tostring(err))
return nil
end)
end
bulkInsert
Purpose
Inserts multiple records into a database table in a single operation for better performance
When Called
When inserting large amounts of data like inventory items, logs, or batch operations
Parameters
dbTable(string): Table name without 'lia_' prefixrows(table): Array of tables containing the data to insert
Returns
- Deferred promise object resolving when all records are inserted
Realm
Server
Example Usage
Low Complexity:
-- Simple: Insert multiple items
local items = {
{uniqueID = "pistol", quantity = 1, x = 1, y = 1},
{uniqueID = "ammo", quantity = 50, x = 2, y = 1}
}
lia.db.bulkInsert("items", items):next(function()
print("Items inserted successfully")
end)
Medium Complexity:
-- Medium: Insert with validation and error handling
local function insertInventoryItems(invID, items)
local rows = {}
for _, item in ipairs(items) do
table.insert(rows, {
invID = invID,
uniqueID = item.uniqueID,
data = util.TableToJSON(item.data or {}),
quantity = item.quantity or 1,
x = item.x or 1,
y = item.y or 1
})
end
return lia.db.bulkInsert("items", rows):next(function()
lia.log.add("Inserted " .. #rows .. " items into inventory " .. invID)
end):catch(function(err)
lia.error("Failed to insert items: " .. tostring(err))
end)
end
High Complexity:
-- High: Insert with batching, validation, and progress tracking
local function bulkInsertWithBatching(dbTable, data, batchSize)
batchSize = batchSize or 100
local batches = {}
for i = 1, #data, batchSize do
local batch = {}
for j = i, math.min(i + batchSize - 1, #data) do
table.insert(batch, data[j])
end
table.insert(batches, batch)
end
local currentBatch = 1
local function insertNextBatch()
if currentBatch > #batches then
return deferred.new():resolve()
end
return lia.db.bulkInsert(dbTable, batches[currentBatch]):next(function()
lia.log.add("Batch " .. currentBatch .. "/" .. #batches .. " completed")
currentBatch = currentBatch + 1
return insertNextBatch()
end)
end
return insertNextBatch()
end
bulkUpsert
Purpose
Performs bulk INSERT OR REPLACE operations for updating existing records or inserting new ones
When Called
When synchronizing data that may already exist, like configuration updates or data imports
Parameters
dbTable(string): Table name without 'lia_' prefixrows(table): Array of tables containing the data to upsert
Returns
- Deferred promise object resolving when all records are upserted
Realm
Server
Example Usage
Low Complexity:
-- Simple: Upsert configuration data
local configs = {
{schema = "default", key = "maxPlayers", value = "32"},
{schema = "default", key = "serverName", value = "My Server"}
}
lia.db.bulkUpsert("config", configs):next(function()
print("Configuration updated")
end)
Medium Complexity:
-- Medium: Upsert with validation and error handling
local function syncPlayerData(players)
local rows = {}
for _, player in ipairs(players) do
table.insert(rows, {
steamID = player:SteamID(),
steamName = player:Name(),
lastJoin = os.date("%Y-%m-%d %H:%M:%S"),
lastIP = player:IPAddress(),
userGroup = player:GetUserGroup()
})
end
return lia.db.bulkUpsert("players", rows):next(function()
lia.log.add("Synchronized " .. #rows .. " player records")
end):catch(function(err)
lia.error("Failed to sync player data: " .. tostring(err))
end)
end
High Complexity:
-- High: Upsert with conflict resolution and progress tracking
local function bulkSyncWithConflictResolution(dbTable, data, conflictFields)
local batches = {}
local batchSize = 50
for i = 1, #data, batchSize do
local batch = {}
for j = i, math.min(i + batchSize - 1, #data) do
local record = data[j]
-- Add conflict resolution metadata
record._syncTimestamp = os.time()
record._conflictFields = conflictFields
table.insert(batch, record)
end
table.insert(batches, batch)
end
local completed = 0
local function processNextBatch()
if completed >= #batches then
return deferred.new():resolve()
end
return lia.db.bulkUpsert(dbTable, batches[completed + 1]):next(function()
completed = completed + 1
lia.log.add("Batch " .. completed .. "/" .. #batches .. " synced")
return processNextBatch()
end)
end
return processNextBatch()
end
insertOrIgnore
Purpose
Inserts a record into a database table, ignoring the operation if it would cause a constraint violation
When Called
When inserting data that may already exist, like unique configurations or duplicate-safe operations
Parameters
value(table): Key-value pairs representing the data to insertdbTable(string, optional): Table name without 'lia_' prefix (defaults to 'characters')
Returns
- Deferred promise object with results and lastID
Realm
Server
Example Usage
Low Complexity:
-- Simple: Insert configuration without duplicates
lia.db.insertOrIgnore({
schema = "default",
key = "serverName",
value = "My Server"
}, "config"):next(function(results, lastID)
print("Configuration inserted or ignored")
end)
Medium Complexity:
-- Medium: Insert with validation and logging
local function ensureDefaultConfig(configs)
for _, config in ipairs(configs) do
lia.db.insertOrIgnore({
schema = config.schema,
key = config.key,
value = config.value
}, "config"):next(function(results, lastID)
if lastID then
lia.log.add("Added new config: " .. config.key)
end
end)
end
end
High Complexity:
-- High: Insert with conflict detection and fallback
local function safeInsertWithFallback(data, dbTable, fallbackData)
return lia.db.insertOrIgnore(data, dbTable):next(function(results, lastID)
if lastID then
-- Successfully inserted new record
return {success = true, id = lastID, action = "inserted"}
else
-- Record already exists, try fallback operation
return lia.db.updateTable(fallbackData, nil, dbTable, {
[data.primaryKey or "id"] = data.id
}):next(function()
return {success = true, action = "updated"}
end)
end
end):catch(function(err)
lia.error("Insert or ignore failed: " .. tostring(err))
return {success = false, error = err}
end)
end
tableExists
Purpose
Checks if a database table exists in the current database
When Called
When validating table existence before operations or during schema validation
Parameters
tbl(string): Table name to check for existence
Returns
- Deferred promise object resolving to boolean (true if table exists)
Realm
Server
Example Usage
Low Complexity:
-- Simple: Check if table exists
lia.db.tableExists("lia_characters"):next(function(exists)
if exists then
print("Characters table exists")
else
print("Characters table missing")
end
end)
Medium Complexity:
-- Medium: Check with conditional logic
lia.db.tableExists("lia_custom_table"):next(function(exists)
if not exists then
lia.log.add("Custom table missing, creating...")
lia.db.createTable("custom_table", "id", {
{name = "id", type = "INTEGER", not_null = true},
{name = "data", type = "TEXT"}
})
end
end)
High Complexity:
-- High: Check with validation and error handling
local function validateDatabaseSchema()
local requiredTables = {"characters", "players", "items", "inventories"}
local missingTables = {}
local function checkNextTable(index)
if index > #requiredTables then
if #missingTables > 0 then
lia.error("Missing tables: " .. table.concat(missingTables, ", "))
return lia.db.loadTables()
else
lia.log.add("All required tables exist")
return deferred.new():resolve()
end
end
local tableName = "lia_" .. requiredTables[index]
return lia.db.tableExists(tableName):next(function(exists)
if not exists then
table.insert(missingTables, tableName)
end
return checkNextTable(index + 1)
end)
end
return checkNextTable(1)
end
fieldExists
Purpose
Checks if a specific field/column exists in a database table
When Called
When validating column existence before operations or during schema migrations
Parameters
tbl(string): Table name to checkfield(string): Field/column name to check for existence
Returns
- Deferred promise object resolving to boolean (true if field exists)
Realm
Server
Example Usage
Low Complexity:
-- Simple: Check if field exists
lia.db.fieldExists("lia_characters", "money"):next(function(exists)
if exists then
print("Money field exists")
else
print("Money field missing")
end
end)
Medium Complexity:
-- Medium: Check with conditional field creation
lia.db.fieldExists("lia_characters", "newField"):next(function(exists)
if not exists then
lia.log.add("Adding new field to characters table")
lia.db.createColumn("characters", "newField", "VARCHAR(255)", "default_value")
end
end)
High Complexity:
-- High: Check with validation and error handling
local function validateCharacterFields()
local requiredFields = {"name", "steamID", "money", "faction", "model"}
local missingFields = {}
local function checkNextField(index)
if index > #requiredFields then
if #missingFields > 0 then
lia.error("Missing character fields: " .. table.concat(missingFields, ", "))
return lia.db.addDatabaseFields()
else
lia.log.add("All required character fields exist")
return deferred.new():resolve()
end
end
return lia.db.fieldExists("lia_characters", requiredFields[index]):next(function(exists)
if not exists then
table.insert(missingFields, requiredFields[index])
end
return checkNextField(index + 1)
end)
end
return checkNextField(1)
end
getTables
Purpose
Retrieves a list of all Lilia database tables in the current database
When Called
When auditing database structure, generating reports, or managing tables
Returns
- Deferred promise object resolving to array of table names
Realm
Server
Example Usage
Low Complexity:
-- Simple: Get all Lilia tables
lia.db.getTables():next(function(tables)
print("Found " .. #tables .. " Lilia tables")
for _, tableName in ipairs(tables) do
print("- " .. tableName)
end
end)
Medium Complexity:
-- Medium: Get tables with analysis
lia.db.getTables():next(function(tables)
local coreTables = {"lia_characters", "lia_players", "lia_items"}
local missingTables = {}
for _, coreTable in ipairs(coreTables) do
if not table.HasValue(tables, coreTable) then
table.insert(missingTables, coreTable)
end
end
if #missingTables > 0 then
lia.log.add("Missing core tables: " .. table.concat(missingTables, ", "))
else
lia.log.add("All core tables present")
end
end)
High Complexity:
-- High: Get tables with validation and management
local function auditDatabaseStructure()
return lia.db.getTables():next(function(tables)
local tableStats = {}
local function analyzeNextTable(index)
if index > #tables then
lia.log.add("Database audit complete:")
for tableName, stats in pairs(tableStats) do
lia.log.add(tableName .. ": " .. stats.count .. " records")
end
return tableStats
end
local tableName = tables[index]
return lia.db.count(tableName:sub(5)):next(function(count)
tableStats[tableName] = {count = count}
return analyzeNextTable(index + 1)
end)
end
return analyzeNextTable(1)
end):catch(function(err)
lia.error("Database audit failed: " .. tostring(err))
return {}
end)
end
transaction
Purpose
Executes multiple database queries as a single atomic transaction with rollback on failure
When Called
When performing complex operations that must succeed or fail together
Parameters
queries(table): Array of SQL query strings to execute in sequence
Returns
- Deferred promise object resolving when all queries succeed or rejecting on failure
Realm
Server
Example Usage
Low Complexity:
-- Simple: Transfer money between characters
lia.db.transaction({
"UPDATE lia_characters SET money = money - 100 WHERE id = 1",
"UPDATE lia_characters SET money = money + 100 WHERE id = 2"
}):next(function()
print("Money transfer completed")
end):catch(function(err)
print("Transfer failed: " .. tostring(err))
end)
Medium Complexity:
-- Medium: Create character with inventory
local function createCharacterWithInventory(charData)
local queries = {
"INSERT INTO lia_characters (steamID, name, faction) VALUES ('" ..
charData.steamID .. "', '" .. charData.name .. "', '" .. charData.faction .. "')",
"INSERT INTO lia_inventories (charID, invType) VALUES (last_insert_rowid(), 'pocket')"
}
return lia.db.transaction(queries):next(function()
lia.log.add("Character and inventory created successfully")
hook.Run("OnCharacterCreated", charData)
end):catch(function(err)
lia.error("Failed to create character: " .. tostring(err))
end)
end
High Complexity:
-- High: Complex transaction with validation and rollback
local function transferItemsWithValidation(fromChar, toChar, items)
local queries = {}
local validationQueries = {}
-- Build validation queries
for _, item in ipairs(items) do
table.insert(validationQueries,
"SELECT COUNT(*) FROM lia_items WHERE invID = " .. fromChar.invID ..
" AND uniqueID = '" .. item.uniqueID .. "' AND quantity >= " .. item.quantity)
end
-- Build transfer queries
for _, item in ipairs(items) do
table.insert(queries,
"UPDATE lia_items SET quantity = quantity - " .. item.quantity ..
" WHERE invID = " .. fromChar.invID .. " AND uniqueID = '" .. item.uniqueID .. "'")
table.insert(queries,
"INSERT OR REPLACE INTO lia_items (invID, uniqueID, quantity) VALUES (" ..
toChar.invID .. ", '" .. item.uniqueID .. "', " .. item.quantity .. ")")
end
return lia.db.transaction(queries):next(function()
lia.log.add("Items transferred successfully")
hook.Run("OnItemsTransferred", fromChar, toChar, items)
end):catch(function(err)
lia.error("Item transfer failed: " .. tostring(err))
hook.Run("OnTransferFailed", fromChar, toChar, items, err)
end)
end
escapeIdentifier
Purpose
Escapes database identifiers (table names, column names) to prevent SQL injection
When Called
Internally by database functions when building SQL queries with dynamic identifiers
Parameters
id(string): Identifier to escape (table name, column name, etc.)
Returns
- Escaped identifier string wrapped in backticks
Realm
Server
Example Usage
Low Complexity:
-- Simple: Escape a column name
local escapedColumn = lia.db.escapeIdentifier("user_name")
-- Returns: `user_name`
Medium Complexity:
-- Medium: Escape multiple identifiers
local function buildSelectQuery(tableName, columns)
local escapedTable = lia.db.escapeIdentifier(tableName)
local escapedColumns = {}
for _, column in ipairs(columns) do
table.insert(escapedColumns, lia.db.escapeIdentifier(column))
end
return "SELECT " .. table.concat(escapedColumns, ", ") .. " FROM " .. escapedTable
end
High Complexity:
-- High: Escape with validation and error handling
local function safeEscapeIdentifiers(identifiers)
local escaped = {}
for _, id in ipairs(identifiers) do
if type(id) == "string" and id:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then
table.insert(escaped, lia.db.escapeIdentifier(id))
else
lia.log.add("Invalid identifier: " .. tostring(id))
return nil
end
end
return escaped
end
upsert
Purpose
Inserts a new record or updates an existing one based on primary key conflicts
When Called
When synchronizing data that may already exist, like configuration updates or data imports
Parameters
value(table): Key-value pairs representing the data to upsertdbTable(string, optional): Table name without 'lia_' prefix (defaults to 'characters')
Returns
- Deferred promise object with results and lastID
Realm
Server
Example Usage
Low Complexity:
-- Simple: Upsert configuration
lia.db.upsert({
schema = "default",
key = "serverName",
value = "My Server"
}, "config"):next(function(results, lastID)
print("Configuration upserted")
end)
Medium Complexity:
-- Medium: Upsert with validation and logging
local function syncPlayerData(player)
local playerData = {
steamID = player:SteamID(),
steamName = player:Name(),
lastJoin = os.date("%Y-%m-%d %H:%M:%S"),
userGroup = player:GetUserGroup()
}
return lia.db.upsert(playerData, "players"):next(function(results, lastID)
lia.log.add("Player data synchronized: " .. player:Name())
hook.Run("OnPlayerDataSynced", player, lastID)
end):catch(function(err)
lia.error("Failed to sync player data: " .. tostring(err))
end)
end
High Complexity:
-- High: Upsert with conflict resolution and validation
local function upsertWithValidation(data, dbTable, validationRules)
local validation = validateData(data, validationRules)
if not validation.valid then
return deferred.new():reject("Validation failed: " .. validation.error)
end
return lia.db.upsert(data, dbTable):next(function(results, lastID)
local action = lastID and "inserted" or "updated"
lia.log.add("Record " .. action .. " in " .. dbTable)
-- Update cache if applicable
if lia.char.cache and dbTable == "characters" then
lia.char.cache[data.id or lastID] = data
end
hook.Run("OnRecordUpserted", dbTable, data, action)
return {success = true, action = action, id = lastID}
end):catch(function(err)
lia.error("Upsert failed: " .. tostring(err))
return {success = false, error = err}
end)
end
delete
Purpose
Deletes records from a database table based on specified conditions
When Called
When removing data like deleted characters, expired items, or cleanup operations
Parameters
dbTable(string, optional): Table name without 'lia_' prefix (defaults to 'character')condition(table/string, optional): WHERE clause conditions for the deletion
Returns
- Deferred promise object with results and lastID
Realm
Server
Example Usage
Low Complexity:
-- Simple: Delete character by ID
lia.db.delete("characters", {id = 1}):next(function(results, lastID)
print("Character deleted")
end)
Medium Complexity:
-- Medium: Delete with validation and logging
local function deleteCharacter(charID)
return lia.db.delete("characters", {id = charID}):next(function(results, lastID)
lia.log.add("Character " .. charID .. " deleted")
hook.Run("OnCharacterDeleted", charID)
-- Clean up related data
lia.db.delete("items", {invID = charID})
lia.db.delete("inventories", {charID = charID})
end):catch(function(err)
lia.error("Failed to delete character: " .. tostring(err))
end)
end
High Complexity:
-- High: Delete with cascade and transaction safety
local function deleteCharacterWithCascade(charID)
return lia.db.transaction({
"DELETE FROM lia_items WHERE invID IN (SELECT invID FROM lia_inventories WHERE charID = " .. charID .. ")",
"DELETE FROM lia_inventories WHERE charID = " .. charID,
"DELETE FROM lia_chardata WHERE charID = " .. charID,
"DELETE FROM lia_characters WHERE id = " .. charID
}):next(function()
lia.log.add("Character " .. charID .. " and all related data deleted")
-- Update cache
if lia.char.cache then
lia.char.cache[charID] = nil
end
hook.Run("OnCharacterDeleted", charID)
return {success = true, charID = charID}
end):catch(function(err)
lia.error("Failed to delete character with cascade: " .. tostring(err))
return {success = false, error = err}
end)
end
createTable
Purpose
Creates a new database table with specified schema and primary key
When Called
When setting up custom tables for modules or extending the database schema
Parameters
dbName(string): Table name without 'lia_' prefixprimaryKey(string, optional): Primary key column nameschema(table): Array of column definitions with name, type, not_null, and default properties
Returns
- Deferred promise object resolving to true on success
Realm
Server
Example Usage
Low Complexity:
-- Simple: Create a basic table
lia.db.createTable("custom_data", "id", {
{name = "id", type = "INTEGER", not_null = true},
{name = "data", type = "TEXT"}
}):next(function(success)
print("Table created successfully")
end)
Medium Complexity:
-- Medium: Create table with validation
local function createPlayerStatsTable()
local schema = {
{name = "id", type = "INTEGER", not_null = true},
{name = "steamID", type = "VARCHAR(255)", not_null = true},
{name = "kills", type = "INTEGER", default = 0},
{name = "deaths", type = "INTEGER", default = 0},
{name = "score", type = "INTEGER", default = 0},
{name = "lastUpdated", type = "DATETIME", default = "CURRENT_TIMESTAMP"}
}
return lia.db.createTable("player_stats", "id", schema):next(function(success)
if success then
lia.log.add("Player stats table created")
hook.Run("OnPlayerStatsTableCreated")
end
end):catch(function(err)
lia.error("Failed to create player stats table: " .. tostring(err))
end)
end
High Complexity:
-- High: Create table with validation and error handling
local function createModuleTable(moduleName, tableConfig)
local function validateSchema(schema)
for _, column in ipairs(schema) do
if not column.name or not column.type then
return false, "Invalid column definition"
end
end
return true
end
local valid, error = validateSchema(tableConfig.schema)
if not valid then
return deferred.new():reject("Schema validation failed: " .. error)
end
return lia.db.tableExists("lia_" .. moduleName .. "_" .. tableConfig.name):next(function(exists)
if exists then
lia.log.add("Table already exists: " .. moduleName .. "_" .. tableConfig.name)
return true
end
return lia.db.createTable(moduleName .. "_" .. tableConfig.name,
tableConfig.primaryKey, tableConfig.schema):next(function(success)
if success then
lia.log.add("Module table created: " .. moduleName .. "_" .. tableConfig.name)
hook.Run("OnModuleTableCreated", moduleName, tableConfig.name)
end
return success
end)
end)
end
createColumn
Purpose
Adds a new column to an existing database table
When Called
When extending table schemas, adding new fields, or during database migrations
Parameters
tableName(string): Table name without 'lia_' prefixcolumnName(string): Name of the new column to addcolumnType(string): SQL data type for the columndefaultValue(any, optional): Default value for the column
Returns
- Deferred promise object resolving to true on success, false if column already exists
Realm
Server
Example Usage
Low Complexity:
-- Simple: Add a new column
lia.db.createColumn("characters", "level", "INTEGER", 1):next(function(success)
if success then
print("Level column added")
else
print("Column already exists")
end
end)
Medium Complexity:
-- Medium: Add column with validation
local function addPlayerStatsColumn()
return lia.db.createColumn("players", "totalPlayTime", "FLOAT", 0):next(function(success)
if success then
lia.log.add("Added totalPlayTime column to players table")
hook.Run("OnColumnAdded", "players", "totalPlayTime")
else
lia.log.add("totalPlayTime column already exists")
end
end):catch(function(err)
lia.error("Failed to add column: " .. tostring(err))
end)
end
High Complexity:
-- High: Add column with validation and error handling
local function migrateCharacterTable()
local newColumns = {
{name = "level", type = "INTEGER", default = 1},
{name = "experience", type = "INTEGER", default = 0},
{name = "lastLevelUp", type = "DATETIME", default = "CURRENT_TIMESTAMP"}
}
local function addNextColumn(index)
if index > #newColumns then
lia.log.add("Character table migration completed")
return deferred.new():resolve()
end
local column = newColumns[index]
return lia.db.createColumn("characters", column.name, column.type, column.default):next(function(success)
if success then
lia.log.add("Added column: " .. column.name)
end
return addNextColumn(index + 1)
end):catch(function(err)
lia.error("Failed to add column " .. column.name .. ": " .. tostring(err))
return addNextColumn(index + 1)
end)
end
return addNextColumn(1)
end
removeTable
Purpose
Removes a database table and all its data from the database
When Called
When cleaning up unused tables, removing modules, or during database maintenance
Parameters
tableName(string): Table name without 'lia_' prefix
Returns
- Deferred promise object resolving to true on success, false if table doesn't exist
Realm
Server
Example Usage
Low Complexity:
-- Simple: Remove a table
lia.db.removeTable("old_data"):next(function(success)
if success then
print("Table removed")
else
print("Table doesn't exist")
end
end)
Medium Complexity:
-- Medium: Remove table with validation
local function cleanupOldModule(moduleName)
return lia.db.removeTable(moduleName .. "_data"):next(function(success)
if success then
lia.log.add("Removed table for module: " .. moduleName)
hook.Run("OnModuleTableRemoved", moduleName)
else
lia.log.add("Table for module " .. moduleName .. " doesn't exist")
end
end):catch(function(err)
lia.error("Failed to remove table: " .. tostring(err))
end)
end
High Complexity:
-- High: Remove table with backup and validation
local function removeTableWithBackup(tableName)
return lia.db.tableExists("lia_" .. tableName):next(function(exists)
if not exists then
lia.log.add("Table " .. tableName .. " doesn't exist")
return false
end
-- Create backup before removal
return lia.db.createSnapshot(tableName):next(function(snapshot)
lia.log.add("Created backup: " .. snapshot.file)
return lia.db.removeTable(tableName):next(function(success)
if success then
lia.log.add("Table " .. tableName .. " removed successfully")
hook.Run("OnTableRemoved", tableName, snapshot)
end
return success
end)
end):catch(function(err)
lia.error("Failed to backup table " .. tableName .. ": " .. tostring(err))
return false
end)
end)
end
removeColumn
Purpose
Removes a column from an existing database table using table recreation
When Called
When removing unused columns, cleaning up schemas, or during database migrations
Parameters
tableName(string): Table name without 'lia_' prefixcolumnName(string): Name of the column to remove
Returns
- Deferred promise object resolving to true on success, false if column doesn't exist
Realm
Server
Example Usage
Low Complexity:
-- Simple: Remove a column
lia.db.removeColumn("characters", "old_field"):next(function(success)
if success then
print("Column removed")
else
print("Column doesn't exist")
end
end)
Medium Complexity:
-- Medium: Remove column with validation
local function cleanupOldColumn(tableName, columnName)
return lia.db.removeColumn(tableName, columnName):next(function(success)
if success then
lia.log.add("Removed column " .. columnName .. " from " .. tableName)
hook.Run("OnColumnRemoved", tableName, columnName)
else
lia.log.add("Column " .. columnName .. " doesn't exist in " .. tableName)
end
end):catch(function(err)
lia.error("Failed to remove column: " .. tostring(err))
end)
end
High Complexity:
-- High: Remove column with backup and validation
local function removeColumnWithBackup(tableName, columnName)
return lia.db.tableExists("lia_" .. tableName):next(function(tableExists)
if not tableExists then
lia.error("Table " .. tableName .. " doesn't exist")
return false
end
return lia.db.fieldExists("lia_" .. tableName, columnName):next(function(columnExists)
if not columnExists then
lia.log.add("Column " .. columnName .. " doesn't exist")
return false
end
-- Create backup before removal
return lia.db.createSnapshot(tableName):next(function(snapshot)
lia.log.add("Created backup before column removal: " .. snapshot.file)
return lia.db.removeColumn(tableName, columnName):next(function(success)
if success then
lia.log.add("Column " .. columnName .. " removed from " .. tableName)
hook.Run("OnColumnRemoved", tableName, columnName, snapshot)
end
return success
end)
end):catch(function(err)
lia.error("Failed to backup table before column removal: " .. tostring(err))
return false
end)
end)
end)
end
getCharacterTable
Purpose
Retrieves the column information for the lia_characters table
When Called
When analyzing character table structure, generating reports, or during schema validation
Parameters
callback(function): Function to call with the column information array
Returns
- None
Realm
Server
Example Usage
Low Complexity:
-- Simple: Get character table columns
lia.db.getCharacterTable(function(columns)
print("Character table has " .. #columns .. " columns")
for _, column in ipairs(columns) do
print("- " .. column)
end
end)
Medium Complexity:
-- Medium: Get columns with analysis
local function analyzeCharacterTable()
lia.db.getCharacterTable(function(columns)
local requiredColumns = {"id", "steamID", "name", "model", "faction", "money"}
local missingColumns = {}
for _, required in ipairs(requiredColumns) do
if not table.HasValue(columns, required) then
table.insert(missingColumns, required)
end
end
if #missingColumns > 0 then
lia.log.add("Missing character columns: " .. table.concat(missingColumns, ", "))
else
lia.log.add("All required character columns present")
end
end)
end
High Complexity:
-- High: Get columns with validation and error handling
local function validateCharacterSchema()
return lia.db.waitForTablesToLoad():next(function()
lia.db.getCharacterTable(function(columns)
if not columns or #columns == 0 then
lia.error("Failed to get character table columns")
return
end
local schemaValidation = {
required = {"id", "steamID", "name", "model", "faction", "money"},
optional = {"desc", "attribs", "schema", "createTime", "lastJoinTime", "recognition", "fakenames"}
}
local validationResults = {
valid = true,
missing = {},
extra = {}
}
-- Check for missing required columns
for _, required in ipairs(schemaValidation.required) do
if not table.HasValue(columns, required) then
table.insert(validationResults.missing, required)
validationResults.valid = false
end
end
-- Check for extra columns
for _, column in ipairs(columns) do
if not table.HasValue(schemaValidation.required, column) and
not table.HasValue(schemaValidation.optional, column) then
table.insert(validationResults.extra, column)
end
end
if validationResults.valid then
lia.log.add("Character table schema validation passed")
else
lia.log.add("Character table schema issues found")
if #validationResults.missing > 0 then
lia.log.add("Missing columns: " .. table.concat(validationResults.missing, ", "))
end
if #validationResults.extra > 0 then
lia.log.add("Extra columns: " .. table.concat(validationResults.extra, ", "))
end
end
hook.Run("OnCharacterSchemaValidated", validationResults)
end)
end):catch(function(err)
lia.error("Character schema validation failed: " .. tostring(err))
end)
end
createSnapshot
Purpose
Creates a backup snapshot of a database table and saves it to a JSON file
When Called
When backing up data before major operations, creating restore points, or archiving data
Parameters
tableName(string): Table name without 'lia_' prefix
Returns
- Deferred promise object resolving to snapshot information (file, path, records)
Realm
Server
Example Usage
Low Complexity:
-- Simple: Create a snapshot
lia.db.createSnapshot("characters"):next(function(snapshot)
print("Snapshot created: " .. snapshot.file)
print("Records backed up: " .. snapshot.records)
end)
Medium Complexity:
-- Medium: Create snapshot with validation
local function backupTable(tableName)
return lia.db.createSnapshot(tableName):next(function(snapshot)
lia.log.add("Backup created: " .. snapshot.file .. " (" .. snapshot.records .. " records)")
hook.Run("OnTableBackedUp", tableName, snapshot)
return snapshot
end):catch(function(err)
lia.error("Failed to backup table " .. tableName .. ": " .. tostring(err))
end)
end
High Complexity:
-- High: Create snapshot with validation and error handling
local function createBackupWithValidation(tableName)
return lia.db.tableExists("lia_" .. tableName):next(function(exists)
if not exists then
return deferred.new():reject("Table " .. tableName .. " doesn't exist")
end
return lia.db.createSnapshot(tableName):next(function(snapshot)
-- Validate snapshot data
if snapshot.records == 0 then
lia.log.add("Snapshot created but table is empty")
end
-- Create backup metadata
local metadata = {
table = tableName,
timestamp = snapshot.timestamp,
records = snapshot.records,
file = snapshot.file,
path = snapshot.path,
server = GetHostName(),
version = lia.version or "unknown"
}
-- Save metadata
local metadataFile = "lilia/snapshots/" .. snapshot.file .. ".meta"
file.Write(metadataFile, util.TableToJSON(metadata, true))
lia.log.add("Backup completed: " .. snapshot.file .. " (" .. snapshot.records .. " records)")
hook.Run("OnBackupCreated", metadata)
return metadata
end):catch(function(err)
lia.error("Backup failed for " .. tableName .. ": " .. tostring(err))
return {success = false, error = err}
end)
end)
end
loadSnapshot
Purpose
Restores a database table from a previously created snapshot file
When Called
When restoring data from backups, recovering from errors, or migrating data
Parameters
fileName(string): Name of the snapshot file to load
Returns
- Deferred promise object resolving to restore information (table, records, timestamp)
Realm
Server
Example Usage
Low Complexity:
-- Simple: Load a snapshot
lia.db.loadSnapshot("snapshot_characters_1234567890.json"):next(function(result)
print("Restored " .. result.records .. " records to " .. result.table)
end)
Medium Complexity:
-- Medium: Load snapshot with validation
local function restoreTable(fileName)
return lia.db.loadSnapshot(fileName):next(function(result)
lia.log.add("Restored " .. result.records .. " records to " .. result.table)
hook.Run("OnTableRestored", result.table, result.records)
return result
end):catch(function(err)
lia.error("Failed to restore from " .. fileName .. ": " .. tostring(err))
end)
end
High Complexity:
-- High: Load snapshot with validation and error handling
local function restoreWithValidation(fileName)
return lia.db.loadSnapshot(fileName):next(function(result)
-- Validate restore results
if result.records == 0 then
lia.log.add("Restore completed but no records were loaded")
end
-- Verify table exists and has data
return lia.db.count(result.table):next(function(count)
if count ~= result.records then
lia.log.add("Record count mismatch: expected " .. result.records .. ", got " .. count)
end
-- Create restore log entry
local restoreLog = {
fileName = fileName,
table = result.table,
records = result.records,
timestamp = result.timestamp,
restoredAt = os.time(),
success = true
}
lia.log.add("Restore completed successfully: " .. fileName)
hook.Run("OnRestoreCompleted", restoreLog)
return restoreLog
end)
end):catch(function(err)
lia.error("Restore failed: " .. tostring(err))
-- Log failed restore attempt
local failedLog = {
fileName = fileName,
error = tostring(err),
failedAt = os.time(),
success = false
}
hook.Run("OnRestoreFailed", failedLog)
return failedLog
end)
end
lia.GM:RegisterPreparedStatements
Purpose
Restores a database table from a previously created snapshot file
When Called
When restoring data from backups, recovering from errors, or migrating data
Parameters
fileName(string): Name of the snapshot file to load
Returns
- Deferred promise object resolving to restore information (table, records, timestamp)
Realm
Server
Example Usage
Low Complexity:
-- Simple: Load a snapshot
lia.db.loadSnapshot("snapshot_characters_1234567890.json"):next(function(result)
print("Restored " .. result.records .. " records to " .. result.table)
end)
Medium Complexity:
-- Medium: Load snapshot with validation
local function restoreTable(fileName)
return lia.db.loadSnapshot(fileName):next(function(result)
lia.log.add("Restored " .. result.records .. " records to " .. result.table)
hook.Run("OnTableRestored", result.table, result.records)
return result
end):catch(function(err)
lia.error("Failed to restore from " .. fileName .. ": " .. tostring(err))
end)
end
High Complexity:
-- High: Load snapshot with validation and error handling
local function restoreWithValidation(fileName)
return lia.db.loadSnapshot(fileName):next(function(result)
-- Validate restore results
if result.records == 0 then
lia.log.add("Restore completed but no records were loaded")
end
-- Verify table exists and has data
return lia.db.count(result.table):next(function(count)
if count ~= result.records then
lia.log.add("Record count mismatch: expected " .. result.records .. ", got " .. count)
end
-- Create restore log entry
local restoreLog = {
fileName = fileName,
table = result.table,
records = result.records,
timestamp = result.timestamp,
restoredAt = os.time(),
success = true
}
lia.log.add("Restore completed successfully: " .. fileName)
hook.Run("OnRestoreCompleted", restoreLog)
return restoreLog
end)
end):catch(function(err)
lia.error("Restore failed: " .. tostring(err))
-- Log failed restore attempt
local failedLog = {
fileName = fileName,
error = tostring(err),
failedAt = os.time(),
success = false
}
hook.Run("OnRestoreFailed", failedLog)
return failedLog
end)
end
lia.GM:SetupDatabase
Purpose
Restores a database table from a previously created snapshot file
When Called
When restoring data from backups, recovering from errors, or migrating data
Parameters
fileName(string): Name of the snapshot file to load
Returns
- Deferred promise object resolving to restore information (table, records, timestamp)
Realm
Server
Example Usage
Low Complexity:
-- Simple: Load a snapshot
lia.db.loadSnapshot("snapshot_characters_1234567890.json"):next(function(result)
print("Restored " .. result.records .. " records to " .. result.table)
end)
Medium Complexity:
-- Medium: Load snapshot with validation
local function restoreTable(fileName)
return lia.db.loadSnapshot(fileName):next(function(result)
lia.log.add("Restored " .. result.records .. " records to " .. result.table)
hook.Run("OnTableRestored", result.table, result.records)
return result
end):catch(function(err)
lia.error("Failed to restore from " .. fileName .. ": " .. tostring(err))
end)
end
High Complexity:
-- High: Load snapshot with validation and error handling
local function restoreWithValidation(fileName)
return lia.db.loadSnapshot(fileName):next(function(result)
-- Validate restore results
if result.records == 0 then
lia.log.add("Restore completed but no records were loaded")
end
-- Verify table exists and has data
return lia.db.count(result.table):next(function(count)
if count ~= result.records then
lia.log.add("Record count mismatch: expected " .. result.records .. ", got " .. count)
end
-- Create restore log entry
local restoreLog = {
fileName = fileName,
table = result.table,
records = result.records,
timestamp = result.timestamp,
restoredAt = os.time(),
success = true
}
lia.log.add("Restore completed successfully: " .. fileName)
hook.Run("OnRestoreCompleted", restoreLog)
return restoreLog
end)
end):catch(function(err)
lia.error("Restore failed: " .. tostring(err))
-- Log failed restore attempt
local failedLog = {
fileName = fileName,
error = tostring(err),
failedAt = os.time(),
success = false
}
hook.Run("OnRestoreFailed", failedLog)
return failedLog
end)
end
lia.GM:DatabaseConnected
Purpose
Restores a database table from a previously created snapshot file
When Called
When restoring data from backups, recovering from errors, or migrating data
Parameters
fileName(string): Name of the snapshot file to load
Returns
- Deferred promise object resolving to restore information (table, records, timestamp)
Realm
Server
Example Usage
Low Complexity:
-- Simple: Load a snapshot
lia.db.loadSnapshot("snapshot_characters_1234567890.json"):next(function(result)
print("Restored " .. result.records .. " records to " .. result.table)
end)
Medium Complexity:
-- Medium: Load snapshot with validation
local function restoreTable(fileName)
return lia.db.loadSnapshot(fileName):next(function(result)
lia.log.add("Restored " .. result.records .. " records to " .. result.table)
hook.Run("OnTableRestored", result.table, result.records)
return result
end):catch(function(err)
lia.error("Failed to restore from " .. fileName .. ": " .. tostring(err))
end)
end
High Complexity:
-- High: Load snapshot with validation and error handling
local function restoreWithValidation(fileName)
return lia.db.loadSnapshot(fileName):next(function(result)
-- Validate restore results
if result.records == 0 then
lia.log.add("Restore completed but no records were loaded")
end
-- Verify table exists and has data
return lia.db.count(result.table):next(function(count)
if count ~= result.records then
lia.log.add("Record count mismatch: expected " .. result.records .. ", got " .. count)
end
-- Create restore log entry
local restoreLog = {
fileName = fileName,
table = result.table,
records = result.records,
timestamp = result.timestamp,
restoredAt = os.time(),
success = true
}
lia.log.add("Restore completed successfully: " .. fileName)
hook.Run("OnRestoreCompleted", restoreLog)
return restoreLog
end)
end):catch(function(err)
lia.error("Restore failed: " .. tostring(err))
-- Log failed restore attempt
local failedLog = {
fileName = fileName,
error = tostring(err),
failedAt = os.time(),
success = false
}
hook.Run("OnRestoreFailed", failedLog)
return failedLog
end)
end