From ba62a415a6e9f819b852925e005e99e04a7f63db Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Wed, 11 Dec 2024 00:38:22 -0300 Subject: [PATCH] improve: migration database update (#3071) This improves the database migration process by removing the need to manually define if more migrations are required with return values in Lua scripts. The new approach automatically processes all migration files based on their version, reducing complexity and making the update process more robust. This change aims to streamline the database update logic and eliminate manual steps previously required. --- data-canary/migrations/0.lua | 3 - data-canary/migrations/1.lua | 5 -- data-canary/migrations/README.md | 45 +++++++++++++ data-otservbr-global/migrations/0.lua | 14 ---- data-otservbr-global/migrations/1.lua | 35 +++------- data-otservbr-global/migrations/10.lua | 1 - data-otservbr-global/migrations/11.lua | 1 - data-otservbr-global/migrations/12.lua | 1 - data-otservbr-global/migrations/13.lua | 1 - data-otservbr-global/migrations/14.lua | 1 - data-otservbr-global/migrations/15.lua | 1 - data-otservbr-global/migrations/16.lua | 1 - data-otservbr-global/migrations/17.lua | 1 - data-otservbr-global/migrations/18.lua | 2 - data-otservbr-global/migrations/19.lua | 2 - data-otservbr-global/migrations/2.lua | 2 - data-otservbr-global/migrations/20.lua | 1 - data-otservbr-global/migrations/21.lua | 1 - data-otservbr-global/migrations/22.lua | 1 - data-otservbr-global/migrations/23.lua | 1 - data-otservbr-global/migrations/24.lua | 1 - data-otservbr-global/migrations/25.lua | 1 - data-otservbr-global/migrations/26.lua | 1 - data-otservbr-global/migrations/27.lua | 1 - data-otservbr-global/migrations/28.lua | 1 - data-otservbr-global/migrations/29.lua | 1 - data-otservbr-global/migrations/3.lua | 1 - data-otservbr-global/migrations/30.lua | 1 - data-otservbr-global/migrations/31.lua | 1 - data-otservbr-global/migrations/32.lua | 1 - data-otservbr-global/migrations/33.lua | 1 - data-otservbr-global/migrations/34.lua | 1 - data-otservbr-global/migrations/35.lua | 1 - data-otservbr-global/migrations/36.lua | 1 - data-otservbr-global/migrations/37.lua | 1 - data-otservbr-global/migrations/38.lua | 1 - data-otservbr-global/migrations/39.lua | 1 - data-otservbr-global/migrations/4.lua | 1 - data-otservbr-global/migrations/40.lua | 2 - data-otservbr-global/migrations/41.lua | 2 - data-otservbr-global/migrations/42.lua | 2 - data-otservbr-global/migrations/43.lua | 2 - data-otservbr-global/migrations/44.lua | 2 - data-otservbr-global/migrations/45.lua | 2 - data-otservbr-global/migrations/46.lua | 2 - data-otservbr-global/migrations/47.lua | 23 ++++++- data-otservbr-global/migrations/5.lua | 1 - data-otservbr-global/migrations/6.lua | 1 - data-otservbr-global/migrations/7.lua | 1 - data-otservbr-global/migrations/8.lua | 1 - data-otservbr-global/migrations/9.lua | 1 - data-otservbr-global/migrations/README.md | 45 +++++++++++++ src/database/databasemanager.cpp | 81 +++++++++++++++-------- 53 files changed, 177 insertions(+), 129 deletions(-) delete mode 100644 data-canary/migrations/0.lua delete mode 100644 data-canary/migrations/1.lua create mode 100644 data-canary/migrations/README.md delete mode 100644 data-otservbr-global/migrations/0.lua create mode 100644 data-otservbr-global/migrations/README.md diff --git a/data-canary/migrations/0.lua b/data-canary/migrations/0.lua deleted file mode 100644 index d0ffd9c0cb3..00000000000 --- a/data-canary/migrations/0.lua +++ /dev/null @@ -1,3 +0,0 @@ -function onUpdateDatabase() - return false -end diff --git a/data-canary/migrations/1.lua b/data-canary/migrations/1.lua deleted file mode 100644 index 332f1838723..00000000000 --- a/data-canary/migrations/1.lua +++ /dev/null @@ -1,5 +0,0 @@ --- return true = There are others migrations file --- return false = This is the last migration file -function onUpdateDatabase() - return false -end diff --git a/data-canary/migrations/README.md b/data-canary/migrations/README.md new file mode 100644 index 00000000000..b23473bf29d --- /dev/null +++ b/data-canary/migrations/README.md @@ -0,0 +1,45 @@ +# Database Migration System + +This document provides an overview of the current database migration system for the project. The migration process has been streamlined to ensure that all migration scripts are automatically applied in order, making it easier to maintain database updates. + +## How It Works + +The migration system is designed to apply updates to the database schema or data whenever a new server version is started. Migration scripts are stored in the `migrations` directory, and the system will automatically apply any scripts that have not yet been executed. + +### Steps Involved + +1. **Retrieve Current Database Version**: + - The system first retrieves the current version of the database using `getDatabaseVersion()`. + - This version is used to determine which migration scripts need to be executed. + +2. **Migration Files Directory**: + - All migration scripts are stored in the `migrations` directory. + - Each migration script is named using a numerical pattern, such as `1.lua`, `2.lua`, etc. + - The naming convention helps determine the order in which scripts should be applied. + +3. **Execute Migration Scripts**: + - The migration system iterates through the migration directory and applies each migration script that has a version greater than the current database version. + - Only scripts that have not been applied are executed. + - The Lua state (`lua_State* L`) is initialized to run each script. + +4. **Update Database Version**: + - After each migration script is successfully applied, the system updates the database version to reflect the applied change. + - This ensures that the script is not re-applied on subsequent server startups. + +## Example Migration Script + +Below is an example of what a migration script might look like. Note that no return value is required, as all migration files are applied based on the current database version. + +```lua +-- Migration script example (for documentation purposes only) +-- This migration script should include all necessary SQL commands or operations to apply a specific update to the database. + +-- Example: Adding a new column to the "players" table +local query = [[ + ALTER TABLE players ADD COLUMN new_feature_flag TINYINT(1) NOT NULL DEFAULT 0; +]] + +-- Execute the query +db.execute(query) -- This function executes the given SQL query on the database. + +-- Note: Ensure that queries are validated to avoid errors during the migration process. diff --git a/data-otservbr-global/migrations/0.lua b/data-otservbr-global/migrations/0.lua deleted file mode 100644 index b40962e7c1f..00000000000 --- a/data-otservbr-global/migrations/0.lua +++ /dev/null @@ -1,14 +0,0 @@ -function onUpdateDatabase() - logger.info("Updating database to version 1 (sample players)") - -- Rook Sample - db.query("UPDATE `players` SET `level` = 2, `vocation` = 0, `health` = 155, `healthmax` = 155, `experience` = 100, `soul` = 100, `lookbody` = 113, `lookfeet` = 115, `lookhead` = 95, `looklegs` = 39, `looktype` = 129, `mana` = 60, `manamax` = 60, `town_id` = 1, `cap` = 410 WHERE `id` = 1;") - -- Sorcerer Sample - db.query("UPDATE `players` SET `level` = 8, `vocation` = 1, `health` = 185, `healthmax` = 185, `experience` = 4200, `soul` = 100, `lookbody` = 113, `lookfeet` = 115, `lookhead` = 95, `looklegs` = 39, `looktype` = 129, `mana` = 90, `manamax` = 90, `town_id` = 8, `cap` = 470 WHERE `id` = 2;") - -- Druid Sample - db.query("UPDATE `players` SET `level` = 8, `vocation` = 2, `health` = 185, `healthmax` = 185, `experience` = 4200, `soul` = 100, `lookbody` = 113, `lookfeet` = 115, `lookhead` = 95, `looklegs` = 39, `looktype` = 129, `mana` = 90, `manamax` = 90, `town_id` = 8, `cap` = 470 WHERE `id` = 3;") - -- Paladin Sample - db.query("UPDATE `players` SET `level` = 8, `vocation` = 3, `health` = 185, `healthmax` = 185, `experience` = 4200, `soul` = 100, `lookbody` = 113, `lookfeet` = 115, `lookhead` = 95, `looklegs` = 39, `looktype` = 129, `mana` = 90, `manamax` = 90, `town_id` = 8, `cap` = 470 WHERE `id` = 4;") - -- Knight Sample - db.query("UPDATE `players` SET `level` = 8, `vocation` = 4, `health` = 185, `healthmax` = 185, `experience` = 4200, `soul` = 100, `lookbody` = 113, `lookfeet` = 115, `lookhead` = 95, `looklegs` = 39, `looktype` = 129, `mana` = 90, `manamax` = 90, `town_id` = 8, `cap` = 470 WHERE `id` = 5;") - return true -end diff --git a/data-otservbr-global/migrations/1.lua b/data-otservbr-global/migrations/1.lua index 180a8b2ce90..1c5888f52d7 100644 --- a/data-otservbr-global/migrations/1.lua +++ b/data-otservbr-global/migrations/1.lua @@ -1,26 +1,13 @@ function onUpdateDatabase() - logger.info("Updating database to version 2 (hireling)") - - db.query([[ - CREATE TABLE IF NOT EXISTS `player_hirelings` ( - `id` INT NOT NULL PRIMARY KEY auto_increment, - `player_id` INT NOT NULL, - `name` varchar(255), - `active` tinyint unsigned NOT NULL DEFAULT '0', - `sex` tinyint unsigned NOT NULL DEFAULT '0', - `posx` int(11) NOT NULL DEFAULT '0', - `posy` int(11) NOT NULL DEFAULT '0', - `posz` int(11) NOT NULL DEFAULT '0', - `lookbody` int(11) NOT NULL DEFAULT '0', - `lookfeet` int(11) NOT NULL DEFAULT '0', - `lookhead` int(11) NOT NULL DEFAULT '0', - `looklegs` int(11) NOT NULL DEFAULT '0', - `looktype` int(11) NOT NULL DEFAULT '136', - - FOREIGN KEY(`player_id`) REFERENCES `players`(`id`) - ON DELETE CASCADE - ) - ]]) - - return true + logger.info("Updating database to version 1 (sample players)") + -- Rook Sample + db.query("UPDATE `players` SET `level` = 2, `vocation` = 0, `health` = 155, `healthmax` = 155, `experience` = 100, `soul` = 100, `lookbody` = 113, `lookfeet` = 115, `lookhead` = 95, `looklegs` = 39, `looktype` = 129, `mana` = 60, `manamax` = 60, `town_id` = 1, `cap` = 410 WHERE `id` = 1;") + -- Sorcerer Sample + db.query("UPDATE `players` SET `level` = 8, `vocation` = 1, `health` = 185, `healthmax` = 185, `experience` = 4200, `soul` = 100, `lookbody` = 113, `lookfeet` = 115, `lookhead` = 95, `looklegs` = 39, `looktype` = 129, `mana` = 90, `manamax` = 90, `town_id` = 8, `cap` = 470 WHERE `id` = 2;") + -- Druid Sample + db.query("UPDATE `players` SET `level` = 8, `vocation` = 2, `health` = 185, `healthmax` = 185, `experience` = 4200, `soul` = 100, `lookbody` = 113, `lookfeet` = 115, `lookhead` = 95, `looklegs` = 39, `looktype` = 129, `mana` = 90, `manamax` = 90, `town_id` = 8, `cap` = 470 WHERE `id` = 3;") + -- Paladin Sample + db.query("UPDATE `players` SET `level` = 8, `vocation` = 3, `health` = 185, `healthmax` = 185, `experience` = 4200, `soul` = 100, `lookbody` = 113, `lookfeet` = 115, `lookhead` = 95, `looklegs` = 39, `looktype` = 129, `mana` = 90, `manamax` = 90, `town_id` = 8, `cap` = 470 WHERE `id` = 4;") + -- Knight Sample + db.query("UPDATE `players` SET `level` = 8, `vocation` = 4, `health` = 185, `healthmax` = 185, `experience` = 4200, `soul` = 100, `lookbody` = 113, `lookfeet` = 115, `lookhead` = 95, `looklegs` = 39, `looktype` = 129, `mana` = 90, `manamax` = 90, `town_id` = 8, `cap` = 470 WHERE `id` = 5;") end diff --git a/data-otservbr-global/migrations/10.lua b/data-otservbr-global/migrations/10.lua index 0285bb0fee6..9dfded3813d 100644 --- a/data-otservbr-global/migrations/10.lua +++ b/data-otservbr-global/migrations/10.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 11 (Guilds Balance)") db.query("ALTER TABLE `guilds` ADD `balance` bigint(20) UNSIGNED NOT NULL DEFAULT '0';") - return true end diff --git a/data-otservbr-global/migrations/11.lua b/data-otservbr-global/migrations/11.lua index 7f448f94a9d..08d40b66381 100644 --- a/data-otservbr-global/migrations/11.lua +++ b/data-otservbr-global/migrations/11.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 12 (Player get daily reward)") db.query("ALTER TABLE `players` ADD `isreward` tinyint(1) NOT NULL DEFAULT 1") - return true end diff --git a/data-otservbr-global/migrations/12.lua b/data-otservbr-global/migrations/12.lua index 0c6e27bb275..e83ca4e51f8 100644 --- a/data-otservbr-global/migrations/12.lua +++ b/data-otservbr-global/migrations/12.lua @@ -7,5 +7,4 @@ function onUpdateDatabase() db.query("ALTER TABLE boosted_creature ADD `lookbody` int(11) NOT NULL DEFAULT 0;") db.query("ALTER TABLE boosted_creature ADD `lookaddons` int(11) NOT NULL DEFAULT 0;") db.query("ALTER TABLE boosted_creature ADD `lookmount` int(11) DEFAULT 0;") - return true end diff --git a/data-otservbr-global/migrations/13.lua b/data-otservbr-global/migrations/13.lua index 5918b6cbd58..479b28eda79 100644 --- a/data-otservbr-global/migrations/13.lua +++ b/data-otservbr-global/migrations/13.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 14 (Fixed mana spent)") db.query("ALTER TABLE `players` CHANGE `manaspent` `manaspent` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0';") - return true end diff --git a/data-otservbr-global/migrations/14.lua b/data-otservbr-global/migrations/14.lua index d2a1faf273b..7c23d8053b5 100644 --- a/data-otservbr-global/migrations/14.lua +++ b/data-otservbr-global/migrations/14.lua @@ -2,5 +2,4 @@ function onUpdateDatabase() logger.info("Updating database to version 15 (Magic Shield Spell)") db.query("ALTER TABLE `players` ADD `manashield` SMALLINT UNSIGNED NOT NULL DEFAULT '0' AFTER `skill_manaleech_amount`") db.query("ALTER TABLE `players` ADD `max_manashield` SMALLINT UNSIGNED NOT NULL DEFAULT '0' AFTER `manashield`") - return true end diff --git a/data-otservbr-global/migrations/15.lua b/data-otservbr-global/migrations/15.lua index 1521e96101f..73daf3c5b31 100644 --- a/data-otservbr-global/migrations/15.lua +++ b/data-otservbr-global/migrations/15.lua @@ -4,5 +4,4 @@ function onUpdateDatabase() db.query("UPDATE `players` SET `maglevel` = 2, `manaspent` = 5936, `skill_club` = 12, `skill_club_tries` = 155, `skill_sword` = 12, `skill_sword_tries` = 155, `skill_axe` = 12, `skill_axe_tries` = 155, `skill_dist` = 12, `skill_dist_tries` = 93 WHERE `id` = 1;") -- GOD db.query("UPDATE `players` SET `health` = 155, `healthmax` = 155, `experience` = 100, `looktype` = 75, `town_id` = 8 WHERE `id` = 6;") - return true end diff --git a/data-otservbr-global/migrations/16.lua b/data-otservbr-global/migrations/16.lua index c9ca340f0b3..a5766130bc3 100644 --- a/data-otservbr-global/migrations/16.lua +++ b/data-otservbr-global/migrations/16.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() print("Updating database to version 17 (Tutorial support)") db.query("ALTER TABLE `players` ADD `istutorial` SMALLINT(1) NOT NULL DEFAULT '0'") - return true -- true = There are others migrations file | false = this is the last migration file end diff --git a/data-otservbr-global/migrations/17.lua b/data-otservbr-global/migrations/17.lua index d25e4ccd5a9..9d5f0d8d624 100644 --- a/data-otservbr-global/migrations/17.lua +++ b/data-otservbr-global/migrations/17.lua @@ -2,5 +2,4 @@ function onUpdateDatabase() logger.info("Updating database to version 18 (Fix guild creation myaac)") db.query("ALTER TABLE `guilds` ADD `level` int(11) NOT NULL DEFAULT 1") db.query("ALTER TABLE `guilds` ADD `points` int(11) NOT NULL DEFAULT 0") - return true end diff --git a/data-otservbr-global/migrations/18.lua b/data-otservbr-global/migrations/18.lua index 01ef6048033..e017b86e05b 100644 --- a/data-otservbr-global/migrations/18.lua +++ b/data-otservbr-global/migrations/18.lua @@ -48,6 +48,4 @@ function onUpdateDatabase() `monster_list` BLOB NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ]]) - - return true end diff --git a/data-otservbr-global/migrations/19.lua b/data-otservbr-global/migrations/19.lua index 382273dfef1..e7d27a859ef 100644 --- a/data-otservbr-global/migrations/19.lua +++ b/data-otservbr-global/migrations/19.lua @@ -4,6 +4,4 @@ function onUpdateDatabase() db.query("ALTER TABLE `accounts` ADD `tournament_coins` int(11) NOT NULL DEFAULT 0 AFTER `coins`") db.query("ALTER TABLE `store_history` ADD `coin_type` tinyint(1) NOT NULL DEFAULT 0 AFTER `description`") db.query("ALTER TABLE `store_history` DROP COLUMN `coins`") -- Not in use anywhere. - - return true end diff --git a/data-otservbr-global/migrations/2.lua b/data-otservbr-global/migrations/2.lua index e953d579a3e..72c797b4b0e 100644 --- a/data-otservbr-global/migrations/2.lua +++ b/data-otservbr-global/migrations/2.lua @@ -109,6 +109,4 @@ function onUpdateDatabase() ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ]]) - - return true end diff --git a/data-otservbr-global/migrations/20.lua b/data-otservbr-global/migrations/20.lua index 49bc9ecd56f..daaefc6f041 100644 --- a/data-otservbr-global/migrations/20.lua +++ b/data-otservbr-global/migrations/20.lua @@ -2,5 +2,4 @@ function onUpdateDatabase() logger.info("Updating database to version 21 (Fix market price size)") db.query("ALTER TABLE `market_history` CHANGE `price` `price` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0';") db.query("ALTER TABLE `market_offers` CHANGE `price` `price` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0';") - return true end diff --git a/data-otservbr-global/migrations/21.lua b/data-otservbr-global/migrations/21.lua index a2e945576f7..cec635ed937 100644 --- a/data-otservbr-global/migrations/21.lua +++ b/data-otservbr-global/migrations/21.lua @@ -4,5 +4,4 @@ function onUpdateDatabase() db.query("ALTER TABLE `market_history` ADD `tier` tinyint UNSIGNED NOT NULL DEFAULT '0';") db.query("ALTER TABLE `players` ADD `forge_dusts` bigint(21) NOT NULL DEFAULT '0';") db.query("ALTER TABLE `players` ADD `forge_dust_level` bigint(21) UNSIGNED NOT NULL DEFAULT '100';") - return true end diff --git a/data-otservbr-global/migrations/22.lua b/data-otservbr-global/migrations/22.lua index ee1caf87ac3..c4c5bd385bc 100644 --- a/data-otservbr-global/migrations/22.lua +++ b/data-otservbr-global/migrations/22.lua @@ -4,5 +4,4 @@ function onUpdateDatabase() ALTER TABLE `players` MODIFY offlinetraining_skill tinyint(2) NOT NULL DEFAULT '-1'; ]]) - return true end diff --git a/data-otservbr-global/migrations/23.lua b/data-otservbr-global/migrations/23.lua index da05835f759..8edac8cef47 100644 --- a/data-otservbr-global/migrations/23.lua +++ b/data-otservbr-global/migrations/23.lua @@ -16,5 +16,4 @@ function onUpdateDatabase() FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ]]) - return true end diff --git a/data-otservbr-global/migrations/24.lua b/data-otservbr-global/migrations/24.lua index c3cc1563b56..fed9f189085 100644 --- a/data-otservbr-global/migrations/24.lua +++ b/data-otservbr-global/migrations/24.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 25 (random mount outfit window)") db.query("ALTER TABLE `players` ADD `randomize_mount` SMALLINT(1) NOT NULL DEFAULT '0'") - return true end diff --git a/data-otservbr-global/migrations/25.lua b/data-otservbr-global/migrations/25.lua index e486b9ddf76..4d229bb58e5 100644 --- a/data-otservbr-global/migrations/25.lua +++ b/data-otservbr-global/migrations/25.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 26 (reward bag fix)") db.query("UPDATE player_rewards SET pid = 0 WHERE itemtype = 19202;") - return true end diff --git a/data-otservbr-global/migrations/26.lua b/data-otservbr-global/migrations/26.lua index bbac31b8170..ddf821ca5cd 100644 --- a/data-otservbr-global/migrations/26.lua +++ b/data-otservbr-global/migrations/26.lua @@ -11,5 +11,4 @@ function onUpdateDatabase() PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`)) ]]) - return true end diff --git a/data-otservbr-global/migrations/27.lua b/data-otservbr-global/migrations/27.lua index b16b589da87..73e7bf5c4f7 100644 --- a/data-otservbr-global/migrations/27.lua +++ b/data-otservbr-global/migrations/27.lua @@ -23,5 +23,4 @@ function onUpdateDatabase() `bossIdSlotTwo` int NOT NULL DEFAULT 0, `removeTimes` int NOT NULL DEFAULT 1 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;]]) - return true end diff --git a/data-otservbr-global/migrations/28.lua b/data-otservbr-global/migrations/28.lua index 2bd44799cfc..d7575edf3c8 100644 --- a/data-otservbr-global/migrations/28.lua +++ b/data-otservbr-global/migrations/28.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 29 (transfer coins)") db.query("ALTER TABLE `accounts` ADD `coins_transferable` int unsigned NOT NULL DEFAULT '0';") - return true end diff --git a/data-otservbr-global/migrations/29.lua b/data-otservbr-global/migrations/29.lua index 1b490d324c2..0c633e46b5d 100644 --- a/data-otservbr-global/migrations/29.lua +++ b/data-otservbr-global/migrations/29.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 30 (looktypeEx)") db.query("ALTER TABLE `boosted_boss` ADD `looktypeEx` int unsigned NOT NULL DEFAULT '0';") - return true end diff --git a/data-otservbr-global/migrations/3.lua b/data-otservbr-global/migrations/3.lua index 72fc0d41cd8..ae06343be07 100644 --- a/data-otservbr-global/migrations/3.lua +++ b/data-otservbr-global/migrations/3.lua @@ -5,5 +5,4 @@ function onUpdateDatabase() ALTER TABLE `prey_slots` ADD `tick` smallint(3) NOT NULL DEFAULT '0'; ]]) - return true end diff --git a/data-otservbr-global/migrations/30.lua b/data-otservbr-global/migrations/30.lua index f724284e258..4ee1632421d 100644 --- a/data-otservbr-global/migrations/30.lua +++ b/data-otservbr-global/migrations/30.lua @@ -3,5 +3,4 @@ function onUpdateDatabase() db.query([[ ALTER TABLE `accounts` ADD COLUMN `premdays_purchased` int(11) NOT NULL DEFAULT 0; ]]) - return true end diff --git a/data-otservbr-global/migrations/31.lua b/data-otservbr-global/migrations/31.lua index 4207776b90e..5ba21bbe561 100644 --- a/data-otservbr-global/migrations/31.lua +++ b/data-otservbr-global/migrations/31.lua @@ -13,5 +13,4 @@ function onUpdateDatabase() db.query([[ ALTER TABLE `accounts` MODIFY `password` TEXT NOT NULL; ]]) - return true end diff --git a/data-otservbr-global/migrations/32.lua b/data-otservbr-global/migrations/32.lua index 102a9aafd9f..078ef407da6 100644 --- a/data-otservbr-global/migrations/32.lua +++ b/data-otservbr-global/migrations/32.lua @@ -10,5 +10,4 @@ function onUpdateDatabase() ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ]]) - return true end diff --git a/data-otservbr-global/migrations/33.lua b/data-otservbr-global/migrations/33.lua index afac0cebdfc..2c77cbb6e24 100644 --- a/data-otservbr-global/migrations/33.lua +++ b/data-otservbr-global/migrations/33.lua @@ -24,5 +24,4 @@ function onUpdateDatabase() ALTER TABLE `player_wheeldata` ADD PRIMARY KEY (`player_id`); ]]) - return true end diff --git a/data-otservbr-global/migrations/34.lua b/data-otservbr-global/migrations/34.lua index 7f0a289f656..7537f6e6582 100644 --- a/data-otservbr-global/migrations/34.lua +++ b/data-otservbr-global/migrations/34.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 35 (bosstiary tracker)") db.query("ALTER TABLE `player_bosstiary` ADD `tracker` blob NOT NULL;") - return true end diff --git a/data-otservbr-global/migrations/35.lua b/data-otservbr-global/migrations/35.lua index 10bddc47138..70c820c32fd 100644 --- a/data-otservbr-global/migrations/35.lua +++ b/data-otservbr-global/migrations/35.lua @@ -12,7 +12,6 @@ function onUpdateDatabase() until not Result.next(resultQuery) Result.free(resultQuery) end - return true end function getNewValue(premDays, lastDay) diff --git a/data-otservbr-global/migrations/36.lua b/data-otservbr-global/migrations/36.lua index 7d35e223cf9..5f912763cc8 100644 --- a/data-otservbr-global/migrations/36.lua +++ b/data-otservbr-global/migrations/36.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 37 (add coin_type to accounts)") db.query("ALTER TABLE `coins_transactions` ADD `coin_type` tinyint(1) UNSIGNED NOT NULL DEFAULT '1';") - return true end diff --git a/data-otservbr-global/migrations/37.lua b/data-otservbr-global/migrations/37.lua index 70f2ec126ce..ae3dbefbc27 100644 --- a/data-otservbr-global/migrations/37.lua +++ b/data-otservbr-global/migrations/37.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 38 (add pronoun to players)") db.query("ALTER TABLE `players` ADD `pronoun` int(11) NOT NULL DEFAULT '0';") - return true end diff --git a/data-otservbr-global/migrations/38.lua b/data-otservbr-global/migrations/38.lua index 7981d5d7063..3412e4d488f 100644 --- a/data-otservbr-global/migrations/38.lua +++ b/data-otservbr-global/migrations/38.lua @@ -8,5 +8,4 @@ function onUpdateDatabase() PRIMARY KEY (`key_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ]]) - return true end diff --git a/data-otservbr-global/migrations/39.lua b/data-otservbr-global/migrations/39.lua index 2bf3815016f..181994882db 100644 --- a/data-otservbr-global/migrations/39.lua +++ b/data-otservbr-global/migrations/39.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 40 (house transfer ownership on startup)") db.query("ALTER TABLE `houses` ADD `new_owner` int(11) NOT NULL DEFAULT '-1';") - return true end diff --git a/data-otservbr-global/migrations/4.lua b/data-otservbr-global/migrations/4.lua index fa07383aeaa..891bc20915a 100644 --- a/data-otservbr-global/migrations/4.lua +++ b/data-otservbr-global/migrations/4.lua @@ -6,5 +6,4 @@ function onUpdateDatabase() `raceid` varchar(250) NOT NULL DEFAULT '', PRIMARY KEY (`date`) ) AS SELECT 0 AS date, "default" AS boostname, 0 AS raceid]]) - return true end diff --git a/data-otservbr-global/migrations/40.lua b/data-otservbr-global/migrations/40.lua index 22bfea0da95..be8794e7b25 100644 --- a/data-otservbr-global/migrations/40.lua +++ b/data-otservbr-global/migrations/40.lua @@ -12,6 +12,4 @@ function onUpdateDatabase() ALTER TABLE `house_lists` MODIFY `version` bigint(20) NOT NULL DEFAULT '0'; ]]) - - return true end diff --git a/data-otservbr-global/migrations/41.lua b/data-otservbr-global/migrations/41.lua index 15eb1d88e99..1fa9a40e36d 100644 --- a/data-otservbr-global/migrations/41.lua +++ b/data-otservbr-global/migrations/41.lua @@ -6,6 +6,4 @@ function onUpdateDatabase() MODIFY `xpboost_stamina` smallint(5) UNSIGNED DEFAULT NULL, MODIFY `xpboost_value` tinyint(4) UNSIGNED DEFAULT NULL ]]) - - return true end diff --git a/data-otservbr-global/migrations/42.lua b/data-otservbr-global/migrations/42.lua index 4d07b663daa..4b0b97b9987 100644 --- a/data-otservbr-global/migrations/42.lua +++ b/data-otservbr-global/migrations/42.lua @@ -5,6 +5,4 @@ function onUpdateDatabase() ALTER TABLE `guildwar_kills` DROP INDEX `guildwar_kills_unique` ]]) - - return true end diff --git a/data-otservbr-global/migrations/43.lua b/data-otservbr-global/migrations/43.lua index 6d3492a815a..438ba91b713 100644 --- a/data-otservbr-global/migrations/43.lua +++ b/data-otservbr-global/migrations/43.lua @@ -7,6 +7,4 @@ function onUpdateDatabase() ADD `payment` bigint(13) UNSIGNED NOT NULL DEFAULT '0', ADD `duration_days` tinyint(3) UNSIGNED NOT NULL DEFAULT '0' ]]) - - return true end diff --git a/data-otservbr-global/migrations/44.lua b/data-otservbr-global/migrations/44.lua index c551fc79aeb..0e2140c3183 100644 --- a/data-otservbr-global/migrations/44.lua +++ b/data-otservbr-global/migrations/44.lua @@ -6,6 +6,4 @@ function onUpdateDatabase() MODIFY COLUMN `manashield` INT UNSIGNED NOT NULL DEFAULT '0', MODIFY COLUMN `max_manashield` INT UNSIGNED NOT NULL DEFAULT '0'; ]]) - - return true end diff --git a/data-otservbr-global/migrations/45.lua b/data-otservbr-global/migrations/45.lua index 4ceb5f7e3fd..a88de886861 100644 --- a/data-otservbr-global/migrations/45.lua +++ b/data-otservbr-global/migrations/45.lua @@ -51,6 +51,4 @@ function onUpdateDatabase() INSERT INTO `account_vipgroups` (`id`, `account_id`, `name`, `customizable`) SELECT 3, id, 'Trading Partners', 0 FROM `accounts`; ]]) - - return true end diff --git a/data-otservbr-global/migrations/46.lua b/data-otservbr-global/migrations/46.lua index 506da3a132b..da4ade8cbf3 100644 --- a/data-otservbr-global/migrations/46.lua +++ b/data-otservbr-global/migrations/46.lua @@ -2,6 +2,4 @@ function onUpdateDatabase() logger.info("Updating database to version 47 (fix: creature speed and conditions)") db.query("ALTER TABLE `players` MODIFY `conditions` mediumblob NOT NULL;") - - return true end diff --git a/data-otservbr-global/migrations/47.lua b/data-otservbr-global/migrations/47.lua index 86a6d8ffec1..3c8908b5641 100644 --- a/data-otservbr-global/migrations/47.lua +++ b/data-otservbr-global/migrations/47.lua @@ -1,3 +1,24 @@ function onUpdateDatabase() - return false -- true = There are others migrations file | false = this is the last migration file + logger.info("Updating database to version 46 (hireling)") + + db.query([[ + CREATE TABLE IF NOT EXISTS `player_hirelings` ( + `id` INT NOT NULL PRIMARY KEY auto_increment, + `player_id` INT NOT NULL, + `name` varchar(255), + `active` tinyint unsigned NOT NULL DEFAULT '0', + `sex` tinyint unsigned NOT NULL DEFAULT '0', + `posx` int(11) NOT NULL DEFAULT '0', + `posy` int(11) NOT NULL DEFAULT '0', + `posz` int(11) NOT NULL DEFAULT '0', + `lookbody` int(11) NOT NULL DEFAULT '0', + `lookfeet` int(11) NOT NULL DEFAULT '0', + `lookhead` int(11) NOT NULL DEFAULT '0', + `looklegs` int(11) NOT NULL DEFAULT '0', + `looktype` int(11) NOT NULL DEFAULT '136', + + FOREIGN KEY(`player_id`) REFERENCES `players`(`id`) + ON DELETE CASCADE + ) + ]]) end diff --git a/data-otservbr-global/migrations/5.lua b/data-otservbr-global/migrations/5.lua index 50a02a7feb5..dbc324198dd 100644 --- a/data-otservbr-global/migrations/5.lua +++ b/data-otservbr-global/migrations/5.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 6 (quickloot)") db.query("ALTER TABLE `players` ADD `quickloot_fallback` TINYINT DEFAULT 0") - return true end diff --git a/data-otservbr-global/migrations/6.lua b/data-otservbr-global/migrations/6.lua index 905a02ac146..91766a68ca7 100644 --- a/data-otservbr-global/migrations/6.lua +++ b/data-otservbr-global/migrations/6.lua @@ -4,5 +4,4 @@ function onUpdateDatabase() `player_id` INT(16) NOT NULL, `item_id` INT(16) NOT NULL, `item_count` INT(32) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;]]) - return true -- true = There are others migrations file | false = this is the last migration file end diff --git a/data-otservbr-global/migrations/7.lua b/data-otservbr-global/migrations/7.lua index f5c7e6ed530..cade1faae1f 100644 --- a/data-otservbr-global/migrations/7.lua +++ b/data-otservbr-global/migrations/7.lua @@ -1,5 +1,4 @@ function onUpdateDatabase() logger.info("Updating database to version 8 (recruiter system)") db.query("ALTER TABLE `accounts` ADD `recruiter` INT(6) DEFAULT 0") - return true end diff --git a/data-otservbr-global/migrations/8.lua b/data-otservbr-global/migrations/8.lua index bab5e908756..523b705c0c7 100644 --- a/data-otservbr-global/migrations/8.lua +++ b/data-otservbr-global/migrations/8.lua @@ -26,5 +26,4 @@ function onUpdateDatabase() `UsedRunesBit` VARCHAR(250) NULL , `UnlockedRunesBit` VARCHAR(250) NULL, `tracker list` BLOB NULL ) ENGINE = InnoDB DEFAULT CHARSET=utf8;]]) - return true -- true = There are others migrations file | false = this is the last migration file end diff --git a/data-otservbr-global/migrations/9.lua b/data-otservbr-global/migrations/9.lua index 23aa28daf75..7ce8e189768 100644 --- a/data-otservbr-global/migrations/9.lua +++ b/data-otservbr-global/migrations/9.lua @@ -5,5 +5,4 @@ function onUpdateDatabase() db.query("ALTER TABLE `players` ADD `lookmounthead` tinyint(3) unsigned NOT NULL DEFAULT '0'") db.query("ALTER TABLE `players` ADD `lookmountlegs` tinyint(3) unsigned NOT NULL DEFAULT '0'") db.query("ALTER TABLE `players` ADD `lookfamiliarstype` int(11) unsigned NOT NULL DEFAULT '0'") - return true end diff --git a/data-otservbr-global/migrations/README.md b/data-otservbr-global/migrations/README.md new file mode 100644 index 00000000000..b23473bf29d --- /dev/null +++ b/data-otservbr-global/migrations/README.md @@ -0,0 +1,45 @@ +# Database Migration System + +This document provides an overview of the current database migration system for the project. The migration process has been streamlined to ensure that all migration scripts are automatically applied in order, making it easier to maintain database updates. + +## How It Works + +The migration system is designed to apply updates to the database schema or data whenever a new server version is started. Migration scripts are stored in the `migrations` directory, and the system will automatically apply any scripts that have not yet been executed. + +### Steps Involved + +1. **Retrieve Current Database Version**: + - The system first retrieves the current version of the database using `getDatabaseVersion()`. + - This version is used to determine which migration scripts need to be executed. + +2. **Migration Files Directory**: + - All migration scripts are stored in the `migrations` directory. + - Each migration script is named using a numerical pattern, such as `1.lua`, `2.lua`, etc. + - The naming convention helps determine the order in which scripts should be applied. + +3. **Execute Migration Scripts**: + - The migration system iterates through the migration directory and applies each migration script that has a version greater than the current database version. + - Only scripts that have not been applied are executed. + - The Lua state (`lua_State* L`) is initialized to run each script. + +4. **Update Database Version**: + - After each migration script is successfully applied, the system updates the database version to reflect the applied change. + - This ensures that the script is not re-applied on subsequent server startups. + +## Example Migration Script + +Below is an example of what a migration script might look like. Note that no return value is required, as all migration files are applied based on the current database version. + +```lua +-- Migration script example (for documentation purposes only) +-- This migration script should include all necessary SQL commands or operations to apply a specific update to the database. + +-- Example: Adding a new column to the "players" table +local query = [[ + ALTER TABLE players ADD COLUMN new_feature_flag TINYINT(1) NOT NULL DEFAULT 0; +]] + +-- Execute the query +db.execute(query) -- This function executes the given SQL query on the database. + +-- Note: Ensure that queries are validated to avoid errors during the migration process. diff --git a/src/database/databasemanager.cpp b/src/database/databasemanager.cpp index 2941172f35a..142a1db332a 100644 --- a/src/database/databasemanager.cpp +++ b/src/database/databasemanager.cpp @@ -13,6 +13,19 @@ #include "lua/functions/core/libs/core_libs_functions.hpp" #include "lua/scripts/luascript.hpp" +namespace InternalDBManager { + int32_t extractVersionFromFilename(const std::string &filename) { + std::regex versionRegex(R"((\d+)\.lua)"); + std::smatch match; + + if (std::regex_search(filename, match, versionRegex) && match.size() > 1) { + return std::stoi(match.str(1)); + } + + return -1; + } +} + bool DatabaseManager::optimizeTables() { Database &db = Database::getInstance(); std::ostringstream query; @@ -73,48 +86,62 @@ int32_t DatabaseManager::getDatabaseVersion() { } void DatabaseManager::updateDatabase() { + Benchmark bm; lua_State* L = luaL_newstate(); if (!L) { return; } luaL_openlibs(L); - CoreLibsFunctions::init(L); - int32_t version = getDatabaseVersion(); - do { - std::ostringstream ss; - ss << g_configManager().getString(DATA_DIRECTORY) + "/migrations/" << version << ".lua"; - if (luaL_dofile(L, ss.str().c_str()) != 0) { - g_logger().error("DatabaseManager::updateDatabase - Version: {}" - "] {}", - version, lua_tostring(L, -1)); - break; - } + int32_t currentVersion = getDatabaseVersion(); + std::string migrationDirectory = g_configManager().getString(DATA_DIRECTORY) + "/migrations/"; - if (!LuaScriptInterface::reserveScriptEnv()) { - break; - } + std::vector> migrations; - lua_getglobal(L, "onUpdateDatabase"); - if (lua_pcall(L, 0, 1, 0) != 0) { - LuaScriptInterface::resetScriptEnv(); - g_logger().warn("[DatabaseManager::updateDatabase - Version: {}] {}", version, lua_tostring(L, -1)); - break; + for (const auto &entry : std::filesystem::directory_iterator(migrationDirectory)) { + if (entry.is_regular_file()) { + std::string filename = entry.path().filename().string(); + int32_t fileVersion = InternalDBManager::extractVersionFromFilename(filename); + migrations.emplace_back(fileVersion, entry.path().string()); } + } + + std::sort(migrations.begin(), migrations.end()); + + for (const auto &[fileVersion, scriptPath] : migrations) { + if (fileVersion > currentVersion) { + if (!LuaScriptInterface::reserveScriptEnv()) { + break; + } + + if (luaL_dofile(L, scriptPath.c_str()) != 0) { + g_logger().error("DatabaseManager::updateDatabase - Version: {}] {}", fileVersion, lua_tostring(L, -1)); + continue; + } + + lua_getglobal(L, "onUpdateDatabase"); + if (lua_pcall(L, 0, 1, 0) != 0) { + LuaScriptInterface::resetScriptEnv(); + g_logger().warn("[DatabaseManager::updateDatabase - Version: {}] {}", fileVersion, lua_tostring(L, -1)); + continue; + } + + currentVersion = fileVersion; + g_logger().info("Database has been updated to version {}", currentVersion); + registerDatabaseConfig("db_version", currentVersion); - if (!LuaScriptInterface::getBoolean(L, -1, false)) { LuaScriptInterface::resetScriptEnv(); - break; } + } - version++; - g_logger().info("Database has been updated to version {}", version); - registerDatabaseConfig("db_version", version); - - LuaScriptInterface::resetScriptEnv(); - } while (true); + double duration = bm.duration(); + if (duration < 1000.0) { + g_logger().debug("Database update completed in {:.2f} ms", duration); + } else { + g_logger().debug("Database update completed in {:.2f} seconds", duration / 1000.0); + } lua_close(L); }