1
0
mirror of synced 2024-12-15 07:36:03 +03:00
doctrine2/lib/Doctrine/DBAL/Schema/MySqlSchemaManger.php
2008-09-12 10:17:13 +00:00

327 lines
11 KiB
PHP

<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine::DBAL::Schema;
/**
* xxx
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @version $Revision$
* @since 2.0
*/
class Doctrine_DBAL_Schema_MySqlSchemaManager extends Doctrine_DBAL_Schema_AbstractSchemaManager
{
public function __construct(Doctrine_Connection $conn)
{
$this->_conn = $conn;
}
/**
* lists all database sequences
*
* @param string|null $database
* @return array
* @override
*/
public function listSequences($database = null)
{
$query = 'SHOW TABLES';
if ( ! is_null($database)) {
$query .= ' FROM ' . $database;
}
$tableNames = $this->_conn->fetchColumn($query);
return array_map(array($this->_conn->formatter, 'fixSequenceName'), $tableNames);
}
/**
* lists table constraints
*
* @param string $table database table name
* @return array
* @override
*/
public function listTableConstraints($table)
{
$keyName = 'Key_name';
$nonUnique = 'Non_unique';
if ($this->_conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_FIX_CASE) {
if ($this->_conn->getAttribute(Doctrine::ATTR_FIELD_CASE) == CASE_LOWER) {
$keyName = strtolower($keyName);
$nonUnique = strtolower($nonUnique);
} else {
$keyName = strtoupper($keyName);
$nonUnique = strtoupper($nonUnique);
}
}
$table = $this->_conn->quoteIdentifier($table, true);
$query = 'SHOW INDEX FROM ' . $table;
$indexes = $this->_conn->fetchAssoc($query);
$result = array();
foreach ($indexes as $indexData) {
if ( ! $indexData[$nonUnique]) {
if ($indexData[$keyName] !== 'PRIMARY') {
$index = $this->_conn->formatter->fixIndexName($indexData[$keyName]);
} else {
$index = 'PRIMARY';
}
if ( ! empty($index)) {
$result[] = $index;
}
}
}
return $result;
}
/**
* lists table foreign keys
*
* @param string $table database table name
* @return array
* @override
*/
public function listTableForeignKeys($table)
{
$sql = 'SHOW CREATE TABLE ' . $this->_conn->quoteIdentifier($table, true);
$definition = $this->_conn->fetchOne($sql);
if (!empty($definition)) {
$pattern = '/\bCONSTRAINT\s+([^\s]+)\s+FOREIGN KEY\b/i';
if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 1) {
foreach ($matches[1] as $constraint) {
$result[$constraint] = true;
}
}
}
if ($this->_conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_FIX_CASE) {
$result = array_change_key_case($result, $this->_conn->getAttribute(Doctrine::ATTR_FIELD_CASE));
}
return $result;
}
/**
* lists table constraints
*
* @param string $table database table name
* @return array
* @override
*/
public function listTableColumns($table)
{
$sql = 'DESCRIBE ' . $this->_conn->quoteIdentifier($table, true);
$result = $this->_conn->fetchAssoc($sql);
$description = array();
$columns = array();
foreach ($result as $key => $val) {
$val = array_change_key_case($val, CASE_LOWER);
$decl = $this->_conn->getDatabasePlatform()->getPortableDeclaration($val);
$values = isset($decl['values']) ? $decl['values'] : array();
$description = array(
'name' => $val['field'],
'type' => $decl['type'][0],
'alltypes' => $decl['type'],
'ntype' => $val['type'],
'length' => $decl['length'],
'fixed' => $decl['fixed'],
'unsigned' => $decl['unsigned'],
'values' => $values,
'primary' => (strtolower($val['key']) == 'pri'),
'default' => $val['default'],
'notnull' => (bool) ($val['null'] != 'YES'),
'autoincrement' => (bool) (strpos($val['extra'], 'auto_increment') !== false),
);
$columns[$val['field']] = $description;
}
return $columns;
}
/**
* lists table constraints
*
* @param string $table database table name
* @return array
* @override
*/
public function listTableIndexes($table)
{
$keyName = 'Key_name';
$nonUnique = 'Non_unique';
if ($this->_conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_FIX_CASE) {
if ($this->_conn->getAttribute(Doctrine::ATTR_FIELD_CASE) == CASE_LOWER) {
$keyName = strtolower($keyName);
$nonUnique = strtolower($nonUnique);
} else {
$keyName = strtoupper($keyName);
$nonUnique = strtoupper($nonUnique);
}
}
$table = $this->_conn->quoteIdentifier($table, true);
$query = 'SHOW INDEX FROM ' . $table;
$indexes = $this->_conn->fetchAssoc($query);
$result = array();
foreach ($indexes as $indexData) {
if ($indexData[$nonUnique] && ($index = $this->_conn->formatter->fixIndexName($indexData[$keyName]))) {
$result[] = $index;
}
}
return $result;
}
/**
* lists tables
*
* @param string|null $database
* @return array
* @override
*/
public function listTables($database = null)
{
return $this->_conn->fetchColumn($this->_conn->getDatabasePlatform()
->getListTablesSql());
}
/**
* lists database views
*
* @param string|null $database
* @return array
* @override
*/
public function listViews($database = null)
{
if ( ! is_null($database)) {
$query = sprintf($this->sql['listViews'], ' FROM ' . $database);
}
return $this->_conn->fetchColumn($query);
}
/**
* create sequence
*
* @param string $sequenceName name of the sequence to be created
* @param string $start start value of the sequence; default is 1
* @param array $options An associative array of table options:
* array(
* 'comment' => 'Foo',
* 'charset' => 'utf8',
* 'collate' => 'utf8_unicode_ci',
* 'type' => 'innodb',
* );
* @return boolean
* @override
*/
public function createSequence($sequenceName, $start = 1, array $options = array())
{
$sequenceName = $this->_conn->quoteIdentifier($this->_conn->getSequenceName($sequenceName), true);
$seqcolName = $this->_conn->quoteIdentifier($this->_conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true);
$optionsStrings = array();
if (isset($options['comment']) && ! empty($options['comment'])) {
$optionsStrings['comment'] = 'COMMENT = ' . $this->_conn->quote($options['comment'], 'string');
}
if (isset($options['charset']) && ! empty($options['charset'])) {
$optionsStrings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset'];
if (isset($options['collate'])) {
$optionsStrings['collate'] .= ' COLLATE ' . $options['collate'];
}
}
$type = false;
if (isset($options['type'])) {
$type = $options['type'];
} else {
$type = $this->_conn->default_table_type;
}
if ($type) {
$optionsStrings[] = 'ENGINE = ' . $type;
}
try {
$query = 'CREATE TABLE ' . $sequenceName
. ' (' . $seqcolName . ' INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ('
. $seqcolName . '))';
if (!empty($options_strings)) {
$query .= ' '.implode(' ', $options_strings);
}
$res = $this->_conn->exec($query);
} catch(Doctrine_Connection_Exception $e) {
throw new Doctrine_Export_Exception('could not create sequence table');
}
if ($start == 1) {
return true;
}
$query = 'INSERT INTO ' . $sequenceName
. ' (' . $seqcolName . ') VALUES (' . ($start - 1) . ')';
$res = $this->_conn->exec($query);
// Handle error
try {
$res = $this->_conn->exec('DROP TABLE ' . $sequenceName);
} catch(Doctrine_Connection_Exception $e) {
throw new Doctrine_Export_Exception('could not drop inconsistent sequence table');
}
return $res;
}
/**
* Enter description here...
*
* @param unknown_type $table
* @param unknown_type $name
* @return unknown
* @override
*/
public function dropForeignKey($table, $name)
{
$table = $this->_conn->quoteIdentifier($table);
$name = $this->_conn->quoteIdentifier($name);
return $this->_conn->exec('ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $name);
}
}
?>