Skip to content

Instantly share code, notes, and snippets.

@halkyon
Last active June 18, 2019 23:08
Show Gist options
  • Save halkyon/ec08493c2906c1539a49 to your computer and use it in GitHub Desktop.
Save halkyon/ec08493c2906c1539a49 to your computer and use it in GitHub Desktop.
BuildTask for SilverStripe to remove obsolete tables, columns and indexes from the database
<?php
/**
* Remove old tables, columns, and indexes from a SilverStripe database.
*
* Define your obsolete tables, columns and indexes in {@link $deleted_tables},
* {@link deleted_columns} and {@link deleted_indexes} and these will be deleted
* from the database.
*
* In addition to that, it will automatically remove any tables and columns prefixed with "_obsolete".
*/
class CleanupDatabaseTask extends BuildTask {
/**
* If any of these tables are found in the database, they will be removed.
* @var array
*/
private static $deleted_tables = array(
'SomeOldTable'
);
/**
* These columns should be deleted. * key indicates any table with columns listed in the array
* value should be removed. If the key is a specific table, only columns listed in the array
* for that table will be removed.
*
* @var array
*/
private static $deleted_columns = array(
'*' => array('SomeOldColumn'),
'SomeOldTable' => array('Status', 'Version')
);
/**
* If any of these indexes are found in any tables, they will be removed.
* @var array
*/
private static $deleted_indexes = array(
'SomeOldIndex'
);
protected function log($message) {
echo $message . PHP_EOL;
}
protected function execute($sql) {
if(!empty($_REQUEST['dryrun'])) {
$this->log(sprintf('DRY RUN: Not running query: %s', $sql));
return true;
}
DB::query($sql);
$this->log(sprintf('INFO: Successfully executed SQL: %s', $sql));
return true;
}
public function run($request) {
global $databaseConfig;
$database = $databaseConfig['database'];
$this->log(sprintf('=== Using database %s ===', $database));
if(!empty($_REQUEST['dryrun'])) {
$this->log('=== Running in dry run mode. SQL will be displayed, but not executed ===');
}
if(!Director::is_cli()) {
$this->log('ERROR: Please run this task under the command line');
return;
}
if(empty($_REQUEST['flush'])) {
$this->log('ERROR: Please run flush=1 to ensure manifest is up to date');
return;
}
foreach($this->config()->deleted_tables as $tableName) {
if(!DB::query(sprintf('SHOW TABLES LIKE \'%s\'', $tableName))->value()) {
$this->log(sprintf('INFO: Table %s was not found in database %s. Skipping', $tableName, $database));
continue;
}
$this->execute(sprintf('DROP TABLE "%s"', $tableName));
}
$obsoleteTables = DB::query(sprintf(
'SHOW TABLES WHERE Tables_in_%s REGEXP \'_obsolete|_copy|_backup\'', $database
));
foreach($obsoleteTables as $table) {
$tableName = $table[sprintf('Tables_in_%s', $database)];
$this->execute(sprintf('DROP TABLE "%s"', $tableName));
}
foreach(DB::query(sprintf('SHOW TABLES FROM "%s"', $database)) as $table) {
$tableName = $table[sprintf('Tables_in_%s', $database)];
// search through indexes, remove indexes marked for deletion
foreach(DB::query(sprintf('SHOW INDEXES FROM "%s"', $tableName)) as $index) {
if(in_array($index['Key_name'], $this->config()->deleted_indexes)) {
$this->execute(sprintf('DROP INDEX "%s" ON "%s"', $index['Key_name'], $tableName));
}
}
// remove obsolete prefixed columns
foreach(DB::query(sprintf('SHOW COLUMNS FROM "%s" WHERE "Field" LIKE \'_obsolete%%\'', $tableName)) as $column) {
$this->execute(sprintf('ALTER TABLE "%s" DROP COLUMN "%s"', $tableName, $column['Field']));
}
// remove columns marked for deletion
foreach($this->config()->deleted_columns as $key => $columnNameArr) {
// if the definitions were for a specific table that we're currently not processing
if($key !== '*' && $key !== $tableName) {
continue;
}
foreach($columnNameArr as $columnName) {
foreach(DB::query(sprintf('SHOW COLUMNS FROM "%s" WHERE "Field" = \'%s\'', $tableName, $columnName)) as $column) {
$this->execute(sprintf('ALTER TABLE "%s" DROP COLUMN "%s"', $tableName, $column['Field']));
}
}
}
}
$this->log('Done');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment