Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
83.33% |
10 / 12 |
CRAP | |
96.88% |
62 / 64 |
DatabaseMigrator | |
0.00% |
0 / 1 |
|
83.33% |
10 / 12 |
23 | |
96.88% |
62 / 64 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
11 / 11 |
|||
createAlterStatementList | |
100.00% |
1 / 1 |
3 | |
100.00% |
9 / 9 |
|||
createDropAllProcedureStatementList | |
0.00% |
0 / 1 |
2.06 | |
75.00% |
3 / 4 |
|||
migrateEntity | |
100.00% |
1 / 1 |
2 | |
100.00% |
10 / 10 |
|||
setupEntityInDatabase | |
100.00% |
1 / 1 |
2 | |
100.00% |
7 / 7 |
|||
getTableMetaDataByEntity | |
0.00% |
0 / 1 |
4.03 | |
87.50% |
7 / 8 |
|||
dropUnusedTables | |
100.00% |
1 / 1 |
4 | |
100.00% |
8 / 8 |
|||
addStatementList | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
addAlterStatementList | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
getDropStoredProcedureStatementList | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getAlterStatementList | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getCreateStoredProcedureStatementList | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
<?php | |
declare(strict_types = 1); | |
namespace Siesta\Migration; | |
use Siesta\Database\Connection; | |
use Siesta\Database\CreateStatementFactory; | |
use Siesta\Database\MetaData\DatabaseMetaData; | |
use Siesta\Database\MetaData\TableMetaData; | |
use Siesta\Database\MigrationStatementFactory; | |
use Siesta\Database\StoredProcedureFactory; | |
use Siesta\Model\DataModel; | |
use Siesta\Model\Entity; | |
/** | |
* @author Gregor Müller | |
*/ | |
class DatabaseMigrator | |
{ | |
/** | |
* @var Connection | |
*/ | |
protected $connection; | |
/** | |
* @var DatabaseMetaData | |
*/ | |
protected $databaseMetaData; | |
/** | |
* @var TableMetaData[] | |
*/ | |
protected $databaseTableList; | |
/** | |
* @var MigrationStatementFactory | |
*/ | |
protected $migrationStatementFactory; | |
/** | |
* @var StoredProcedureFactory | |
*/ | |
protected $storedProcedureFactoy; | |
/** | |
* @var StoredProcedureMigrator | |
*/ | |
protected $storedProcedureMigrator; | |
/** | |
* @var DataModel | |
*/ | |
protected $dataModel; | |
/** | |
* list of table names that are also defined in the current datamodel | |
* @var string[] | |
*/ | |
protected $neededTableList; | |
/** | |
* @var string[] | |
*/ | |
protected $dropStoredProcedureStatementList; | |
/** | |
* @var string[] | |
*/ | |
protected $createStoredProcedureStatementList; | |
/** | |
* @var string[] | |
*/ | |
protected $alterStatementList; | |
/** | |
* @param DataModel $dataModel | |
* @param Connection $connection | |
*/ | |
public function __construct(DataModel $dataModel, Connection $connection) | |
{ | |
$this->dataModel = $dataModel; | |
$this->connection = $connection; | |
$this->databaseMetaData = $connection->getDatabaseMetaData(); | |
$this->storedProcedureFactory = $connection->getStoredProcedureFactory(); | |
$this->storedProcedureMigrator = new StoredProcedureMigrator($this->storedProcedureFactory); | |
$this->migrationStatementFactory = $connection->getMigrationStatementFactory(); | |
$this->neededTableList = [CreateStatementFactory::SEQUENCER_TABLE_NAME]; | |
$this->dropStoredProcedureStatementList = []; | |
$this->alterStatementList = []; | |
$this->createStoredProcedureStatementList = []; | |
} | |
/** | |
* @param bool $dropUnusedTables | |
*/ | |
public function createAlterStatementList(bool $dropUnusedTables) | |
{ | |
$this->createDropAllProcedureStatementList(); | |
$factory = $this->connection->getCreateStatementFactory(); | |
$this->addStatementList($factory->buildSequencer()); | |
$this->databaseTableList = $this->databaseMetaData->getTableList(); | |
foreach ($this->dataModel->getEntityList() as $entity) { | |
$this->migrateEntity($entity); | |
} | |
if ($dropUnusedTables) { | |
$this->dropUnusedTables(); | |
} | |
} | |
/** | |
* | |
*/ | |
private function createDropAllProcedureStatementList() | |
{ | |
$storedProcedureNameList = $this->databaseMetaData->getStoredProcedureList(); | |
foreach ($storedProcedureNameList as $storedProcedureName) { | |
$this->dropStoredProcedureStatementList[] = $this->storedProcedureFactory->createDropStatementForProcedureName($storedProcedureName); | |
} | |
} | |
/** | |
* @param Entity $entity | |
* | |
* @return void | |
*/ | |
private function migrateEntity(Entity $entity) | |
{ | |
$tableMetaData = $this->getTableMetaDataByEntity($entity); | |
// if database entity does not exist, create it | |
if ($tableMetaData === null) { | |
$this->setupEntityInDatabase($entity); | |
return; | |
} | |
// compare database with current model/schema | |
$entityMigrator = new TableMigrator($this->migrationStatementFactory, $tableMetaData, $entity); | |
$alterStatementList = $entityMigrator->createAlterStatementList(); | |
$this->addAlterStatementList($alterStatementList); | |
// create stored procedures | |
$statementList = $this->storedProcedureMigrator->getMigrateProcedureStatementList($this->dataModel, $entity); | |
$this->addStatementList($statementList); | |
} | |
/** | |
* @param Entity $entity | |
* | |
* @return void | |
*/ | |
private function setupEntityInDatabase(Entity $entity) | |
{ | |
$factory = $this->connection->getCreateStatementFactory(); | |
$this->addAlterStatementList($factory->buildCreateTable($entity)); | |
if ($entity->getIsDelimit()) { | |
$this->addAlterStatementList($factory->buildCreateDelimitTable($entity)); | |
} | |
$spMigrationList = $this->storedProcedureMigrator->getMigrateProcedureStatementList($this->dataModel, $entity); | |
$this->addStatementList($spMigrationList); | |
} | |
/** | |
* @param Entity $entity | |
* | |
* @return TableMetaData|null | |
*/ | |
private function getTableMetaDataByEntity(Entity $entity) | |
{ | |
$tableName = $entity->getTableName(); | |
foreach ($this->databaseTableList as $tableMetaData) { | |
if ($tableMetaData->getName() === $tableName) { | |
$this->neededTableList[] = $tableName; | |
if ($entity->getIsDelimit()) { | |
$this->neededTableList[] = $entity->getDelimitTableName(); | |
} | |
// TODO: handle replication | |
return $tableMetaData; | |
} | |
} | |
return null; | |
} | |
/** | |
* drops unused database tables | |
* @return void | |
*/ | |
private function dropUnusedTables() | |
{ | |
foreach ($this->databaseTableList as $databaseTable) { | |
if (in_array($databaseTable->getName(), $this->neededTableList)) { | |
continue; | |
} | |
$statementList = $this->migrationStatementFactory->getDropTableStatement($databaseTable); | |
foreach ($statementList as $statement) { | |
$dropStatement = str_replace(MigrationStatementFactory::TABLE_PLACE_HOLDER, $databaseTable->getName(), $statement); | |
$this->addAlterStatementList([$dropStatement]); | |
} | |
} | |
} | |
/** | |
* @param array $statementList | |
* | |
* @return void | |
*/ | |
private function addStatementList(array $statementList) | |
{ | |
$this->createStoredProcedureStatementList = array_merge($this->createStoredProcedureStatementList, $statementList); | |
} | |
/** | |
* @param array $alterStatementList | |
*/ | |
private function addAlterStatementList(array $alterStatementList) | |
{ | |
$this->alterStatementList = array_merge($this->alterStatementList, $alterStatementList); | |
} | |
/** | |
* @return string[] | |
*/ | |
public function getDropStoredProcedureStatementList() | |
{ | |
return $this->dropStoredProcedureStatementList; | |
} | |
/** | |
* will contain create table and alter table statements | |
* @return String[] | |
*/ | |
public function getAlterStatementList() | |
{ | |
return $this->alterStatementList; | |
} | |
/** | |
* will contain stored procedure create and drop statements as well as sequencer | |
* @return String[] | |
*/ | |
public function getCreateStoredProcedureStatementList() | |
{ | |
return $this->createStoredProcedureStatementList; | |
} | |
} |