Commit 10bdfcb1 authored by Jonathan.Wage's avatar Jonathan.Wage

Changes for new migration code.

parent 5d12093b
...@@ -465,6 +465,8 @@ final class Doctrine ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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; ...@@ -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 ...@@ -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 ...@@ -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;
}
}
\ No newline at end of file
...@@ -43,7 +43,35 @@ class Doctrine_Migration ...@@ -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 ...@@ -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($directory, $direction, $num) public static function doDirectionStep($direction, $num)
{ {
$className = 'Migration' . $num; $className = 'Migration' . $num;
$fileName = $className . '.class.php';
$filePath = $directory . DIRECTORY_SEPARATOR . $fileName;
if (file_exists($filePath)) { if (class_exists($className)) {
require_once($filePath); $migrate = new $className();
$migrate->migrate($direction);
} else {
throw new Doctrine_Migration_Exception('Could not find migration class: ' . $className);
}
}
public static function loadMigrationClasses($directory)
{
$classes = get_declared_classes();
if ($directory !== null) {
foreach ((array) $directory as $dir) {
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir),
RecursiveIteratorIterator::LEAVES_ONLY);
foreach ($it as $file) {
$e = explode('.', $file->getFileName());
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);
if (class_exists($className)) { while ($class->isSubclassOf($parent)) {
$migrate = new $className();
$migrate->migrate($direction); $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 ...@@ -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 ...@@ -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);
} }
} }
......
<?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');
\ No newline at end of file
Doctrine_Migration::migration('migration', 1, 3);
Doctrine_Migration::migration('migration', 3, 1);
...@@ -32,4 +32,64 @@ ...@@ -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');
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment