Changes for new migration code.
This commit is contained in:
parent
5d12093b8e
commit
10bdfcb17f
@ -465,6 +465,8 @@ final class Doctrine
|
|||||||
/**
|
/**
|
||||||
* getLoadedModels
|
* getLoadedModels
|
||||||
*
|
*
|
||||||
|
* Get all the loaded models, you can provide an array of classes or it will use get_declared_classes()
|
||||||
|
*
|
||||||
* @package default
|
* @package default
|
||||||
* @author Jonathan H. Wage
|
* @author Jonathan H. Wage
|
||||||
*/
|
*/
|
||||||
@ -507,12 +509,21 @@ final class Doctrine
|
|||||||
|
|
||||||
return $loadedModels;
|
return $loadedModels;
|
||||||
}
|
}
|
||||||
public function getConnectionByTableName($tableName)
|
/**
|
||||||
|
* getConnectionByTableName
|
||||||
|
*
|
||||||
|
* Get the connection object for a table by the actual table name
|
||||||
|
*
|
||||||
|
* @param string $tableName
|
||||||
|
* @return void
|
||||||
|
* @author Jonathan H. Wage
|
||||||
|
*/
|
||||||
|
public static function getConnectionByTableName($tableName)
|
||||||
{
|
{
|
||||||
$loadedModels = Doctrine::getLoadedModels();
|
$loadedModels = self::getLoadedModels();
|
||||||
|
|
||||||
foreach ($loadedModels AS $name) {
|
foreach ($loadedModels AS $name) {
|
||||||
$model = new $model();
|
$model = new $name();
|
||||||
$table = $model->getTable();
|
$table = $model->getTable();
|
||||||
|
|
||||||
if ($table->getTableName() == $tableName) {
|
if ($table->getTableName() == $tableName) {
|
||||||
|
@ -547,9 +547,13 @@ class Doctrine_Export extends Doctrine_Connection_Module
|
|||||||
* actually perform them otherwise.
|
* actually perform them otherwise.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function alterTable($name, array $changes, $check)
|
public function alterTable($name, array $changes, $check = false)
|
||||||
{
|
{
|
||||||
$this->conn->execute($this->alterTableSql($name, $changes, $check));
|
$sql = $this->alterTableSql($name, $changes, $check);
|
||||||
|
|
||||||
|
if (is_string($sql) && $sql) {
|
||||||
|
$this->conn->execute($sql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* generates the sql for altering an existing table
|
* generates the sql for altering an existing table
|
||||||
@ -563,7 +567,7 @@ class Doctrine_Export extends Doctrine_Connection_Module
|
|||||||
* @see Doctrine_Export::alterTable()
|
* @see Doctrine_Export::alterTable()
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function alterTableSql($name, array $changes, $check)
|
public function alterTableSql($name, array $changes, $check = false)
|
||||||
{
|
{
|
||||||
throw new Doctrine_Export_Exception('Alter table not supported by this driver.');
|
throw new Doctrine_Export_Exception('Alter table not supported by this driver.');
|
||||||
}
|
}
|
||||||
|
@ -300,7 +300,7 @@ class Doctrine_Export_Firebird extends Doctrine_Export
|
|||||||
* actually perform them otherwise.
|
* actually perform them otherwise.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function alterTable($name, array $changes, $check)
|
public function alterTable($name, array $changes, $check = false)
|
||||||
{
|
{
|
||||||
foreach ($changes as $changeName => $change) {
|
foreach ($changes as $changeName => $change) {
|
||||||
switch ($changeName) {
|
switch ($changeName) {
|
||||||
|
@ -157,7 +157,7 @@ class Doctrine_Export_Frontbase extends Doctrine_Export
|
|||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function alterTable($name, array $changes, $check)
|
public function alterTable($name, array $changes, $check = false)
|
||||||
{
|
{
|
||||||
foreach ($changes as $changeName => $change) {
|
foreach ($changes as $changeName => $change) {
|
||||||
switch ($changeName) {
|
switch ($changeName) {
|
||||||
|
@ -161,7 +161,7 @@ class Doctrine_Export_Mssql extends Doctrine_Export
|
|||||||
* actually perform them otherwise.
|
* actually perform them otherwise.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function alterTable($name, array $changes, $check)
|
public function alterTable($name, array $changes, $check = false)
|
||||||
{
|
{
|
||||||
foreach ($changes as $changeName => $change) {
|
foreach ($changes as $changeName => $change) {
|
||||||
switch ($changeName) {
|
switch ($changeName) {
|
||||||
|
@ -267,7 +267,7 @@ class Doctrine_Export_Mysql extends Doctrine_Export
|
|||||||
* actually perform them otherwise.
|
* actually perform them otherwise.
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function alterTableSql($name, array $changes, $check)
|
public function alterTableSql($name, array $changes, $check = false)
|
||||||
{
|
{
|
||||||
if ( ! $name) {
|
if ( ! $name) {
|
||||||
throw new Doctrine_Export_Exception('no valid table name specified');
|
throw new Doctrine_Export_Exception('no valid table name specified');
|
||||||
@ -355,7 +355,8 @@ class Doctrine_Export_Mysql extends Doctrine_Export
|
|||||||
}
|
}
|
||||||
|
|
||||||
$name = $this->conn->quoteIdentifier($name, true);
|
$name = $this->conn->quoteIdentifier($name, true);
|
||||||
return $this->conn->exec('ALTER TABLE ' . $name . ' ' . $query);
|
|
||||||
|
return 'ALTER TABLE ' . $name . ' ' . $query;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* create sequence
|
* create sequence
|
||||||
|
@ -398,7 +398,7 @@ END;
|
|||||||
* actually perform them otherwise.
|
* actually perform them otherwise.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function alterTable($name, array $changes, $check)
|
public function alterTable($name, array $changes, $check = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
foreach ($changes as $changeName => $change) {
|
foreach ($changes as $changeName => $change) {
|
||||||
|
@ -182,7 +182,7 @@ class Doctrine_Export_Pgsql extends Doctrine_Export
|
|||||||
* @throws Doctrine_Connection_Exception
|
* @throws Doctrine_Connection_Exception
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function alterTable($name, array $changes, $check)
|
public function alterTable($name, array $changes, $check = false)
|
||||||
{
|
{
|
||||||
foreach ($changes as $changeName => $change) {
|
foreach ($changes as $changeName => $change) {
|
||||||
switch ($changeName) {
|
switch ($changeName) {
|
||||||
|
@ -325,4 +325,96 @@ class Doctrine_Export_Sqlite extends Doctrine_Export
|
|||||||
|
|
||||||
return 'DROP TABLE ' . $sequenceName;
|
return 'DROP TABLE ' . $sequenceName;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public function alterTableSql($name, array $changes, $check = false)
|
||||||
|
{
|
||||||
|
if ( ! $name) {
|
||||||
|
throw new Doctrine_Export_Exception('no valid table name specified');
|
||||||
|
}
|
||||||
|
foreach ($changes as $changeName => $change) {
|
||||||
|
switch ($changeName) {
|
||||||
|
case 'add':
|
||||||
|
case 'remove':
|
||||||
|
case 'change':
|
||||||
|
case 'rename':
|
||||||
|
case 'name':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Doctrine_Export_Exception('change type "' . $changeName . '" not yet supported');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($check) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = '';
|
||||||
|
if ( ! empty($changes['name'])) {
|
||||||
|
$change_name = $this->conn->quoteIdentifier($changes['name']);
|
||||||
|
$query .= 'RENAME TO ' . $change_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! empty($changes['add']) && is_array($changes['add'])) {
|
||||||
|
foreach ($changes['add'] as $fieldName => $field) {
|
||||||
|
if ($query) {
|
||||||
|
$query.= ', ';
|
||||||
|
}
|
||||||
|
$query.= 'ADD ' . $this->getDeclaration($field['type'], $fieldName, $field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! empty($changes['remove']) && is_array($changes['remove'])) {
|
||||||
|
foreach ($changes['remove'] as $fieldName => $field) {
|
||||||
|
if ($query) {
|
||||||
|
$query .= ', ';
|
||||||
|
}
|
||||||
|
$fieldName = $this->conn->quoteIdentifier($fieldName);
|
||||||
|
$query .= 'DROP ' . $fieldName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$rename = array();
|
||||||
|
if ( ! empty($changes['rename']) && is_array($changes['rename'])) {
|
||||||
|
foreach ($changes['rename'] as $fieldName => $field) {
|
||||||
|
$rename[$field['name']] = $fieldName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! empty($changes['change']) && is_array($changes['change'])) {
|
||||||
|
foreach ($changes['change'] as $fieldName => $field) {
|
||||||
|
if ($query) {
|
||||||
|
$query.= ', ';
|
||||||
|
}
|
||||||
|
if (isset($rename[$fieldName])) {
|
||||||
|
$oldFieldName = $rename[$fieldName];
|
||||||
|
unset($rename[$fieldName]);
|
||||||
|
} else {
|
||||||
|
$oldFieldName = $fieldName;
|
||||||
|
}
|
||||||
|
$oldFieldName = $this->conn->quoteIdentifier($oldFieldName, true);
|
||||||
|
$query .= 'CHANGE ' . $oldFieldName . ' '
|
||||||
|
. $this->getDeclaration($field['definition']['type'], $fieldName, $field['definition']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! empty($rename) && is_array($rename)) {
|
||||||
|
foreach ($rename as $renameName => $renamedField) {
|
||||||
|
if ($query) {
|
||||||
|
$query.= ', ';
|
||||||
|
}
|
||||||
|
$field = $changes['rename'][$renamedField];
|
||||||
|
$renamedField = $this->conn->quoteIdentifier($renamedField, true);
|
||||||
|
$query .= 'CHANGE ' . $renamedField . ' '
|
||||||
|
. $this->getDeclaration($field['definition']['type'], $field['name'], $field['definition']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! $query) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = $this->conn->quoteIdentifier($name, true);
|
||||||
|
|
||||||
|
return 'ALTER TABLE ' . $name . ' ' . $query;
|
||||||
|
}
|
||||||
|
}
|
@ -43,7 +43,35 @@ class Doctrine_Migration
|
|||||||
'added_indexes' => array(),
|
'added_indexes' => array(),
|
||||||
'removed_indexes' => array());
|
'removed_indexes' => array());
|
||||||
|
|
||||||
static public function migration($directory, $from, $to)
|
static public function setCurrentVersion($number)
|
||||||
|
{
|
||||||
|
$conn = Doctrine_Manager::connection();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn->export->createTable('migration_version', array('version' => array('type' => 'integer', 'size' => 11)));
|
||||||
|
} catch(Exception $e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$current = self::getCurrentVersion();
|
||||||
|
|
||||||
|
if (!$current) {
|
||||||
|
$conn->exec("INSERT INTO migration_version (version) VALUES ($number)");
|
||||||
|
} else {
|
||||||
|
$conn->exec("UPDATE migration_version SET version = $number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function getCurrentVersion()
|
||||||
|
{
|
||||||
|
$conn = Doctrine_Manager::connection();
|
||||||
|
|
||||||
|
$result = $conn->fetchColumn("SELECT version FROM migration_version");
|
||||||
|
|
||||||
|
return isset($result[0]) ? $result[0]:false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function migration($from, $to)
|
||||||
{
|
{
|
||||||
if ($from === $to || $from === 0) {
|
if ($from === $to || $from === 0) {
|
||||||
throw new Doctrine_Migration_Exception('You specified an invalid migration path. The from and to cannot be the same and from cannot be zero.');
|
throw new Doctrine_Migration_Exception('You specified an invalid migration path. The from and to cannot be the same and from cannot be zero.');
|
||||||
@ -53,29 +81,80 @@ class Doctrine_Migration
|
|||||||
|
|
||||||
if ($direction === 'up') {
|
if ($direction === 'up') {
|
||||||
for ($i = $from + 1; $i <= $to; $i++) {
|
for ($i = $from + 1; $i <= $to; $i++) {
|
||||||
self::doDirectionStep($directory, $direction, $i);
|
self::doDirectionStep($direction, $i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for ($i = $from; $i > $to; $i--) {
|
for ($i = $from; $i > $to; $i--) {
|
||||||
self::doDirectionStep($directory, $direction, $i);
|
self::doDirectionStep($direction, $i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self::setCurrentVersion($to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function doDirectionStep($direction, $num)
|
||||||
|
{
|
||||||
|
$className = 'Migration' . $num;
|
||||||
|
|
||||||
|
if (class_exists($className)) {
|
||||||
|
$migrate = new $className();
|
||||||
|
$migrate->migrate($direction);
|
||||||
|
} else {
|
||||||
|
throw new Doctrine_Migration_Exception('Could not find migration class: ' . $className);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function doDirectionStep($directory, $direction, $num)
|
public static function loadMigrationClasses($directory)
|
||||||
{
|
{
|
||||||
$className = 'Migration' . $num;
|
$classes = get_declared_classes();
|
||||||
$fileName = $className . '.class.php';
|
|
||||||
$filePath = $directory . DIRECTORY_SEPARATOR . $fileName;
|
if ($directory !== null) {
|
||||||
|
foreach ((array) $directory as $dir) {
|
||||||
if (file_exists($filePath)) {
|
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir),
|
||||||
require_once($filePath);
|
RecursiveIteratorIterator::LEAVES_ONLY);
|
||||||
|
|
||||||
if (class_exists($className)) {
|
foreach ($it as $file) {
|
||||||
$migrate = new $className();
|
$e = explode('.', $file->getFileName());
|
||||||
$migrate->migrate($direction);
|
if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false) {
|
||||||
|
require_once $file->getPathName();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$classes = array_diff(get_declared_classes(), $classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return self::getLoadedMigrationClasses($classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getLoadedMigrationClasses($classes = null)
|
||||||
|
{
|
||||||
|
if ($classes === null) {
|
||||||
|
$classes = get_declared_classes();
|
||||||
|
}
|
||||||
|
|
||||||
|
$parent = new ReflectionClass('Doctrine_Migration');
|
||||||
|
$loadedClasses = array();
|
||||||
|
|
||||||
|
foreach ($classes as $name) {
|
||||||
|
$class = new ReflectionClass($name);
|
||||||
|
|
||||||
|
while ($class->isSubclassOf($parent)) {
|
||||||
|
|
||||||
|
$class = $class->getParentClass();
|
||||||
|
if ($class === false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($class === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$loadedClasses[] = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $loadedClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function migrate($direction)
|
public function migrate($direction)
|
||||||
|
@ -37,7 +37,7 @@ class Doctrine_Migration_Process
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function processCreatedTables($tables)
|
public function processCreatedTables($tables)
|
||||||
{
|
{
|
||||||
foreach ($tables as $table) {
|
foreach ($tables as $table) {
|
||||||
$conn = $this->getConnection($table['tableName']);
|
$conn = $this->getConnection($table['tableName']);
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ class Doctrine_Migration_Process
|
|||||||
$options = $column['options'];
|
$options = $column['options'];
|
||||||
$options['type'] = $column['type'];
|
$options['type'] = $column['type'];
|
||||||
|
|
||||||
$conn->export->alterTable($column['tableName'], array('change' => array($column['oldColumnName'] => array('definition' => $options))), true);
|
$conn->export->alterTable($column['tableName'], array('change' => array($column['columnName'] => array('definition' => $options))), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once('playground.php');
|
require_once('playground.php');
|
||||||
require_once('connection.php');
|
require_once('connection.php');
|
||||||
require_once('models.php');
|
require_once('models.php');
|
||||||
|
|
||||||
Doctrine_Migration::migration('migration', 1, 3);
|
|
||||||
Doctrine_Migration::migration('migration', 3, 1);
|
|
@ -32,4 +32,64 @@
|
|||||||
*/
|
*/
|
||||||
class Doctrine_Migration_TestCase extends Doctrine_UnitTestCase
|
class Doctrine_Migration_TestCase extends Doctrine_UnitTestCase
|
||||||
{
|
{
|
||||||
|
public function testMigration()
|
||||||
|
{
|
||||||
|
// Upgrade one at a time
|
||||||
|
Doctrine_Migration::migration(1, 2);
|
||||||
|
Doctrine_Migration::migration(2, 3);
|
||||||
|
Doctrine_Migration::migration(3, 4);
|
||||||
|
|
||||||
|
// Then revert back to version 1
|
||||||
|
Doctrine_Migration::migration(4, 1);
|
||||||
|
|
||||||
|
// Check to make sure the current version is 1
|
||||||
|
$this->assertEqual(Doctrine_Migration::getCurrentVersion(), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MigrationTestTable extends Doctrine_Record
|
||||||
|
{
|
||||||
|
public function setTableDefinition()
|
||||||
|
{
|
||||||
|
$this->hasColumn('field1', 'string');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Migration2 extends Doctrine_Migration
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$this->createTable('migration_test_table', array('field1' => array('type' => 'string')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
$this->dropTable('migration_test_table');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Migration3 extends Doctrine_Migration
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$this->addColumn('migration_test_table', 'field1', 'string');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
$this->renameColumn('migration_test_table', 'field1', 'field2');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Migration4 extends Doctrine_Migration
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$this->changeColumn('migration_test_table', 'field1', 'integer');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
$this->changeColumn('migration_test_table', 'field1', 'string');
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user