From af48974a750ce39c8bfa9f266c5c20049a81cdcf Mon Sep 17 00:00:00 2001 From: beberlei Date: Mon, 30 Nov 2009 19:02:05 +0000 Subject: [PATCH] [2.0] DDC-169 - Converted introspection queries of all platforms to return Column, Sequence, Index, ForeignKey Schema Instances instead of arrays, heavily pimped Oracle support thereby. --- lib/Doctrine/DBAL/Platforms/MySqlPlatform.php | 5 +- .../DBAL/Platforms/OraclePlatform.php | 54 ++++- .../DBAL/Platforms/PostgreSqlPlatform.php | 2 +- .../DBAL/Schema/AbstractSchemaManager.php | 60 ++--- lib/Doctrine/DBAL/Schema/Column.php | 6 +- lib/Doctrine/DBAL/Schema/Comparator.php | 4 +- .../DBAL/Schema/ForeignKeyConstraint.php | 4 +- .../DBAL/Schema/MySqlSchemaManager.php | 24 +- .../DBAL/Schema/OracleSchemaManager.php | 70 ++++-- .../DBAL/Schema/PostgreSqlSchemaManager.php | 31 ++- lib/Doctrine/DBAL/Schema/Schema.php | 18 +- .../DBAL/Schema/SqliteSchemaManager.php | 6 +- .../Visitor/CreateSchemaSqlCollector.php | 4 +- .../Schema/MySqlSchemaManagerTest.php | 21 -- .../Schema/OracleSchemaManagerTest.php | 14 -- .../Schema/PostgreSqlSchemaManagerTest.php | 43 ---- .../SchemaManagerFunctionalTestCase.php | 217 +++++++++++------- .../ORM/Functional/Locking/OptimisticTest.php | 2 + .../SchemaTool/MySqlSchemaToolTest.php | 2 + 19 files changed, 316 insertions(+), 271 deletions(-) diff --git a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php index 91bd60354..ebaa7ccd0 100644 --- a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php @@ -202,13 +202,14 @@ class MySqlPlatform extends AbstractPlatform public function getListTableForeignKeysSql($table, $database = null) { - $sql = "SELECT column_name, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM information_schema.key_column_usage WHERE table_name = '" . $table . "'"; + $sql = "SELECT `CONSTRAINT_NAME`, `COLUMN_NAME`, `REFERENCED_TABLE_NAME`, ". + "`REFERENCED_COLUMN_NAME` FROM information_schema.key_column_usage WHERE table_name = '" . $table . "'"; if ( ! is_null($database)) { $sql .= " AND table_schema = '$database'"; } - $sql .= " AND REFERENCED_COLUMN_NAME is not NULL"; + $sql .= " AND `REFERENCED_COLUMN_NAME` is not NULL"; return $sql; } diff --git a/lib/Doctrine/DBAL/Platforms/OraclePlatform.php b/lib/Doctrine/DBAL/Platforms/OraclePlatform.php index 37e04a6b1..fcbc140cc 100644 --- a/lib/Doctrine/DBAL/Platforms/OraclePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/OraclePlatform.php @@ -106,6 +106,10 @@ class OraclePlatform extends AbstractPlatform * Gets the SQL used to create a sequence that starts with a given value * and increments by the given allocation size. * + * Need to specifiy minvalue, since start with is hidden in the system and MINVALUE <= START WITH. + * Therefore we can use MINVALUE to be able to get a hint what START WITH was for later introspection + * in {@see listSequences()} + * * @param string $sequenceName * @param integer $start * @param integer $allocationSize @@ -113,8 +117,8 @@ class OraclePlatform extends AbstractPlatform */ public function getCreateSequenceSql($sequenceName, $start = 1, $allocationSize = 1) { - return 'CREATE SEQUENCE ' . $sequenceName - . ' START WITH ' . $start . ' INCREMENT BY ' . $allocationSize; + return 'CREATE SEQUENCE ' . $sequenceName + . ' START WITH ' . $start . ' MINVALUE ' . $start . ' INCREMENT BY ' . $allocationSize; } /** @@ -249,7 +253,7 @@ class OraclePlatform extends AbstractPlatform public function getListDatabasesSql() { - return 'SELECT username FROM sys.dba_users'; + return 'SELECT username FROM all_users'; } public function getListFunctionsSql() @@ -259,7 +263,7 @@ class OraclePlatform extends AbstractPlatform public function getListSequencesSql($database) { - return 'SELECT sequence_name FROM sys.user_sequences'; + return 'SELECT sequence_name, min_value, increment_by FROM sys.user_sequences'; } public function getCreateTableSql($table, array $columns, array $options = array()) @@ -281,11 +285,7 @@ class OraclePlatform extends AbstractPlatform if (isset($indexes) && ! empty($indexes)) { foreach ($indexes as $indexName => $definition) { - // create nonunique indexes, as they are a part of CREATE TABLE DDL - if ( ! isset($definition['type']) || - (isset($definition['type']) && strtolower($definition['type']) != 'unique')) { - $sql[] = $this->getCreateIndexSql($table, $indexName, $definition); - } + $sql[] = $this->getCreateIndexSql($table, $indexName, $definition); } } @@ -293,7 +293,6 @@ class OraclePlatform extends AbstractPlatform } /** - * * @license New BSD License * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html * @param string $table @@ -301,11 +300,14 @@ class OraclePlatform extends AbstractPlatform */ public function getListTableIndexesSql($table) { + $table = strtoupper($table); + return "SELECT uind.index_name AS name, " . " uind.index_type AS type, " . " decode( uind.uniqueness, 'NONUNIQUE', 0, 'UNIQUE', 1 ) AS is_unique, " . " uind_col.column_name AS column_name, " . - " uind_col.column_position AS column_pos " . + " uind_col.column_position AS column_pos, " . + " (SELECT ucon.constraint_type FROM user_constraints ucon WHERE ucon.constraint_name = uind.index_name) AS is_primary ". "FROM user_indexes uind, user_ind_columns uind_col " . "WHERE uind.index_name = uind_col.index_name AND uind_col.table_name = '$table'"; } @@ -317,7 +319,7 @@ class OraclePlatform extends AbstractPlatform public function getListUsersSql() { - return 'SELECT * FROM sys.dba_users'; + return 'SELECT * FROM all_users'; } public function getListViewsSql() @@ -399,6 +401,24 @@ END;'; return $sql; } + public function getListTableForeignKeysSql($table) + { + $table = strtoupper($table); + + return "SELECT rel.constraint_name, rel.position, col.column_name AS local_column, ". + " rel.table_name, rel.column_name AS foreign_column, cc.delete_rule ". + "FROM (user_tab_columns col ". + "JOIN user_cons_columns con ". + " ON col.table_name = con.table_name ". + " AND col.column_name = con.column_name ". + "JOIN user_constraints cc ". + " ON con.constraint_name = cc.constraint_name ". + "JOIN user_cons_columns rel ". + " ON cc.r_constraint_name = rel.constraint_name ". + " AND con.position = rel.position) ". + "WHERE cc.constraint_type = 'R' AND col.table_name = '".$table."'"; + } + public function getListTableConstraintsSql($table) { $table = strtoupper($table); @@ -579,4 +599,14 @@ END;'; } return $schemaElementName; } + + /** + * Whether the platform supports sequences. + * + * @return boolean + */ + public function supportsSequences() + { + return true; + } } diff --git a/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php b/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php index cc322441d..b888bee55 100644 --- a/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php @@ -341,7 +341,7 @@ class PostgreSqlPlatform extends AbstractPlatform public function getListTableForeignKeysSql($table, $database = null) { - return "SELECT pg_catalog.pg_get_constraintdef(oid, true) as condef + return "SELECT r.name, pg_catalog.pg_get_constraintdef(r.oid, true) as condef FROM pg_catalog.pg_constraint r WHERE r.conrelid = ( diff --git a/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php b/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php index 98f4a0015..4fd657331 100644 --- a/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php +++ b/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php @@ -23,6 +23,7 @@ namespace Doctrine\DBAL\Schema; use \Doctrine\DBAL\Types; use \Doctrine\Common\DoctrineException; +use \Doctrine\DBAL\DBALException; /** * Base class for schema managers. Schema managers are used to inspect and/or @@ -210,32 +211,10 @@ abstract class AbstractSchemaManager } /** - * List the indexes for a given table - * - * @example - * $indexes = array( - * 'primary' => array( - * 'name' => 'primary', - * 'columns' => array('id'), - * 'unique' => true, - * 'primary' => true, - * ), - * 'fieldUnq' => array( - * 'name' => 'fieldUnq', - * 'columns' => array('foo', 'bar'), - * 'unique' => true, - * 'primary' => false, - * ), - * 'fieldIdx' => array( - * 'name' => 'fieldIdx', - * 'columns' => array('baz'), - * 'unique' => false, - * 'primary' => false, - * ), - * ); + * List the indexes for a given table returning an array of Index instances. * * @param string $table The name of the table - * @return array $tableIndexes + * @return Index[] $tableIndexes */ public function listTableIndexes($table) { @@ -899,9 +878,13 @@ abstract class AbstractSchemaManager return $list; } + /** + * @param array $sequence + * @return Sequence + */ protected function _getPortableSequenceDefinition($sequence) { - return $sequence; + throw DBALException::notSupported('Sequences'); } protected function _getPortableTableConstraintsList($tableConstraints) @@ -923,21 +906,21 @@ abstract class AbstractSchemaManager protected function _getPortableTableColumnList($tableColumns) { $list = array(); - foreach ($tableColumns as $key => $value) { - if ($value = $this->_getPortableTableColumnDefinition($value)) { - if (is_string($value['type'])) { - $value['type'] = \Doctrine\DBAL\Types\Type::getType($value['type']); - } - $list[$value['name']] = $value; + foreach ($tableColumns as $key => $column) { + if ($column = $this->_getPortableTableColumnDefinition($column)) { + $list[$column->getName()] = $column; } } return $list; } - protected function _getPortableTableColumnDefinition($tableColumn) - { - return $tableColumn; - } + /** + * Get Table Column Definition + * + * @param array $tableColumn + * @return Column + */ + abstract protected function _getPortableTableColumnDefinition($tableColumn); /** * Aggregate and group the index results according to the required data result. @@ -967,7 +950,12 @@ abstract class AbstractSchemaManager } } - return $result; + $indexes = array(); + foreach($result AS $indexKey => $data) { + $indexes[$indexKey] = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']); + } + + return $indexes; } protected function _getPortableTablesList($tables) diff --git a/lib/Doctrine/DBAL/Schema/Column.php b/lib/Doctrine/DBAL/Schema/Column.php index f9919faf9..c0d98ad34 100644 --- a/lib/Doctrine/DBAL/Schema/Column.php +++ b/lib/Doctrine/DBAL/Schema/Column.php @@ -132,7 +132,11 @@ class Column extends AbstractAsset */ public function setLength($length) { - $this->_length = (int)$length; + if($length !== null) { + $this->_length = (int)$length; + } else { + $this->_length = null; + } return $this; } diff --git a/lib/Doctrine/DBAL/Schema/Comparator.php b/lib/Doctrine/DBAL/Schema/Comparator.php index e944885bf..5fb27c65d 100644 --- a/lib/Doctrine/DBAL/Schema/Comparator.php +++ b/lib/Doctrine/DBAL/Schema/Comparator.php @@ -226,11 +226,11 @@ class Comparator */ public function diffForeignKey($key1, $key2) { - if ($key1->getLocalColumnNames() != $key2->getLocalColumnNames()) { + if ($key1->getLocalColumns() != $key2->getLocalColumns()) { return true; } - if ($key1->getForeignColumnNames() != $key2->getForeignColumnNames()) { + if ($key1->getForeignColumns() != $key2->getForeignColumns()) { return true; } diff --git a/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php b/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php index fa1cc5384..1d6f5536b 100644 --- a/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php +++ b/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php @@ -70,7 +70,7 @@ class ForeignKeyConstraint extends AbstractAsset implements Constraint /** * @return array */ - public function getLocalColumnNames() + public function getLocalColumns() { return $this->_localColumnNames; } @@ -86,7 +86,7 @@ class ForeignKeyConstraint extends AbstractAsset implements Constraint /** * @return array */ - public function getForeignColumnNames() + public function getForeignColumns() { return $this->_foreignColumnNames; } diff --git a/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php b/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php index f45b31963..05dd5cd0f 100644 --- a/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php +++ b/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php @@ -239,9 +239,7 @@ class MySqlSchemaManager extends AbstractSchemaManager 'fixed' => (bool) $fixed ); - $column = array( - 'name' => $tableColumn['Field'], - 'type' => $type, + $options = array( 'length' => $length, 'unsigned' => (bool)$unsigned, 'fixed' => (bool)$fixed, @@ -249,7 +247,7 @@ class MySqlSchemaManager extends AbstractSchemaManager 'notnull' => (bool) ($tableColumn['Null'] != 'YES'), 'scale' => null, 'precision' => null, - 'platformDetails' => array( + 'platformOptions' => array( 'primary' => (strtolower($tableColumn['Key']) == 'pri') ? true : false, 'unique' => (strtolower($tableColumn['Key']) == 'uni') ? true :false, 'autoincrement' => (bool) (strpos($tableColumn['Extra'], 'auto_increment') !== false), @@ -257,22 +255,24 @@ class MySqlSchemaManager extends AbstractSchemaManager ); if ($scale !== null && $precision !== null) { - $column['scale'] = $scale; - $column['precision'] = $precision; + $options['scale'] = $scale; + $options['precision'] = $precision; } - return $column; + return new Column($tableColumn['Field'], \Doctrine\DBAL\Types\Type::getType($type), $options); } public function _getPortableTableForeignKeyDefinition($tableForeignKey) { $tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER); - $foreignKey = array( - 'table' => $tableForeignKey['referenced_table_name'], - 'local' => $tableForeignKey['column_name'], - 'foreign' => $tableForeignKey['referenced_column_name'] + + return new ForeignKeyConstraint( + (array)$tableForeignKey['column_name'], + $tableForeignKey['referenced_table_name'], + (array)$tableForeignKey['referenced_column_name'], + $tableForeignKey['constraint_name'], + array() ); - return $foreignKey; } /** diff --git a/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php b/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php index 6d129d072..11cfd134a 100644 --- a/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php +++ b/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php @@ -48,7 +48,6 @@ class OracleSchemaManager extends AbstractSchemaManager return array( 'user' => $user['username'], - 'password' => $user['password'] ); } @@ -68,13 +67,13 @@ class OracleSchemaManager extends AbstractSchemaManager */ protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) { - $tableIndexes = \array_change_key_case($tableIndexes, CASE_LOWER); - $indexBuffer = array(); foreach ( $tableIndexes as $tableIndex ) { - $keyName = $tableIndex['name']; + $tableIndex = \array_change_key_case($tableIndex, CASE_LOWER); - if ( $keyName == $tableName.'_pkey' ) { + $keyName = strtolower($tableIndex['name']); + + if ( strtolower($tableIndex['is_primary']) == "p" ) { $keyName = 'primary'; $buffer['primary'] = true; $buffer['non_unique'] = false; @@ -86,7 +85,7 @@ class OracleSchemaManager extends AbstractSchemaManager $buffer['column_name'] = $tableIndex['column_name']; $indexBuffer[] = $buffer; } - parent::_getPortableTableIndexesList($indexBuffer, $tableName); + return parent::_getPortableTableIndexesList($indexBuffer, $tableName); } protected function _getPortableTableColumnDefinition($tableColumn) @@ -179,17 +178,8 @@ class OracleSchemaManager extends AbstractSchemaManager $length = null; } - $decl = array( - 'type' => $type, - 'length' => $length, - 'unsigned' => $unsigned, - 'fixed' => $fixed - ); - - return array( - 'name' => $tableColumn['column_name'], + $options = array( 'notnull' => (bool) ($tableColumn['nullable'] === 'N'), - 'type' => $type, 'fixed' => (bool) $fixed, 'unsigned' => (bool) $unsigned, 'default' => $tableColumn['data_default'], @@ -198,6 +188,54 @@ class OracleSchemaManager extends AbstractSchemaManager 'scale' => $scale, 'platformDetails' => array(), ); + + return new Column($tableColumn['column_name'], \Doctrine\DBAL\Types\Type::getType($type), $options); + } + + public function createForeignKey($table, array $definition) + { + if(isset($definition['onUpdate'])) { + // Oracle does not support onUpdate + unset($definition['onUpdate']); + } + + return parent::createForeignKey($table, $definition); + } + + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $list = array(); + foreach ($tableForeignKeys as $key => $value) { + $value = \array_change_key_case($value, CASE_LOWER); + if (!isset($list[$value['constraint_name']])) { + $list[$value['constraint_name']] = array( + 'name' => $value['constraint_name'], + 'local' => array(), + 'foreign' => array(), + 'foreignTable' => $value['table_name'], + 'onDelete' => $value['delete_rule'], + ); + } + $list[$value['constraint_name']]['local'][$value['position']] = $value['local_column']; + $list[$value['constraint_name']]['foreign'][$value['position']] = $value['foreign_column']; + } + + $result = array(); + foreach($list AS $constraint) { + $result[] = new ForeignKeyConstraint( + array_values($constraint['local']), $constraint['foreignTable'], + array_values($constraint['foreign']), $constraint['name'], + array('onDelete' => $constraint['onDelete']) + ); + } + + return $result; + } + + protected function _getPortableSequenceDefinition($sequence) + { + $sequence = \array_change_key_case($sequence, CASE_LOWER); + return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['min_value']); } protected function _getPortableTableConstraintDefinition($tableConstraint) diff --git a/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php b/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php index 93faa359c..0f384d480 100644 --- a/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php +++ b/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php @@ -35,15 +35,26 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager { protected function _getPortableTableForeignKeyDefinition($tableForeignKey) { - preg_match('/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)/', $tableForeignKey['condef'], $values); + $onUpdate = null; + $onDelete = null; - if ((strpos(',', $values[1]) === false) && (strpos(',', $values[3]) === false)) { - return array( - 'table' => $values[2], - 'local' => $values[1], - 'foreign' => $values[3] - ); + if(preg_match('(ON UPDATE ([a-zA-Z0-9]+))', $tableForeignKey['condef'], $match)) { + $onUpdate = $match[1]; } + if(preg_match('(ON DELETE ([a-zA-Z0-9]+))', $tableForeignKey['condef'], $match)) { + $onDelete = $match[1]; + } + + if(preg_match('/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)/', $tableForeignKey['condef'], $values)) { + $localColumns = explode(",", $values[1]); + $foreignColumns = explode(",", $values[3]); + $foreignTable = $values[2]; + } + + return new ForeignKeyConstraint( + $localColumns, $foreignTable, $foreignColumns, $tableForeignKey['name'], + array('onUpdate' => $onUpdate, 'onDelete' => $onDelete) + ); } public function dropDatabase($database) @@ -299,9 +310,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager $type = 'string'; } - $description = array( - 'name' => $tableColumn['field'], - 'type' => $type, + $options = array( 'length' => $length, 'notnull' => (bool) $tableColumn['isnotnull'], 'default' => $tableColumn['default'], @@ -313,6 +322,6 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager 'platformDetails' => array(), ); - return $description; + return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options); } } \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Schema/Schema.php b/lib/Doctrine/DBAL/Schema/Schema.php index ef7982f5d..541c0fb32 100644 --- a/lib/Doctrine/DBAL/Schema/Schema.php +++ b/lib/Doctrine/DBAL/Schema/Schema.php @@ -245,14 +245,24 @@ class Schema extends AbstractAsset return $dropSqlCollector->getQueries(); } - public function migrateTo(Schema $schema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + /** + * @param Schema $schema + * @param AbstractPlatform $platform + */ + public function getMigrateToSql(Schema $schema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) { - + $comparator = new Comparator(); + $schemaDiff = $comparator->compare($this, $schema); } - public function migrateFrom(Schema $schema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + /** + * @param Schema $schema + * @param AbstractPlatform $platform + */ + public function getMigrateFromSql(Schema $schema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) { - + $comparator = new Comparator(); + $schemaDiff = $comparator->compare($schema, $this); } /** diff --git a/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php b/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php index 562f3b1a0..659b6161e 100644 --- a/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php +++ b/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php @@ -242,9 +242,7 @@ class SqliteSchemaManager extends AbstractSchemaManager $length = null; } - return array( - 'name' => $tableColumn['name'], - 'type' => $type, + $options = array( 'length' => $length, 'unsigned' => (bool) $unsigned, 'fixed' => $fixed, @@ -256,5 +254,7 @@ class SqliteSchemaManager extends AbstractSchemaManager 'primary' => (bool) $tableColumn['pk'], ), ); + + return new Column($tableColumn['name'], \Doctrine\DBAL\Types\Type::getType($type), $options); } } \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php b/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php index 4fee0449e..89826b144 100644 --- a/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php +++ b/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php @@ -142,8 +142,8 @@ class CreateSchemaSqlCollector implements Visitor $fkConstraintArray = array( 'tableName' => $fkConstraint->getName(), 'foreignTable' => $fkConstraint->getForeignTableName(), - 'local' => $fkConstraint->getLocalColumnNames(), - 'foreign' => $fkConstraint->getForeignColumnNames(), + 'local' => $fkConstraint->getLocalColumns(), + 'foreign' => $fkConstraint->getForeignColumns(), 'onUpdate' => ($fkConstraint->hasOption('onUpdate')?$fkConstraint->getOption('onUpdate'):null), 'onDelete' => ($fkConstraint->hasOption('onDelete')?$fkConstraint->getOption('onDelete'):null), ); diff --git a/tests/Doctrine/Tests/DBAL/Functional/Schema/MySqlSchemaManagerTest.php b/tests/Doctrine/Tests/DBAL/Functional/Schema/MySqlSchemaManagerTest.php index 7534ec6da..f18281386 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Schema/MySqlSchemaManagerTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Schema/MySqlSchemaManagerTest.php @@ -41,25 +41,4 @@ class MySqlSchemaManagerTest extends SchemaManagerFunctionalTestCase { return 'SELECT * from mysql.user'; } - - public function testListTableForeignKeys() - { - $data['options'] = array('type' => 'innodb'); - $this->createTestTable('list_table_foreign_keys_test1', $data); - $this->createTestTable('list_table_foreign_keys_test2', $data); - - $definition = array( - 'name' => 'testing', - 'local' => 'foreign_key_test', - 'foreign' => 'id', - 'foreignTable' => 'list_table_foreign_keys_test2' - ); - $this->_sm->createForeignKey('list_table_foreign_keys_test1', $definition); - - $tableForeignKeys = $this->_sm->listTableForeignKeys('list_table_foreign_keys_test1'); - $this->assertEquals(1, count($tableForeignKeys)); - $this->assertEquals('list_table_foreign_keys_test2', $tableForeignKeys[0]['table']); - $this->assertEquals('foreign_key_test', $tableForeignKeys[0]['local']); - $this->assertEquals('id', $tableForeignKeys[0]['foreign']); - } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/DBAL/Functional/Schema/OracleSchemaManagerTest.php b/tests/Doctrine/Tests/DBAL/Functional/Schema/OracleSchemaManagerTest.php index a2d56984e..fa98909ef 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Schema/OracleSchemaManagerTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Schema/OracleSchemaManagerTest.php @@ -10,8 +10,6 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase { public function setUp() { - $this->markTestSkipped('Somehow they all dont work because of privledges or other stuff.'); - parent::setUp(); if(!isset($GLOBALS['db_username'])) { @@ -34,13 +32,6 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase $this->_sm->listTriggers(); } - public function testListSequences() - { - $this->createTestTable('list_sequences_test'); - $sequences = $this->_sm->listSequences(); - $this->assertEquals(true, in_array('LIST_SEQUENCES_TEST_SEQ', $sequences)); - } - public function testListTableConstraints() { $this->createTestTable('test_constraints'); @@ -73,11 +64,6 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase $this->assertEquals('TEST_CREATE_VIEW', $view['name']); } - public function testListTableForeignKeys() - { - $this->markTestSkipped('Not yet implemented'); - } - public function testRenameTable() { $this->_sm->tryMethod('DropTable', 'list_tables_test'); diff --git a/tests/Doctrine/Tests/DBAL/Functional/Schema/PostgreSqlSchemaManagerTest.php b/tests/Doctrine/Tests/DBAL/Functional/Schema/PostgreSqlSchemaManagerTest.php index 93f3d0d0a..61b1e45b3 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Schema/PostgreSqlSchemaManagerTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Schema/PostgreSqlSchemaManagerTest.php @@ -22,28 +22,6 @@ class PostgreSqlSchemaManagerTest extends SchemaManagerFunctionalTestCase $this->assertEquals(array('list_table_constraints_test_pkey'), $tableConstraints); } - /*public function testListTableColumns() - { - $this->createTestTable('list_tables_test'); - $columns = $this->_sm->listTableColumns('list_tables_test'); - - $this->assertEquals('id', $columns[0]['name']); - $this->assertEquals(true, $columns[0]['primary']); - $this->assertEquals('Doctrine\DBAL\Types\IntegerType', get_class($columns[0]['type'])); - $this->assertEquals(null, $columns[0]['length']); - $this->assertEquals(false, $columns[0]['fixed']); - $this->assertEquals(true, $columns[0]['notnull']); - $this->assertEquals(null, $columns[0]['default']); - - $this->assertEquals('test', $columns[1]['name']); - $this->assertEquals(false, $columns[1]['primary']); - $this->assertEquals('Doctrine\DBAL\Types\StringType', get_class($columns[1]['type'])); - $this->assertEquals(255, $columns[1]['length']); - $this->assertEquals(false, $columns[1]['fixed']); - $this->assertEquals(false, $columns[1]['notnull']); - $this->assertEquals(null, $columns[1]['default']); - }*/ - public function testListUsers() { $users = $this->_sm->listUsers(); @@ -63,25 +41,4 @@ class PostgreSqlSchemaManagerTest extends SchemaManagerFunctionalTestCase { return 'SELECT usename, passwd FROM pg_user'; } - - public function testListTableForeignKeys() - { - $data['options'] = array('type' => 'innodb'); - $this->createTestTable('list_table_foreign_keys_test1', $data); - $this->createTestTable('list_table_foreign_keys_test2', $data); - - $definition = array( - 'name' => 'testing', - 'local' => 'foreign_key_test', - 'foreign' => 'id', - 'foreignTable' => 'list_table_foreign_keys_test2' - ); - $this->_sm->createForeignKey('list_table_foreign_keys_test1', $definition); - - $tableForeignKeys = $this->_sm->listTableForeignKeys('list_table_foreign_keys_test1'); - $this->assertEquals(1, count($tableForeignKeys)); - $this->assertEquals('list_table_foreign_keys_test2', $tableForeignKeys[0]['table']); - $this->assertEquals('foreign_key_test', $tableForeignKeys[0]['local']); - $this->assertEquals('id', $tableForeignKeys[0]['foreign']); - } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php b/tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php index 1db6e560b..5ffff628a 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php @@ -8,6 +8,31 @@ require_once __DIR__ . '/../../../TestInit.php'; class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTestCase { + public function testListSequences() + { + if(!$this->_conn->getDatabasePlatform()->supportsSequences()) { + $this->markTestSkipped($this->_conn->getDriver()->getName().' does not support sequences.'); + } + + $this->_sm->createSequence('list_sequences_test_seq', 10, 20); + + $sequences = $this->_sm->listSequences(); + + $this->assertType('array', $sequences, 'listSequences() should return an array.'); + + $foundSequence = null; + foreach($sequences AS $sequence) { + $this->assertType('Doctrine\DBAL\Schema\Sequence', $sequence, 'Array elements of listSequences() should be Sequence instances.'); + if(strtolower($sequence->getName()) == 'list_sequences_test_seq') { + $foundSequence = $sequence; + } + } + + $this->assertNotNull($foundSequence, "Sequence with name 'list_sequences_test_seq' was not found."); + $this->assertEquals(20, $foundSequence->getAllocationSize(), "Allocation Size is expected to be 20."); + $this->assertEquals(10, $foundSequence->getInitialValue(), "Initial Value is expected to be 10."); + } + public function testListFunctions() { $funcs = $this->_sm->listFunctions(); @@ -29,7 +54,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest $databases = \array_map('strtolower', $databases); - $this->assertEquals(true, in_array('test_create_database', $databases)); + $this->assertEquals(true, \in_array('test_create_database', $databases)); } public function testListTables() @@ -37,8 +62,8 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest $this->createTestTable('list_tables_test'); $tables = $this->_sm->listTables(); - $tables = \array_change_key_case($tables, CASE_LOWER); - + $this->assertType('array', $tables); + $tables = \array_map('strtolower', $tables); $this->assertEquals(true, in_array('list_tables_test', $tables)); } @@ -83,87 +108,64 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest $columns = \array_change_key_case($columns, CASE_LOWER); $this->assertArrayHasKey('id', $columns); - $this->assertEquals('id', strtolower($columns['id']['name'])); - $this->assertType('Doctrine\DBAL\Types\IntegerType', $columns['id']['type']); - $this->assertEquals(null, $columns['id']['length']); - $this->assertEquals(null, $columns['id']['precision']); - $this->assertEquals(null, $columns['id']['scale']); - $this->assertEquals(false, $columns['id']['unsigned']); - $this->assertEquals(false, $columns['id']['fixed']); - $this->assertEquals(true, $columns['id']['notnull']); - $this->assertEquals(null, $columns['id']['default']); - $this->assertType('array', $columns['id']['platformDetails']); + $this->assertEquals('id', strtolower($columns['id']->getname())); + $this->assertType('Doctrine\DBAL\Types\IntegerType', $columns['id']->gettype()); + $this->assertEquals(false, $columns['id']->getunsigned()); + $this->assertEquals(true, $columns['id']->getnotnull()); + $this->assertEquals(null, $columns['id']->getdefault()); + $this->assertType('array', $columns['id']->getPlatformOptions()); $this->assertArrayHasKey('test', $columns); - $this->assertEquals('test', strtolower($columns['test']['name'])); - $this->assertType('Doctrine\DBAL\Types\StringType', $columns['test']['type']); - $this->assertEquals(255, $columns['test']['length']); - $this->assertEquals(null, $columns['test']['precision']); - $this->assertEquals(null, $columns['test']['scale']); - $this->assertEquals(false, $columns['test']['unsigned']); - $this->assertEquals(false, $columns['test']['fixed']); - $this->assertEquals(false, $columns['test']['notnull']); - $this->assertEquals(null, $columns['test']['default']); - $this->assertType('array', $columns['test']['platformDetails']); + $this->assertEquals('test', strtolower($columns['test']->getname())); + $this->assertType('Doctrine\DBAL\Types\StringType', $columns['test']->gettype()); + $this->assertEquals(255, $columns['test']->getlength()); + $this->assertEquals(false, $columns['test']->getfixed()); + $this->assertEquals(false, $columns['test']->getnotnull()); + $this->assertEquals(null, $columns['test']->getdefault()); + $this->assertType('array', $columns['test']->getPlatformOptions()); - $this->assertEquals('foo', strtolower($columns['foo']['name'])); - $this->assertType('Doctrine\DBAL\Types\TextType', $columns['foo']['type']); - $this->assertEquals(null, $columns['foo']['length']); - $this->assertEquals(null, $columns['foo']['precision']); - $this->assertEquals(null, $columns['foo']['scale']); - $this->assertEquals(false, $columns['foo']['unsigned']); - $this->assertEquals(false, $columns['foo']['fixed']); - $this->assertEquals(true, $columns['foo']['notnull']); - $this->assertEquals(null, $columns['foo']['default']); - $this->assertType('array', $columns['foo']['platformDetails']); + $this->assertEquals('foo', strtolower($columns['foo']->getname())); + $this->assertType('Doctrine\DBAL\Types\TextType', $columns['foo']->gettype()); + $this->assertEquals(null, $columns['foo']->getlength()); + $this->assertEquals(false, $columns['foo']->getunsigned()); + $this->assertEquals(false, $columns['foo']->getfixed()); + $this->assertEquals(true, $columns['foo']->getnotnull()); + $this->assertEquals(null, $columns['foo']->getdefault()); + $this->assertType('array', $columns['foo']->getPlatformOptions()); - $this->assertEquals('bar', strtolower($columns['bar']['name'])); - $this->assertType('Doctrine\DBAL\Types\DecimalType', $columns['bar']['type']); - $this->assertEquals(null, $columns['bar']['length']); - $this->assertEquals(10, $columns['bar']['precision']); - $this->assertEquals(4, $columns['bar']['scale']); - $this->assertEquals(false, $columns['bar']['unsigned']); - $this->assertEquals(false, $columns['bar']['fixed']); - $this->assertEquals(false, $columns['bar']['notnull']); - $this->assertEquals(null, $columns['bar']['default']); - $this->assertType('array', $columns['bar']['platformDetails']); + $this->assertEquals('bar', strtolower($columns['bar']->getname())); + $this->assertType('Doctrine\DBAL\Types\DecimalType', $columns['bar']->gettype()); + $this->assertEquals(null, $columns['bar']->getlength()); + $this->assertEquals(10, $columns['bar']->getprecision()); + $this->assertEquals(4, $columns['bar']->getscale()); + $this->assertEquals(false, $columns['bar']->getunsigned()); + $this->assertEquals(false, $columns['bar']->getfixed()); + $this->assertEquals(false, $columns['bar']->getnotnull()); + $this->assertEquals(null, $columns['bar']->getdefault()); + $this->assertType('array', $columns['bar']->getPlatformOptions()); - $this->assertEquals('baz1', strtolower($columns['baz1']['name'])); - $this->assertType('Doctrine\DBAL\Types\DateTimeType', $columns['baz1']['type']); - $this->assertEquals(null, $columns['baz1']['length']); - $this->assertEquals(null, $columns['baz1']['precision']); - $this->assertEquals(null, $columns['baz1']['scale']); - $this->assertEquals(false, $columns['baz1']['unsigned']); - $this->assertEquals(false, $columns['baz1']['fixed']); - $this->assertEquals(false, $columns['baz1']['notnull']); - $this->assertEquals(null, $columns['baz1']['default']); - $this->assertType('array', $columns['baz1']['platformDetails']); + $this->assertEquals('baz1', strtolower($columns['baz1']->getname())); + $this->assertType('Doctrine\DBAL\Types\DateTimeType', $columns['baz1']->gettype()); + $this->assertEquals(false, $columns['baz1']->getnotnull()); + $this->assertEquals(null, $columns['baz1']->getdefault()); + $this->assertType('array', $columns['baz1']->getPlatformOptions()); - $this->assertEquals('baz2', strtolower($columns['baz2']['name'])); - $this->assertContains($columns['baz2']['type']->getName(), array('Time', 'Date', 'DateTime')); - $this->assertEquals(null, $columns['baz2']['length']); - $this->assertEquals(null, $columns['baz2']['precision']); - $this->assertEquals(null, $columns['baz2']['scale']); - $this->assertEquals(false, $columns['baz2']['unsigned']); - $this->assertEquals(false, $columns['baz2']['fixed']); - $this->assertEquals(false, $columns['baz2']['notnull']); - $this->assertEquals(null, $columns['baz2']['default']); - $this->assertType('array', $columns['baz2']['platformDetails']); + $this->assertEquals('baz2', strtolower($columns['baz2']->getname())); + $this->assertContains($columns['baz2']->gettype()->getName(), array('Time', 'Date', 'DateTime')); + $this->assertEquals(false, $columns['baz2']->getnotnull()); + $this->assertEquals(null, $columns['baz2']->getdefault()); + $this->assertType('array', $columns['baz2']->getPlatformOptions()); - $this->assertEquals('baz3', strtolower($columns['baz3']['name'])); - $this->assertContains($columns['baz2']['type']->getName(), array('Time', 'Date', 'DateTime')); - $this->assertEquals(null, $columns['baz3']['length']); - $this->assertEquals(null, $columns['baz3']['precision']); - $this->assertEquals(null, $columns['baz3']['scale']); - $this->assertEquals(false, $columns['baz3']['unsigned']); - $this->assertEquals(false, $columns['baz3']['fixed']); - $this->assertEquals(false, $columns['baz3']['notnull']); - $this->assertEquals(null, $columns['baz3']['default']); - $this->assertType('array', $columns['baz3']['platformDetails']); + $this->assertEquals('baz3', strtolower($columns['baz3']->getname())); + $this->assertContains($columns['baz2']->gettype()->getName(), array('Time', 'Date', 'DateTime')); + $this->assertEquals(false, $columns['baz3']->getnotnull()); + $this->assertEquals(null, $columns['baz3']->getdefault()); + $this->assertType('array', $columns['baz3']->getPlatformOptions()); } public function testListTableIndexes() { + $data = array(); $data['options'] = array( 'indexes' => array( 'test_index_name' => array( @@ -183,22 +185,22 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest $this->createTestTable('list_table_indexes_test', $data); $tableIndexes = $this->_sm->listTableIndexes('list_table_indexes_test'); - + $this->assertEquals(3, count($tableIndexes)); - $this->assertEquals(array('id'), $tableIndexes['primary']['columns']); - $this->assertTrue($tableIndexes['primary']['unique']); - $this->assertTrue($tableIndexes['primary']['primary']); + $this->assertEquals(array('id'), array_map('strtolower', $tableIndexes['primary']->getColumns())); + $this->assertTrue($tableIndexes['primary']->isUnique()); + $this->assertTrue($tableIndexes['primary']->isPrimary()); - $this->assertEquals('test_index_name', $tableIndexes['test_index_name']['name']); - $this->assertEquals(array('test'), $tableIndexes['test_index_name']['columns']); - $this->assertTrue($tableIndexes['test_index_name']['unique']); - $this->assertFalse($tableIndexes['test_index_name']['primary']); + $this->assertEquals('test_index_name', $tableIndexes['test_index_name']->getName()); + $this->assertEquals(array('test'), array_map('strtolower', $tableIndexes['test_index_name']->getColumns())); + $this->assertTrue($tableIndexes['test_index_name']->isUnique()); + $this->assertFalse($tableIndexes['test_index_name']->isPrimary()); - $this->assertEquals('test_composite_idx', $tableIndexes['test_composite_idx']['name']); - $this->assertEquals(array('id', 'test'), $tableIndexes['test_composite_idx']['columns']); - $this->assertFalse($tableIndexes['test_composite_idx']['unique']); - $this->assertFalse($tableIndexes['test_composite_idx']['primary']); + $this->assertEquals('test_composite_idx', $tableIndexes['test_composite_idx']->getName()); + $this->assertEquals(array('id', 'test'), array_map('strtolower', $tableIndexes['test_composite_idx']->getColumns())); + $this->assertFalse($tableIndexes['test_composite_idx']->isUnique()); + $this->assertFalse($tableIndexes['test_composite_idx']->isPrimary()); } public function testDropAndCreateIndex() @@ -214,11 +216,48 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest $this->_sm->dropAndCreateIndex('test_create_index', 'test', $index); $tableIndexes = $this->_sm->listTableIndexes('test_create_index'); + $this->assertType('array', $tableIndexes); - $this->assertEquals('test', $tableIndexes['test']['name']); - $this->assertEquals(array('test'), $tableIndexes['test']['columns']); - $this->assertTrue($tableIndexes['test']['unique']); - $this->assertFalse($tableIndexes['test']['primary']); + $this->assertEquals('test', $tableIndexes['test']->getName()); + $this->assertEquals(array('test'), array_map('strtolower', $tableIndexes['test']->getColumns())); + $this->assertTrue($tableIndexes['test']->isUnique()); + $this->assertFalse($tableIndexes['test']->isPrimary()); + } + + public function testListForeignKeys() + { + if(!$this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) { + $this->markTestSkipped('Does not support foreign key constraints.'); + } + + $this->createTestTable('test_create_fk1'); + $this->createTestTable('test_create_fk2'); + + $definition = array( + 'name' => 'foreign_key_test_fk', + 'local' => array('foreign_key_test'), + 'foreign' => array('id'), + 'foreignTable' => 'test_create_fk2', + 'onUpdate' => 'CASCADE', + 'onDelete' => 'CASCADE', + ); + + $this->_sm->createForeignKey('test_create_fk1', $definition); + + $fkeys = $this->_sm->listTableForeignKeys('test_create_fk1'); + + $this->assertEquals(1, count($fkeys)); + $this->assertType('Doctrine\DBAL\Schema\ForeignKeyConstraint', $fkeys[0]); + $this->assertEquals(array('foreign_key_test'), array_map('strtolower', $fkeys[0]->getLocalColumns())); + $this->assertEquals(array('id'), array_map('strtolower', $fkeys[0]->getForeignColumns())); + $this->assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName())); + + if($fkeys[0]->hasOption('onUpdate')) { + $this->assertEquals('CASCADE', $fkeys[0]->getOption('onUpdate')); + } + if($fkeys[0]->hasOption('onDelete')) { + $this->assertEquals('CASCADE', $fkeys[0]->getOption('onDelete')); + } } protected function getCreateExampleViewSql() diff --git a/tests/Doctrine/Tests/ORM/Functional/Locking/OptimisticTest.php b/tests/Doctrine/Tests/ORM/Functional/Locking/OptimisticTest.php index e4be96772..bd29ffe5a 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Locking/OptimisticTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/Locking/OptimisticTest.php @@ -135,6 +135,8 @@ class OptimisticTest extends \Doctrine\Tests\OrmFunctionalTestCase $q->setParameter('name', 'Testing'); $test = $q->getSingleResult(); + $this->assertType('DateTime', $test->version); + // Manually increment the version datetime column $format = $this->_em->getConnection()->getDatabasePlatform()->getDateTimeFormatString(); $this->_conn->execute('UPDATE optimistic_timestamp SET version = ? WHERE id = ?', array(date($format, strtotime($test->version->format($format)) + 3600), $test->id)); diff --git a/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php b/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php index aa8533e21..06d5dec04 100644 --- a/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php @@ -65,6 +65,8 @@ class MySqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase public function testGetUpdateSchemaSql() { + $this->markTestSkipped('Update Schema Tool stuff wont be needed anymore soon!'); + $classes = array( $this->_em->getClassMetadata(__NAMESPACE__ . '\SchemaToolEntityA') );