[2.0] DDC-114 - Extend SchemaTool Drop functionality to optionally drop the complete database. Additionally a filter against all existing table is applied to avoid errors due to dropping non-existant tables. Updated Schema-Tool CLI command with optional calls --drop=database --drop=metadata but kept original --drop which defaults to "metadata". Updated documentation.
This commit is contained in:
parent
884131e51f
commit
3678b65186
2 changed files with 87 additions and 19 deletions
|
@ -60,8 +60,9 @@ class SchemaToolTask extends AbstractTask
|
|||
->writeln("\t\tCreates the schema in EntityManager (create tables on Database)")
|
||||
->writeln("\t\t\tIf defined, --drop and --update can not be requested on same task")
|
||||
->write(PHP_EOL)
|
||||
->write('--drop', 'REQ_ARG')
|
||||
->write('--drop=<metadata|database>', 'REQ_ARG')
|
||||
->writeln("\t\t\tDrops the schema of EntityManager (drop tables on Database)")
|
||||
->writeln("\t\t\tDefaults to 'metadata' if only --drop is specified.")
|
||||
->writeln("\t\t\tIf defined, --create and --update can not be requested on same task")
|
||||
->write(PHP_EOL)
|
||||
->write('--update', 'REQ_ARG')
|
||||
|
@ -90,7 +91,7 @@ class SchemaToolTask extends AbstractTask
|
|||
private function _writeSynopsis($printer)
|
||||
{
|
||||
$printer->write('schema-tool', 'KEYWORD')
|
||||
->write(' (--create | --drop | --update | --re-create)', 'REQ_ARG')
|
||||
->write(' (--create | --drop=<metadata|database> | --update | --re-create)', 'REQ_ARG')
|
||||
->writeln(' [--dump-sql] [--class-dir=<path>]', 'OPT_ARG');
|
||||
}
|
||||
|
||||
|
@ -151,10 +152,10 @@ class SchemaToolTask extends AbstractTask
|
|||
$em = $this->getEntityManager();
|
||||
$cmf = $em->getMetadataFactory();
|
||||
$driver = $em->getConfiguration()->getMetadataDriverImpl();
|
||||
|
||||
|
||||
$classes = array();
|
||||
$preloadedClasses = $driver->preload(true);
|
||||
|
||||
|
||||
foreach ($preloadedClasses as $className) {
|
||||
$classes[] = $cmf->getMetadataFor($className);
|
||||
}
|
||||
|
@ -169,15 +170,20 @@ class SchemaToolTask extends AbstractTask
|
|||
$tool = new SchemaTool($em);
|
||||
|
||||
if ($isDrop) {
|
||||
$dropMode = $args['drop'];
|
||||
if(!in_array($dropMode, array('metadata', 'database'))) {
|
||||
$dropMode = 'metadata';
|
||||
}
|
||||
|
||||
if (isset($args['dump-sql'])) {
|
||||
foreach ($tool->getDropSchemaSql($classes) as $sql) {
|
||||
foreach ($tool->getDropSchemaSql($classes, $dropMode) as $sql) {
|
||||
$printer->writeln($sql);
|
||||
}
|
||||
} else {
|
||||
$printer->writeln('Dropping database schema...', 'INFO');
|
||||
|
||||
try {
|
||||
$tool->dropSchema($classes);
|
||||
$tool->dropSchema($classes, $dropMode);
|
||||
$printer->writeln('Database schema dropped successfully.', 'INFO');
|
||||
} catch (\Exception $ex) {
|
||||
throw new DoctrineException($ex);
|
||||
|
|
|
@ -40,6 +40,15 @@ use Doctrine\DBAL\Types\Type,
|
|||
*/
|
||||
class SchemaTool
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const DROP_METADATA = "metadata";
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
const DROP_DATABASE = "database";
|
||||
|
||||
/**
|
||||
* @var \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
|
@ -417,13 +426,17 @@ class SchemaTool
|
|||
|
||||
/**
|
||||
* Drops the database schema for the given classes.
|
||||
*
|
||||
*
|
||||
* In any way when an exception is thrown it is supressed since drop was
|
||||
* issued for all classes of the schema and some probably just don't exist.
|
||||
*
|
||||
* @param array $classes
|
||||
* @param string $mode
|
||||
* @return void
|
||||
*/
|
||||
public function dropSchema(array $classes)
|
||||
public function dropSchema(array $classes, $mode=self::DROP_METADATA)
|
||||
{
|
||||
$dropSchemaSql = $this->getDropSchemaSql($classes);
|
||||
$dropSchemaSql = $this->getDropSchemaSql($classes, $mode);
|
||||
$conn = $this->_em->getConnection();
|
||||
|
||||
foreach ($dropSchemaSql as $sql) {
|
||||
|
@ -435,35 +448,84 @@ class SchemaTool
|
|||
* Gets the SQL needed to drop the database schema for the given classes.
|
||||
*
|
||||
* @param array $classes
|
||||
* @param string $mode
|
||||
* @return array
|
||||
*/
|
||||
public function getDropSchemaSql(array $classes)
|
||||
public function getDropSchemaSql(array $classes, $mode=self::DROP_METADATA)
|
||||
{
|
||||
if($mode == self::DROP_METADATA) {
|
||||
$tables = $this->_getDropSchemaTablesMetadataMode($classes);
|
||||
} else if($mode == self::DROP_DATABASE) {
|
||||
$tables = $this->_getDropSchemaTablesDatabaseMode($classes);
|
||||
} else {
|
||||
throw new \Doctrine\ORM\ORMException("Given Drop Schema Mode is not supported.");
|
||||
}
|
||||
|
||||
$sm = $this->_em->getConnection()->getSchemaManager();
|
||||
/* @var $sm \Doctrine\DBAL\Schema\AbstractSchemaManager */
|
||||
$allTables = $sm->listTables();
|
||||
|
||||
$sql = array();
|
||||
foreach($tables AS $tableName) {
|
||||
if(in_array($tableName, $allTables)) {
|
||||
$sql[] = $this->_platform->getDropTableSql($tableName);
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all tables of the database connection.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function _getDropSchemaTablesDatabaseMode($classes)
|
||||
{
|
||||
$conn = $this->_em->getConnection();
|
||||
|
||||
$sm = $conn->getSchemaManager();
|
||||
/* @var $sm \Doctrine\DBAL\Schema\AbstractSchemaManager */
|
||||
|
||||
$allTables = $sm->listTables();
|
||||
|
||||
$orderedTables = $this->_getDropSchemaTablesMetadataMode($classes);
|
||||
foreach($allTables AS $tableName) {
|
||||
if(!in_array($tableName, $orderedTables)) {
|
||||
$orderedTables[] = $tableName;
|
||||
}
|
||||
}
|
||||
|
||||
return $orderedTables;
|
||||
}
|
||||
|
||||
private function _getDropSchemaTablesMetadataMode(array $classes)
|
||||
{
|
||||
$orderedTables = array();
|
||||
|
||||
$commitOrder = $this->_getCommitOrder($classes);
|
||||
$associationTables = $this->_getAssociationTables($commitOrder);
|
||||
|
||||
|
||||
// Drop association tables first
|
||||
foreach ($associationTables as $associationTable) {
|
||||
$sql[] = $this->_platform->getDropTableSql($associationTable);
|
||||
$orderedTables[] = $associationTable;
|
||||
}
|
||||
|
||||
// Drop tables in reverse commit order
|
||||
for ($i = count($commitOrder) - 1; $i >= 0; --$i) {
|
||||
$class = $commitOrder[$i];
|
||||
|
||||
|
||||
if (($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName)
|
||||
|| $class->isMappedSuperclass) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sql[] = $this->_platform->getDropTableSql($class->getTableName());
|
||||
|
||||
$orderedTables[] = $class->getTableName();
|
||||
}
|
||||
|
||||
|
||||
//TODO: Drop other schema elements, like sequences etc.
|
||||
|
||||
return $sql;
|
||||
|
||||
return $orderedTables;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -713,7 +775,7 @@ class SchemaTool
|
|||
private function _getCommitOrder(array $classes)
|
||||
{
|
||||
$calc = new CommitOrderCalculator;
|
||||
|
||||
|
||||
// Calculate dependencies
|
||||
foreach ($classes as $class) {
|
||||
$calc->addClass($class);
|
||||
|
|
Loading…
Add table
Reference in a new issue