1
0
mirror of synced 2025-02-01 04:51:45 +03:00

[2.0] DDC-91 - Enhanced SchemaManager::listTableIndexes() considerably. Add primary keys to the index list, add a bool flag primary to each index, add an array of columns to each index. Moved a test to SchemaFunctionalTestCase to check that every database (Mysql, Pgsql, Sqlite, Oracle) returns exactly the same data from this function.

This commit is contained in:
beberlei 2009-11-03 08:58:03 +00:00
parent 37824abffe
commit cfea7883e0
13 changed files with 259 additions and 145 deletions

View File

@ -25,4 +25,15 @@ Zend Framework
Doctrine contains ports of a few Zend components and has borrowed concepts and ideas from the Zend Framework project. Doctrine contains ports of a few Zend components and has borrowed concepts and ideas from the Zend Framework project.
Url: http://framework.zend.com Url: http://framework.zend.com
Copyright: Copyright © 2006-2007 by Zend Technologies, All rights reserved. Copyright: Copyright © 2006-2009 by Zend Technologies, All rights reserved.
License: New BSD License
eZ Components
------------
Doctrine SchemaTool, Platforms and SchemaManagers borrow ideas and concepts
from ezcDatabaseSchema.
Url: http://www.ezcomponents.org
License: New BSD License
Copyright: Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.

View File

@ -27,6 +27,7 @@ namespace Doctrine\DBAL\Platforms;
* @since 2.0 * @since 2.0
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/ */
class OraclePlatform extends AbstractPlatform class OraclePlatform extends AbstractPlatform
{ {
@ -275,10 +276,22 @@ class OraclePlatform extends AbstractPlatform
return $sql; return $sql;
} }
/**
*
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html
* @param string $table
* @return string
*/
public function getListTableIndexesSql($table) public function getListTableIndexesSql($table)
{ {
return "SELECT * FROM user_indexes" return "SELECT uind.index_name AS name, " .
. " WHERE table_name = '" . strtoupper($table) . "'"; " 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 " .
"FROM user_indexes uind, user_ind_columns uind_col " .
"WHERE uind.index_name = uind_col.index_name AND uind_col.table_name = '$table'";
} }
public function getListTablesSql() public function getListTablesSql()

View File

@ -27,6 +27,7 @@ namespace Doctrine\DBAL\Platforms;
* @since 2.0 * @since 2.0
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/ */
class PostgreSqlPlatform extends AbstractPlatform class PostgreSqlPlatform extends AbstractPlatform
{ {
@ -377,24 +378,22 @@ class PostgreSqlPlatform extends AbstractPlatform
)"; )";
} }
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param string $table
* @return string
*/
public function getListTableIndexesSql($table) public function getListTableIndexesSql($table)
{ {
return "SELECT return "SELECT relname, pg_index.indisunique, pg_index.indisprimary,
relname, pg_index.indkey, pg_index.indrelid
( FROM pg_class, pg_index
SELECT indisunique WHERE oid IN (
FROM pg_index
WHERE oid = indexrelid
) as unique
FROM
pg_class
WHERE oid IN (
SELECT indexrelid SELECT indexrelid
FROM pg_index, pg_class FROM pg_index, pg_class
WHERE pg_class.relname = '$table' WHERE pg_class.relname='$table' AND pg_class.oid=pg_index.indrelid
AND pg_class.oid=pg_index.indrelid ) AND pg_index.indexrelid = oid";
AND indisprimary != 't'
)";
} }
public function getListTableColumnsSql($table) public function getListTableColumnsSql($table)

View File

@ -33,6 +33,7 @@ use \Doctrine\Common\DoctrineException;
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @version $Revision$ * @version $Revision$
* @since 2.0 * @since 2.0
*/ */
@ -182,6 +183,28 @@ abstract class AbstractSchemaManager
/** /**
* List the indexes for a given table * 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,
* ),
* );
* *
* @param string $table The name of the table * @param string $table The name of the table
* @return array $tableIndexes * @return array $tableIndexes
@ -192,7 +215,7 @@ abstract class AbstractSchemaManager
$tableIndexes = $this->_conn->fetchAll($sql); $tableIndexes = $this->_conn->fetchAll($sql);
return $this->_getPortableTableIndexesList($tableIndexes); return $this->_getPortableTableIndexesList($tableIndexes, $table);
} }
/** /**
@ -884,20 +907,35 @@ abstract class AbstractSchemaManager
return $tableColumn; return $tableColumn;
} }
protected function _getPortableTableIndexesList($tableIndexes) /**
* Aggregate and group the index results according to the required data result.
*
* @param array $tableIndexes
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{ {
$list = array(); $result = array();
foreach ($tableIndexes as $key => $value) { foreach($tableIndexes AS $tableIndex) {
if ($value = $this->_getPortableTableIndexDefinition($value)) { $indexName = $keyName = $tableIndex['key_name'];
$list[] = $value; if($tableIndex['primary']) {
$keyName = 'primary';
}
if(!isset($result[$keyName])) {
$result[$keyName] = array(
'name' => $indexName,
'columns' => array($tableIndex['column_name']),
'unique' => $tableIndex['non_unique'] ? false : true,
'primary' => $tableIndex['primary'],
);
} else {
$result[$keyName]['columns'][] = $tableIndex['column_name'];
} }
} }
return $list;
}
protected function _getPortableTableIndexDefinition($tableIndex) return $result;
{
return $tableIndex;
} }
protected function _getPortableTablesList($tables) protected function _getPortableTablesList($tables)

View File

@ -28,6 +28,7 @@ namespace Doctrine\DBAL\Schema;
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @version $Revision$ * @version $Revision$
* @since 2.0 * @since 2.0
*/ */
@ -51,18 +52,19 @@ class MySqlSchemaManager extends AbstractSchemaManager
); );
} }
protected function _getPortableTableIndexDefinition($tableIndex) protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{ {
$tableIndex = array_change_key_case($tableIndex, CASE_LOWER); foreach($tableIndexes AS $k => $v) {
$v = array_change_key_case($v, CASE_LOWER);
$result = array(); if($v['key_name'] == 'PRIMARY') {
if ($tableIndex['key_name'] != 'PRIMARY' && ($index = $tableIndex['key_name'])) { $v['primary'] = true;
$result['name'] = $index; } else {
$result['column'] = $tableIndex['column_name']; $v['primary'] = false;
$result['unique'] = $tableIndex['non_unique'] ? false : true; }
$tablesIndexes[$k] = $v;
} }
return $result; return parent::_getPortableTableIndexesList($tablesIndexes, $tableName);
} }
protected function _getPortableTableConstraintDefinition($tableConstraint) protected function _getPortableTableConstraintDefinition($tableConstraint)

View File

@ -52,12 +52,32 @@ class OracleSchemaManager extends AbstractSchemaManager
return $table['table_name']; return $table['table_name'];
} }
protected function _getPortableTableIndexDefinition($tableIndex) /**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param array $tableIndexes
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{ {
return array( $indexBuffer = array();
'name' => $tableIndex['index_name'], foreach ( $tableIndexes as $tableIndex ) {
'unique' => (isset($tableIndex['uniqueness']) && $tableIndex['uniqueness'] == 'UNIQUE') ? true : false $keyName = $tableIndex['name'];
);
if ( $keyName == $tableName.'_pkey' ) {
$keyName = 'primary';
$buffer['primary'] = true;
$buffer['non_unique'] = false;
} else {
$buffer['primary'] = false;
$buffer['non_unique'] = ( $tableIndex['is_unique'] == 0 ) ? true : false;
}
$buffer['key_name'] = $keyName;
$buffer['column_name'] = $tableIndex['column_name'];
$indexBuffer[] = $buffer;
}
parent::_getPortableTableIndexesList($indexBuffer, $tableName);
} }
protected function _getPortableTableColumnDefinition($tableColumn) protected function _getPortableTableColumnDefinition($tableColumn)

View File

@ -27,6 +27,7 @@ namespace Doctrine\DBAL\Schema;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @version $Revision$ * @version $Revision$
* @since 2.0 * @since 2.0
*/ */
@ -70,12 +71,35 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
return $table['table_name']; return $table['table_name'];
} }
protected function _getPortableTableIndexDefinition($index) /**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param array $tableIndexes
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{ {
return array( $buffer = array();
'name' => $index['relname'], foreach($tableIndexes AS $row) {
'unique' => (bool) $index['unique'] $colNumbers = explode( ' ', $row['indkey'] );
); $colNumbersSql = 'IN (' . join( ' ,', $colNumbers ) . ' )';
$columnNameSql = "SELECT attname FROM pg_attribute
WHERE attrelid={$row['indrelid']} AND attnum $colNumbersSql;";
$stmt = $this->_conn->execute($columnNameSql);
$indexColumns = $stmt->fetchAll();
foreach ( $indexColumns as $colRow ) {
$buffer[] = array(
'key_name' => $row['relname'],
'column_name' => $colRow['attname'],
'non_unique' => !$row['indisunique'],
'primary' => $row['indisprimary']
);
}
}
return parent::_getPortableTableIndexesList($buffer);
} }
protected function _getPortableDatabaseDefinition($database) protected function _getPortableDatabaseDefinition($database)

View File

@ -68,6 +68,51 @@ class SqliteSchemaManager extends AbstractSchemaManager
return $table['name']; return $table['name'];
} }
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param array $tableIndexes
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
$indexBuffer = array();
// fetch primary
$stmt = $this->_conn->execute( "PRAGMA TABLE_INFO ('$tableName')" );
$indexArray = $stmt->fetchAll(\Doctrine\DBAL\Connection::FETCH_ASSOC);
foreach($indexArray AS $indexColumnRow) {
if($indexColumnRow['pk'] == "1") {
$indexBuffer[] = array(
'key_name' => 'primary',
'primary' => true,
'non_unique' => false,
'column_name' => $indexColumnRow['name']
);
}
}
// fetch regular indexes
foreach($tableIndexes AS $tableIndex) {
$keyName = $tableIndex['name'];
$idx = array();
$idx['key_name'] = $keyName;
$idx['primary'] = false;
$idx['non_unique'] = $tableIndex['unique']?false:true;
$stmt = $this->_conn->execute( "PRAGMA INDEX_INFO ( '{$keyName}' )" );
$indexArray = $stmt->fetchAll(\Doctrine\DBAL\Connection::FETCH_ASSOC);
foreach ( $indexArray as $indexColumnRow ) {
$idx['column_name'] = $indexColumnRow['name'];
$indexBuffer[] = $idx;
}
}
return parent::_getPortableTableIndexesList($indexBuffer, $tableName);
}
protected function _getPortableTableIndexDefinition($tableIndex) protected function _getPortableTableIndexDefinition($tableIndex)
{ {
return array( return array(

View File

@ -70,28 +70,6 @@ class MySqlSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertEquals(null, $columns[1]['default']); $this->assertEquals(null, $columns[1]['default']);
} }
public function testListTableIndexes()
{
$data['options'] = array(
'indexes' => array(
'test_index_name' => array(
'columns' => array(
'test' => array()
),
'type' => 'unique'
)
)
);
$this->createTestTable('list_table_indexes_test', $data);
$tableIndexes = $this->_sm->listTableIndexes('list_table_indexes_test');
$this->assertEquals('test_index_name', $tableIndexes[0]['name']);
$this->assertEquals('test', $tableIndexes[0]['column']);
$this->assertEquals(true, $tableIndexes[0]['unique']);
}
public function testListTables() public function testListTables()
{ {
$this->createTestTable('list_tables_test'); $this->createTestTable('list_tables_test');

View File

@ -66,25 +66,6 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertEquals(null, $columns[2]['default']); $this->assertEquals(null, $columns[2]['default']);
} }
public function testListTableIndexes()
{
$data['options'] = array(
'indexes' => array(
'test_index_name' => array(
'columns' => array(
'test' => array()
),
'type' => 'unique'
)
)
);
$this->createTestTable('list_table_indexes_test', $data);
$tableIndexes = $this->_sm->listTableIndexes('list_table_indexes_test');
$this->assertEquals(true, is_string($tableIndexes[0]['name']));
$this->assertEquals(true, $tableIndexes[0]['unique']);
}
public function testListTables() public function testListTables()
{ {
$this->createTestTable('list_tables_test'); $this->createTestTable('list_tables_test');

View File

@ -66,25 +66,6 @@ class PostgreSqlSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertEquals(null, $columns[1]['default']); $this->assertEquals(null, $columns[1]['default']);
} }
public function testListTableIndexes()
{
$data['options'] = array(
'indexes' => array(
'test' => array(
'columns' => array(
'test' => array()
),
'type' => 'unique'
)
)
);
$this->createTestTable('list_table_indexes_test', $data);
$tableIndexes = $this->_sm->listTableIndexes('list_table_indexes_test');
$this->assertEquals('test', $tableIndexes[0]['name']);
$this->assertEquals(true, $tableIndexes[0]['unique']);
}
public function testListTables() public function testListTables()
{ {
$this->createTestTable('list_tables_test'); $this->createTestTable('list_tables_test');

View File

@ -8,6 +8,65 @@ require_once __DIR__ . '/../../../TestInit.php';
class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTestCase class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTestCase
{ {
public function testListTableIndexes()
{
$data['options'] = array(
'indexes' => array(
'test_index_name' => array(
'columns' => array(
'test' => array()
),
'type' => 'unique'
),
'test_composite_idx' => array(
'columns' => array(
'id' => array(), 'test' => array(),
)
),
)
);
$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('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_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']);
}
public function testDropAndCreateIndex()
{
$this->createTestTable('test_create_index');
$index = array(
'columns' => array(
'test' => array()
),
'type' => 'unique'
);
$this->_sm->dropAndCreateIndex('test_create_index', 'test', $index);
$tableIndexes = $this->_sm->listTableIndexes('test_create_index');
$this->assertEquals('test', $tableIndexes['test']['name']);
$this->assertEquals(array('test'), $tableIndexes['test']['columns']);
$this->assertTrue($tableIndexes['test']['unique']);
$this->assertFalse($tableIndexes['test']['primary']);
}
protected function setUp() protected function setUp()
{ {
parent::setUp(); parent::setUp();

View File

@ -74,26 +74,6 @@ class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertEquals(null, $tableColumns[1]['default']); $this->assertEquals(null, $tableColumns[1]['default']);
} }
public function testListTableIndexes()
{
$data['options'] = array(
'indexes' => array(
'test' => array(
'columns' => array(
'test' => array()
),
'type' => 'unique'
)
)
);
$this->createTestTable('list_table_indexes_test', $data);
$tableIndexes = $this->_sm->listTableIndexes('list_table_indexes_test');
$this->assertEquals('test', $tableIndexes[0]['name']);
$this->assertEquals(true, $tableIndexes[0]['unique']);
}
public function testListTables() public function testListTables()
{ {
$this->createTestTable('list_tables_test'); $this->createTestTable('list_tables_test');
@ -164,23 +144,6 @@ class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->_sm->createSequence('seqname', 1, 1); $this->_sm->createSequence('seqname', 1, 1);
} }
public function testCreateIndex()
{
$this->createTestTable('test_create_index');
$index = array(
'columns' => array(
'test' => array()
),
'type' => 'unique'
);
$this->_sm->dropAndCreateIndex('test_create_index', 'test', $index);
$tableIndexes = $this->_sm->listTableIndexes('test_create_index');
$this->assertEquals('test', $tableIndexes[0]['name']);
$this->assertEquals(true, $tableIndexes[0]['unique']);
}
/** /**
* @expectedException \Exception * @expectedException \Exception
*/ */