Adding indexes to alterSchema() and CakeSchema::compare(). Thanks for the test case and patch 'bamyers99'. Fixes #5862

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@7910 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
mark_story 2008-12-09 04:54:58 +00:00
parent 2d9f2c5ac8
commit d405d1d1c3
3 changed files with 195 additions and 5 deletions

View file

@ -536,9 +536,14 @@ class DboMysql extends DboSource {
$out = '';
$colList = array();
foreach ($compare as $curTable => $types) {
$indexes = array();
if (!$table || $table == $curTable) {
$out .= 'ALTER TABLE ' . $this->fullTableName($curTable) . " \n";
foreach ($types as $type => $column) {
if (isset($column['indexes'])) {
$indexes[$type] = $column['indexes'];
unset($column['indexes']);
}
switch ($type) {
case 'add':
foreach ($column as $field => $col) {
@ -566,6 +571,7 @@ class DboMysql extends DboSource {
break;
}
}
$colList = array_merge($colList, $this->_alterIndexes($curTable, $indexes));
$out .= "\t" . join(",\n\t", $colList) . ";\n\n";
}
}
@ -592,5 +598,46 @@ class DboMysql extends DboSource {
}
return $out;
}
/**
* Generate MySQL index alteration statements for a table.
*
* @param string $table Table to alter indexes for
* @param array $new Indexes to add and drop
* @return array Index alteration statements
*/
function _alterIndexes($table, $indexes) {
$alter = array();
if (isset($indexes['drop'])) {
foreach($indexes['drop'] as $name => $value) {
$out = 'DROP ';
if ($name == 'PRIMARY') {
$out .= 'PRIMARY KEY';
} else {
$out .= 'KEY ' . $name;
}
$alter[] = $out;
}
}
if (isset($indexes['add'])) {
foreach ($indexes['add'] as $name => $value) {
$out = 'ADD ';
if ($name == 'PRIMARY') {
$out .= 'PRIMARY ';
$name = null;
} else {
if (!empty($value['unique'])) {
$out .= 'UNIQUE ';
}
}
if (is_array($value['column'])) {
$out .= 'KEY '. $name .' (' . join(', ', array_map(array(&$this, 'name'), $value['column'])) . ')';
} else {
$out .= 'KEY '. $name .' (' . $this->name($value['column']) . ')';
}
$alter[] = $out;
}
}
return $alter;
}
}
?>

View file

@ -407,7 +407,7 @@ class CakeSchema extends Object {
foreach ($fields as $field => $value) {
if (isset($old[$table][$field])) {
$diff = array_diff_assoc($value, $old[$table][$field]);
if (!empty($diff)) {
if (!empty($diff) && $field !== 'indexes') {
$tables[$table]['change'][$field] = array_merge($old[$table][$field], $diff);
}
}
@ -421,6 +421,14 @@ class CakeSchema extends Object {
}
}
}
if (isset($old[$table]['indexes']) && isset($new[$table]['indexes'])) {
$diff = $this->_compareIndexes($new[$table]['indexes'], $old[$table]['indexes']);
if ($diff) {
$tables[$table]['drop']['indexes'] = $diff['drop'];
$tables[$table]['add']['indexes'] = $diff['add'];
}
}
}
return $tables;
}
@ -487,5 +495,55 @@ class CakeSchema extends Object {
return $columns;
}
/**
* Compare two schema indexes
*
* @param array $new New indexes
* @param array $old Old indexes
* @return mixed false on failure or array of indexes to add and drop
*/
function _compareIndexes($new, $old) {
if (!is_array($new) || !is_array($old)) {
return false;
}
$add = $drop = array();
$diff = array_diff_assoc($new, $old);
if (!empty($diff)) {
$add = $diff;
}
$diff = array_diff_assoc($old, $new);
if (!empty($diff)) {
$drop = $diff;
}
foreach ($new as $name => $value) {
if (isset($old[$name])) {
$newUnique = isset($value['unique']) ? $value['unique'] : 0;
$oldUnique = isset($old[$name]['unique']) ? $old[$name]['unique'] : 0;
$newColumn = $value['column'];
$oldColumn = $old[$name]['column'];
$diff = false;
if ($newUnique != $oldUnique) {
$diff = true;
} elseif (is_array($newColumn) && is_array($oldColumn)) {
$diff = ($newColumn !== $oldColumn);
} elseif (is_string($newColumn) && is_string($oldColumn)) {
$diff = ($newColumn != $oldColumn);
} else {
$diff = true;
}
if ($diff) {
$drop[$name] = null;
$add[$name] = $value;
}
}
}
return array_filter(compact('add', 'drop'));
}
}
?>

View file

@ -22,10 +22,6 @@
* @lastmodified $Date$
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
if (!defined('CAKEPHP_UNIT_TEST_EXECUTION')) {
define('CAKEPHP_UNIT_TEST_EXECUTION', 1);
}
App::import('Core', array('Model', 'DataSource', 'DboSource', 'DboMysql'));
/**
@ -190,6 +186,23 @@ class DboMysqlTest extends CakeTestCase {
function tearDown() {
unset($this->db);
}
/**
* startCase
*
* @return void
**/
function startCase() {
$this->_debug = Configure::read('debug');
Configure::write('debug', 1);
}
/**
* endCase
*
* @return void
**/
function endCase() {
Configure::write('debug', $this->_debug);
}
/**
* Test Dbo value method
*
@ -395,6 +408,78 @@ class DboMysqlTest extends CakeTestCase {
$expected = 'float';
$this->assertEqual($result, $expected);
}
/**
* testAlterSchemaIndexes method
*
* @access public
* @return void
*/
function testAlterSchemaIndexes() {
App::import('Core', 'Schema');
$this->db->cacheSources = $this->db->testing = false;
$schema1 =& new CakeSchema(array(
'name' => 'AlterTest1',
'connection' => 'test_suite',
'altertest' => array(
'id' => array('type' => 'integer', 'null' => false, 'default' => 0),
'name' => array('type' => 'string', 'null' => false, 'length' => 50),
'group1' => array('type' => 'integer', 'null' => true),
'group2' => array('type' => 'integer', 'null' => true)
)));
$this->db->query($this->db->createSchema($schema1));
$schema2 =& new CakeSchema(array(
'name' => 'AlterTest2',
'connection' => 'test_suite',
'altertest' => array(
'id' => array('type' => 'integer', 'null' => false, 'default' => 0),
'name' => array('type' => 'string', 'null' => false, 'length' => 50),
'group1' => array('type' => 'integer', 'null' => true),
'group2' => array('type' => 'integer', 'null' => true),
'indexes' => array(
'name_idx' => array('column' => 'name', 'unique' => 0),
'group_idx' => array('column' => 'group1', 'unique' => 0),
'compound_idx' => array('column' => array('group1', 'group2'), 'unique' => 0),
'PRIMARY' => array('column' => 'id', 'unique' => 1))
)));
$this->db->query($this->db->alterSchema($schema2->compare($schema1)));
$indexes = $this->db->index('altertest');
$this->assertEqual($schema2->tables['altertest']['indexes'], $indexes);
// Change three indexes, delete one and add another one
$schema3 =& new CakeSchema(array(
'name' => 'AlterTest3',
'connection' => 'test_suite',
'altertest' => array(
'id' => array('type' => 'integer', 'null' => false, 'default' => 0),
'name' => array('type' => 'string', 'null' => false, 'length' => 50),
'group1' => array('type' => 'integer', 'null' => true),
'group2' => array('type' => 'integer', 'null' => true),
'indexes' => array(
'name_idx' => array('column' => 'name', 'unique' => 1),
'group_idx' => array('column' => 'group2', 'unique' => 0),
'compound_idx' => array('column' => array('group2', 'group1'), 'unique' => 0),
'id_name_idx' => array('column' => array('id', 'name'), 'unique' => 0))
)));
$this->db->query($this->db->alterSchema($schema3->compare($schema2)));
$indexes = $this->db->index('altertest');
$this->assertEqual($schema3->tables['altertest']['indexes'], $indexes);
// Compare us to ourself.
$this->assertEqual($schema3->compare($schema3), array());
// Drop the indexes
$this->db->query($this->db->alterSchema($schema1->compare($schema3)));
$indexes = $this->db->index('altertest');
$this->assertEqual(array(), $indexes);
$this->db->query($this->db->dropSchema($schema1));
}
}
?>