2022-07-10 19:40:26 +00:00
# include "MigrationRunner.h"
2022-10-24 22:20:36 +00:00
# include "BrickByBrickFix.h"
2022-07-10 19:40:26 +00:00
# include "GeneralUtils.h"
# include <fstream>
# include <algorithm>
# include <thread>
void MigrationRunner : : RunMigrations ( ) {
2022-10-24 22:20:36 +00:00
auto * stmt = Database : : CreatePreppedStmt ( " CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP()); " ) ;
stmt - > execute ( ) ;
2022-07-10 19:40:26 +00:00
delete stmt ;
2022-07-28 13:39:57 +00:00
2022-07-10 19:40:26 +00:00
sql : : SQLString finalSQL = " " ;
Migration checkMigration { } ;
2022-10-24 22:20:36 +00:00
bool runSd0Migrations = false ;
2022-07-10 19:40:26 +00:00
for ( const auto & entry : GeneralUtils : : GetFileNamesFromFolder ( " ./migrations/ " ) ) {
auto migration = LoadMigration ( entry ) ;
2022-07-28 13:39:57 +00:00
2022-07-10 19:40:26 +00:00
if ( migration . data . empty ( ) ) {
continue ;
}
2022-07-28 13:39:57 +00:00
2022-07-10 19:40:26 +00:00
checkMigration = migration ;
2022-07-28 13:39:57 +00:00
2022-07-10 19:40:26 +00:00
stmt = Database : : CreatePreppedStmt ( " SELECT name FROM migration_history WHERE name = ?; " ) ;
stmt - > setString ( 1 , migration . name ) ;
2022-10-24 22:20:36 +00:00
auto * res = stmt - > executeQuery ( ) ;
2022-07-10 19:40:26 +00:00
bool doExit = res - > next ( ) ;
delete res ;
delete stmt ;
if ( doExit ) continue ;
2022-07-28 13:39:57 +00:00
2022-07-27 06:52:53 +00:00
Game : : logger - > Log ( " MigrationRunner " , " Running migration: %s " , migration . name . c_str ( ) ) ;
2022-10-24 22:20:36 +00:00
if ( migration . name = = " 5_brick_model_sd0.sql " ) {
runSd0Migrations = true ;
} else {
finalSQL . append ( migration . data ) ;
}
2022-07-28 13:39:57 +00:00
2022-07-10 19:40:26 +00:00
stmt = Database : : CreatePreppedStmt ( " INSERT INTO migration_history (name) VALUES (?); " ) ;
stmt - > setString ( 1 , entry ) ;
stmt - > execute ( ) ;
delete stmt ;
}
2022-07-28 13:39:57 +00:00
2022-10-24 22:20:36 +00:00
if ( finalSQL . empty ( ) & & ! runSd0Migrations ) {
Game : : logger - > Log ( " MigrationRunner " , " Server database is up to date. " ) ;
return ;
}
2022-07-10 19:40:26 +00:00
if ( ! finalSQL . empty ( ) ) {
2022-10-24 22:20:36 +00:00
auto migration = GeneralUtils : : SplitString ( static_cast < std : : string > ( finalSQL ) , ' ; ' ) ;
std : : unique_ptr < sql : : Statement > simpleStatement ( Database : : CreateStmt ( ) ) ;
for ( auto & query : migration ) {
try {
if ( query . empty ( ) ) continue ;
simpleStatement - > execute ( query ) ;
} catch ( sql : : SQLException & e ) {
Game : : logger - > Log ( " MigrationRunner " , " Encountered error running migration: %s " , e . what ( ) ) ;
}
2022-07-10 19:40:26 +00:00
}
}
2022-10-24 22:20:36 +00:00
// Do this last on the off chance none of the other migrations have been run yet.
if ( runSd0Migrations ) {
uint32_t numberOfUpdatedModels = BrickByBrickFix : : UpdateBrickByBrickModelsToSd0 ( ) ;
Game : : logger - > Log ( " MasterServer " , " %i models were updated from zlib to sd0. " , numberOfUpdatedModels ) ;
uint32_t numberOfTruncatedModels = BrickByBrickFix : : TruncateBrokenBrickByBrickXml ( ) ;
Game : : logger - > Log ( " MasterServer " , " %i models were truncated from the database. " , numberOfTruncatedModels ) ;
}
2022-07-10 19:40:26 +00:00
}
Migration MigrationRunner : : LoadMigration ( std : : string path ) {
Migration migration { } ;
std : : ifstream file ( " ./migrations/ " + path ) ;
if ( file . is_open ( ) ) {
std : : string line ;
std : : string total = " " ;
while ( std : : getline ( file , line ) ) {
total + = line ;
}
file . close ( ) ;
migration . name = path ;
migration . data = total ;
}
2022-07-25 02:26:51 +00:00
2022-07-10 19:40:26 +00:00
return migration ;
}