From d522ba73554d3577bfb7df2921e2a328b5e892d7 Mon Sep 17 00:00:00 2001 From: samw3 Date: Tue, 16 Oct 2007 00:03:15 +0000 Subject: [PATCH] changes db drivers to match the new two parameter Export::getDeclaration() --- lib/Doctrine/Export/Firebird.php | 2 +- lib/Doctrine/Export/Frontbase.php | 6 +- lib/Doctrine/Export/Mssql.php | 2 +- lib/Doctrine/Export/Mysql.php | 1276 ++++++++++++++--------------- lib/Doctrine/Export/Oracle.php | 4 +- lib/Doctrine/Export/Sqlite.php | 6 +- 6 files changed, 648 insertions(+), 648 deletions(-) diff --git a/lib/Doctrine/Export/Firebird.php b/lib/Doctrine/Export/Firebird.php index b031d7a13..f25ca6a74 100644 --- a/lib/Doctrine/Export/Firebird.php +++ b/lib/Doctrine/Export/Firebird.php @@ -326,7 +326,7 @@ class Doctrine_Export_Firebird extends Doctrine_Export if ($query) { $query.= ', '; } - $query.= 'ADD ' . $this->getDeclaration($field['type'], $fieldName, $field, $name); + $query.= 'ADD ' . $this->getDeclaration($fieldName, $field); } } diff --git a/lib/Doctrine/Export/Frontbase.php b/lib/Doctrine/Export/Frontbase.php index db16c29c9..7e5f40704 100644 --- a/lib/Doctrine/Export/Frontbase.php +++ b/lib/Doctrine/Export/Frontbase.php @@ -187,7 +187,7 @@ class Doctrine_Export_Frontbase extends Doctrine_Export if ($query) { $query.= ', '; } - $query.= 'ADD ' . $this->conn->getDeclaration($field['type'], $fieldName, $field); + $query.= 'ADD ' . $this->conn->getDeclaration($fieldName, $field); } } @@ -220,7 +220,7 @@ class Doctrine_Export_Frontbase extends Doctrine_Export $oldFieldName = $fieldName; } $oldFieldName = $this->conn->quoteIdentifier($oldFieldName, true); - $query.= 'CHANGE ' . $oldFieldName . ' ' . $this->conn->getDeclaration($field['definition']['type'], $oldFieldName, $field['definition']); + $query.= 'CHANGE ' . $oldFieldName . ' ' . $this->conn->getDeclaration($oldFieldName, $field['definition']); } } @@ -231,7 +231,7 @@ class Doctrine_Export_Frontbase extends Doctrine_Export } $oldFieldName = $rename[$renamedFieldName]; $field = $changes['rename'][$oldFieldName]; - $query.= 'CHANGE ' . $this->conn->getDeclaration($field['definition']['type'], $oldFieldName, $field['definition']); + $query.= 'CHANGE ' . $this->conn->getDeclaration($oldFieldName, $field['definition']); } } diff --git a/lib/Doctrine/Export/Mssql.php b/lib/Doctrine/Export/Mssql.php index eff5e6160..548b78a71 100644 --- a/lib/Doctrine/Export/Mssql.php +++ b/lib/Doctrine/Export/Mssql.php @@ -183,7 +183,7 @@ class Doctrine_Export_Mssql extends Doctrine_Export if ($query) { $query .= ', '; } - $query .= 'ADD ' . $this->conn->getDeclaration($field['type'], $fieldName, $field); + $query .= 'ADD ' . $this->conn->getDeclaration($fieldName, $field); } } diff --git a/lib/Doctrine/Export/Mysql.php b/lib/Doctrine/Export/Mysql.php index d6e848866..0089deb7c 100644 --- a/lib/Doctrine/Export/Mysql.php +++ b/lib/Doctrine/Export/Mysql.php @@ -1,639 +1,639 @@ -. - */ -Doctrine::autoload('Doctrine_Export'); -/** - * Doctrine_Export_Mysql - * - * @package Doctrine - * @subpackage Export - * @author Konsta Vesterinen - * @author Lukas Smith (PEAR MDB2 library) - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.com - * @since 1.0 - * @version $Revision$ - */ -class Doctrine_Export_Mysql extends Doctrine_Export -{ - /** - * create a new database - * - * @param string $name name of the database that should be created - * @return string - */ - public function createDatabaseSql($name) - { - return 'CREATE DATABASE ' . $this->conn->quoteIdentifier($name, true); - } - /** - * drop an existing database - * - * @param string $name name of the database that should be dropped - * @return string - */ - public function dropDatabaseSql($name) - { - return 'DROP DATABASE ' . $this->conn->quoteIdentifier($name); - } - /** - * create a new table - * - * @param string $name Name of the database that should be created - * @param array $fields Associative array that contains the definition of each field of the new table - * The indexes of the array entries are the names of the fields of the table an - * the array entry values are associative arrays like those that are meant to be - * passed with the field definitions to get[Type]Declaration() functions. - * array( - * 'id' => array( - * 'type' => 'integer', - * 'unsigned' => 1 - * 'notnull' => 1 - * 'default' => 0 - * ), - * 'name' => array( - * 'type' => 'text', - * 'length' => 12 - * ), - * 'password' => array( - * 'type' => 'text', - * 'length' => 12 - * ) - * ); - * @param array $options An associative array of table options: - * array( - * 'comment' => 'Foo', - * 'charset' => 'utf8', - * 'collate' => 'utf8_unicode_ci', - * 'type' => 'innodb', - * ); - * - * @return void - */ - public function createTableSql($name, array $fields, array $options = array()) - { - if ( ! $name) - throw new Doctrine_Export_Exception('no valid table name specified'); - - if (empty($fields)) { - throw new Doctrine_Export_Exception('no fields specified for table "'.$name.'"'); - } - $queryFields = $this->getFieldDeclarationList($fields); - - // build indexes for all foreign key fields (needed in MySQL!!) - if (isset($options['foreignKeys'])) { - foreach ($options['foreignKeys'] as $fk) { - $local = $fk['local']; - $found = false; - if (isset($options['indexes'])) { - foreach ($options['indexes'] as $definition) { - if (is_string($definition['fields'])) { - // Check if index already exists on the column - $found = ($local == $definition['fields']); - } else if (in_array($local, $definition['fields']) && count($definition['fields']) === 1) { - // Index already exists on the column - $found = true; - } - } - } - if (isset($options['primary']) && !empty($options['primary']) && - in_array($local, $options['primary'])) { - // field is part of the PK and therefore already indexed - $found = true; - } - - if ( ! $found) { - $options['indexes'][$local] = array('fields' => array($local => array())); - } - } - } - - // add all indexes - if (isset($options['indexes']) && ! empty($options['indexes'])) { - foreach($options['indexes'] as $index => $definition) { - $queryFields .= ', ' . $this->getIndexDeclaration($index, $definition); - } - } - - // attach all primary keys - if (isset($options['primary']) && ! empty($options['primary'])) { - $keyColumns = array_values($options['primary']); - $keyColumns = array_map(array($this->conn, 'quoteIdentifier'), $keyColumns); - $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; - } - - $query = 'CREATE TABLE ' . $this->conn->quoteIdentifier($name, true) . ' (' . $queryFields . ')'; - - $optionStrings = array(); - - if (isset($options['comment'])) { - $optionStrings['comment'] = 'COMMENT = ' . $this->dbh->quote($options['comment'], 'text'); - } - if (isset($options['charset'])) { - $optionStrings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset']; - if (isset($options['collate'])) { - $optionStrings['charset'] .= ' COLLATE ' . $options['collate']; - } - } - - $type = false; - - // get the type of the table - if (isset($options['type'])) { - $type = $options['type']; - } else { - $type = $this->conn->getAttribute(Doctrine::ATTR_DEFAULT_TABLE_TYPE); - } - - if ($type) { - $optionStrings[] = 'ENGINE = ' . $type; - } - - if ( ! empty($optionStrings)) { - $query.= ' '.implode(' ', $optionStrings); - } - $sql[] = $query; - - if (isset($options['foreignKeys'])) { - - foreach ((array) $options['foreignKeys'] as $k => $definition) { - if (is_array($definition)) { - $sql[] = $this->createForeignKeySql($name, $definition); - } - } - } - return $sql; - } - /** - * alter an existing table - * - * @param string $name name of the table that is intended to be changed. - * @param array $changes associative array that contains the details of each type - * of change that is intended to be performed. The types of - * changes that are currently supported are defined as follows: - * - * name - * - * New name for the table. - * - * add - * - * Associative array with the names of fields to be added as - * indexes of the array. The value of each entry of the array - * should be set to another associative array with the properties - * of the fields to be added. The properties of the fields should - * be the same as defined by the Metabase parser. - * - * - * remove - * - * Associative array with the names of fields to be removed as indexes - * of the array. Currently the values assigned to each entry are ignored. - * An empty array should be used for future compatibility. - * - * rename - * - * Associative array with the names of fields to be renamed as indexes - * of the array. The value of each entry of the array should be set to - * another associative array with the entry named name with the new - * field name and the entry named Declaration that is expected to contain - * the portion of the field declaration already in DBMS specific SQL code - * as it is used in the CREATE TABLE statement. - * - * change - * - * Associative array with the names of the fields to be changed as indexes - * of the array. Keep in mind that if it is intended to change either the - * name of a field and any other properties, the change array entries - * should have the new names of the fields as array indexes. - * - * The value of each entry of the array should be set to another associative - * array with the properties of the fields to that are meant to be changed as - * array entries. These entries should be assigned to the new values of the - * respective properties. The properties of the fields should be the same - * as defined by the Metabase parser. - * - * Example - * array( - * 'name' => 'userlist', - * 'add' => array( - * 'quota' => array( - * 'type' => 'integer', - * 'unsigned' => 1 - * ) - * ), - * 'remove' => array( - * 'file_limit' => array(), - * 'time_limit' => array() - * ), - * 'change' => array( - * 'name' => array( - * 'length' => '20', - * 'definition' => array( - * 'type' => 'text', - * 'length' => 20, - * ), - * ) - * ), - * 'rename' => array( - * 'sex' => array( - * 'name' => 'gender', - * 'definition' => array( - * 'type' => 'text', - * 'length' => 1, - * 'default' => 'M', - * ), - * ) - * ) - * ) - * - * @param boolean $check indicates whether the function should just check if the DBMS driver - * can perform the requested table alterations if the value is true or - * actually perform them otherwise. - * @return boolean - */ - 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; - } - /** - * 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 - */ - 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 . '))' - . strlen($this->conn->default_table_type) ? ' TYPE = ' - . $this->conn->default_table_type : ''; - - $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 { - $result = $this->conn->exec('DROP TABLE ' . $sequenceName); - } catch(Doctrine_Connection_Exception $e) { - throw new Doctrine_Export_Exception('could not drop inconsistent sequence table'); - } - - - } - /** - * Get the stucture of a field into an array - * - * @author Leoncx - * @param string $table name of the table on which the index is to be created - * @param string $name name of the index to be created - * @param array $definition associative array that defines properties of the index to be created. - * Currently, only one property named FIELDS is supported. This property - * is also an associative with the names of the index fields as array - * indexes. Each entry of this array is set to another type of associative - * array that specifies properties of the index that are specific to - * each field. - * - * Currently, only the sorting property is supported. It should be used - * to define the sorting direction of the index. It may be set to either - * ascending or descending. - * - * Not all DBMS support index sorting direction configuration. The DBMS - * drivers of those that do not support it ignore this property. Use the - * function supports() to determine whether the DBMS driver can manage indexes. - * - * Example - * array( - * 'fields' => array( - * 'user_name' => array( - * 'sorting' => 'ASC' - * 'length' => 10 - * ), - * 'last_login' => array() - * ) - * ) - * @throws PDOException - * @return void - */ - public function createIndexSql($table, $name, array $definition) - { - $table = $table; - $name = $this->conn->getIndexName($name); - $name = $this->conn->quoteIdentifier($name); - $type = ''; - if (isset($definition['type'])) { - switch (strtolower($definition['type'])) { - case 'fulltext': - case 'unique': - $type = strtoupper($definition['type']) . ' '; - break; - default: - throw new Doctrine_Export_Exception('Unknown index type ' . $definition['type']); - } - } - $query = 'CREATE ' . $type . 'INDEX ' . $name . ' ON ' . $table; - $query .= ' (' . $this->getIndexFieldDeclarationList() . ')'; - - return $query; - } - /** - * getDefaultDeclaration - * Obtain DBMS specific SQL code portion needed to set a default value - * declaration to be used in statements like CREATE TABLE. - * - * @param array $field field definition array - * @return string DBMS specific SQL code portion needed to set a default value - */ - public function getDefaultFieldDeclaration($field) - { - $default = ''; - if (isset($field['default']) && $field['length'] <= 255) { - if ($field['default'] === '') { - $field['default'] = empty($field['notnull']) - ? null : $this->valid_default_values[$field['type']]; - - if ($field['default'] === '' - && ($this->conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_EMPTY_TO_NULL) - ) { - $field['default'] = ' '; - } - } - - $default = ' DEFAULT ' . $this->conn->quote($field['default'], $field['type']); - } - return $default; - } - /** - * Obtain DBMS specific SQL code portion needed to set an index - * declaration to be used in statements like CREATE TABLE. - * - * @param string $charset name of the index - * @param array $definition index definition - * @return string DBMS specific SQL code portion needed to set an index - */ - public function getIndexDeclaration($name, array $definition) - { - $name = $this->conn->formatter->getIndexName($name); - $type = ''; - if (isset($definition['type'])) { - switch (strtolower($definition['type'])) { - case 'fulltext': - case 'unique': - $type = strtoupper($definition['type']) . ' '; - break; - default: - throw new Doctrine_Export_Exception('Unknown index type ' . $definition['type']); - } - } - - if ( ! isset($definition['fields'])) { - throw new Doctrine_Export_Exception('No index columns given.'); - } - if ( ! is_array($definition['fields'])) { - $definition['fields'] = array($definition['fields']); - } - - $query = $type . 'INDEX ' . $this->conn->quoteIdentifier($name); - - $query .= ' (' . $this->getIndexFieldDeclarationList($definition['fields']) . ')'; - - return $query; - } - /** - * getIndexFieldDeclarationList - * Obtain DBMS specific SQL code portion needed to set an index - * declaration to be used in statements like CREATE TABLE. - * - * @return string - */ - public function getIndexFieldDeclarationList(array $fields) - { - $declFields = array(); - - foreach ($fields as $fieldName => $field) { - $fieldString = $this->conn->quoteIdentifier($fieldName); - - if (is_array($field)) { - if (isset($field['length'])) { - $fieldString .= '(' . $field['length'] . ')'; - } - - if (isset($field['sorting'])) { - $sort = strtoupper($field['sorting']); - switch ($sort) { - case 'ASC': - case 'DESC': - $fieldString .= ' ' . $sort; - break; - default: - throw new Doctrine_Export_Exception('Unknown index sorting option given.'); - } - } - } else { - $fieldString = $this->conn->quoteIdentifier($field); - } - $declFields[] = $fieldString; - } - return implode(', ', $declFields); - } - /** - * getAdvancedForeignKeyOptions - * Return the FOREIGN KEY query section dealing with non-standard options - * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... - * - * @param array $definition - * @return string - */ - public function getAdvancedForeignKeyOptions(array $definition) - { - $query = ''; - if ( ! empty($definition['match'])) { - $query .= ' MATCH ' . $definition['match']; - } - if ( ! empty($definition['onUpdate'])) { - $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialAction($definition['onUpdate']); - } - if ( ! empty($definition['onDelete'])) { - $query .= ' ON DELETE ' . $this->getForeignKeyReferentialAction($definition['onDelete']); - } - return $query; - } - /** - * drop existing index - * - * @param string $table name of table that should be used in method - * @param string $name name of the index to be dropped - * @return void - */ - public function dropIndexSql($table, $name) - { - $table = $this->conn->quoteIdentifier($table, true); - $name = $this->conn->quoteIdentifier($this->conn->formatter->getIndexName($name), true); - return 'DROP INDEX ' . $name . ' ON ' . $table; - } - /** - * dropTable - * - * @param string $table name of table that should be dropped from the database - * @throws PDOException - * @return void - */ - public function dropTableSql($table) - { - $table = $this->conn->quoteIdentifier($table, true); - return 'DROP TABLE ' . $table; - } +. + */ +Doctrine::autoload('Doctrine_Export'); +/** + * Doctrine_Export_Mysql + * + * @package Doctrine + * @subpackage Export + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.phpdoctrine.com + * @since 1.0 + * @version $Revision$ + */ +class Doctrine_Export_Mysql extends Doctrine_Export +{ + /** + * create a new database + * + * @param string $name name of the database that should be created + * @return string + */ + public function createDatabaseSql($name) + { + return 'CREATE DATABASE ' . $this->conn->quoteIdentifier($name, true); + } + /** + * drop an existing database + * + * @param string $name name of the database that should be dropped + * @return string + */ + public function dropDatabaseSql($name) + { + return 'DROP DATABASE ' . $this->conn->quoteIdentifier($name); + } + /** + * create a new table + * + * @param string $name Name of the database that should be created + * @param array $fields Associative array that contains the definition of each field of the new table + * The indexes of the array entries are the names of the fields of the table an + * the array entry values are associative arrays like those that are meant to be + * passed with the field definitions to get[Type]Declaration() functions. + * array( + * 'id' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * 'notnull' => 1 + * 'default' => 0 + * ), + * 'name' => array( + * 'type' => 'text', + * 'length' => 12 + * ), + * 'password' => array( + * 'type' => 'text', + * 'length' => 12 + * ) + * ); + * @param array $options An associative array of table options: + * array( + * 'comment' => 'Foo', + * 'charset' => 'utf8', + * 'collate' => 'utf8_unicode_ci', + * 'type' => 'innodb', + * ); + * + * @return void + */ + public function createTableSql($name, array $fields, array $options = array()) + { + if ( ! $name) + throw new Doctrine_Export_Exception('no valid table name specified'); + + if (empty($fields)) { + throw new Doctrine_Export_Exception('no fields specified for table "'.$name.'"'); + } + $queryFields = $this->getFieldDeclarationList($fields); + + // build indexes for all foreign key fields (needed in MySQL!!) + if (isset($options['foreignKeys'])) { + foreach ($options['foreignKeys'] as $fk) { + $local = $fk['local']; + $found = false; + if (isset($options['indexes'])) { + foreach ($options['indexes'] as $definition) { + if (is_string($definition['fields'])) { + // Check if index already exists on the column + $found = ($local == $definition['fields']); + } else if (in_array($local, $definition['fields']) && count($definition['fields']) === 1) { + // Index already exists on the column + $found = true; + } + } + } + if (isset($options['primary']) && !empty($options['primary']) && + in_array($local, $options['primary'])) { + // field is part of the PK and therefore already indexed + $found = true; + } + + if ( ! $found) { + $options['indexes'][$local] = array('fields' => array($local => array())); + } + } + } + + // add all indexes + if (isset($options['indexes']) && ! empty($options['indexes'])) { + foreach($options['indexes'] as $index => $definition) { + $queryFields .= ', ' . $this->getIndexDeclaration($index, $definition); + } + } + + // attach all primary keys + if (isset($options['primary']) && ! empty($options['primary'])) { + $keyColumns = array_values($options['primary']); + $keyColumns = array_map(array($this->conn, 'quoteIdentifier'), $keyColumns); + $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; + } + + $query = 'CREATE TABLE ' . $this->conn->quoteIdentifier($name, true) . ' (' . $queryFields . ')'; + + $optionStrings = array(); + + if (isset($options['comment'])) { + $optionStrings['comment'] = 'COMMENT = ' . $this->dbh->quote($options['comment'], 'text'); + } + if (isset($options['charset'])) { + $optionStrings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset']; + if (isset($options['collate'])) { + $optionStrings['charset'] .= ' COLLATE ' . $options['collate']; + } + } + + $type = false; + + // get the type of the table + if (isset($options['type'])) { + $type = $options['type']; + } else { + $type = $this->conn->getAttribute(Doctrine::ATTR_DEFAULT_TABLE_TYPE); + } + + if ($type) { + $optionStrings[] = 'ENGINE = ' . $type; + } + + if ( ! empty($optionStrings)) { + $query.= ' '.implode(' ', $optionStrings); + } + $sql[] = $query; + + if (isset($options['foreignKeys'])) { + + foreach ((array) $options['foreignKeys'] as $k => $definition) { + if (is_array($definition)) { + $sql[] = $this->createForeignKeySql($name, $definition); + } + } + } + return $sql; + } + /** + * alter an existing table + * + * @param string $name name of the table that is intended to be changed. + * @param array $changes associative array that contains the details of each type + * of change that is intended to be performed. The types of + * changes that are currently supported are defined as follows: + * + * name + * + * New name for the table. + * + * add + * + * Associative array with the names of fields to be added as + * indexes of the array. The value of each entry of the array + * should be set to another associative array with the properties + * of the fields to be added. The properties of the fields should + * be the same as defined by the Metabase parser. + * + * + * remove + * + * Associative array with the names of fields to be removed as indexes + * of the array. Currently the values assigned to each entry are ignored. + * An empty array should be used for future compatibility. + * + * rename + * + * Associative array with the names of fields to be renamed as indexes + * of the array. The value of each entry of the array should be set to + * another associative array with the entry named name with the new + * field name and the entry named Declaration that is expected to contain + * the portion of the field declaration already in DBMS specific SQL code + * as it is used in the CREATE TABLE statement. + * + * change + * + * Associative array with the names of the fields to be changed as indexes + * of the array. Keep in mind that if it is intended to change either the + * name of a field and any other properties, the change array entries + * should have the new names of the fields as array indexes. + * + * The value of each entry of the array should be set to another associative + * array with the properties of the fields to that are meant to be changed as + * array entries. These entries should be assigned to the new values of the + * respective properties. The properties of the fields should be the same + * as defined by the Metabase parser. + * + * Example + * array( + * 'name' => 'userlist', + * 'add' => array( + * 'quota' => array( + * 'type' => 'integer', + * 'unsigned' => 1 + * ) + * ), + * 'remove' => array( + * 'file_limit' => array(), + * 'time_limit' => array() + * ), + * 'change' => array( + * 'name' => array( + * 'length' => '20', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 20, + * ), + * ) + * ), + * 'rename' => array( + * 'sex' => array( + * 'name' => 'gender', + * 'definition' => array( + * 'type' => 'text', + * 'length' => 1, + * 'default' => 'M', + * ), + * ) + * ) + * ) + * + * @param boolean $check indicates whether the function should just check if the DBMS driver + * can perform the requested table alterations if the value is true or + * actually perform them otherwise. + * @return boolean + */ + 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($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($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['name'], $field['definition']); + } + } + + if ( ! $query) { + return false; + } + + $name = $this->conn->quoteIdentifier($name, true); + + return 'ALTER TABLE ' . $name . ' ' . $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 + */ + 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 . '))' + . strlen($this->conn->default_table_type) ? ' TYPE = ' + . $this->conn->default_table_type : ''; + + $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 { + $result = $this->conn->exec('DROP TABLE ' . $sequenceName); + } catch(Doctrine_Connection_Exception $e) { + throw new Doctrine_Export_Exception('could not drop inconsistent sequence table'); + } + + + } + /** + * Get the stucture of a field into an array + * + * @author Leoncx + * @param string $table name of the table on which the index is to be created + * @param string $name name of the index to be created + * @param array $definition associative array that defines properties of the index to be created. + * Currently, only one property named FIELDS is supported. This property + * is also an associative with the names of the index fields as array + * indexes. Each entry of this array is set to another type of associative + * array that specifies properties of the index that are specific to + * each field. + * + * Currently, only the sorting property is supported. It should be used + * to define the sorting direction of the index. It may be set to either + * ascending or descending. + * + * Not all DBMS support index sorting direction configuration. The DBMS + * drivers of those that do not support it ignore this property. Use the + * function supports() to determine whether the DBMS driver can manage indexes. + * + * Example + * array( + * 'fields' => array( + * 'user_name' => array( + * 'sorting' => 'ASC' + * 'length' => 10 + * ), + * 'last_login' => array() + * ) + * ) + * @throws PDOException + * @return void + */ + public function createIndexSql($table, $name, array $definition) + { + $table = $table; + $name = $this->conn->getIndexName($name); + $name = $this->conn->quoteIdentifier($name); + $type = ''; + if (isset($definition['type'])) { + switch (strtolower($definition['type'])) { + case 'fulltext': + case 'unique': + $type = strtoupper($definition['type']) . ' '; + break; + default: + throw new Doctrine_Export_Exception('Unknown index type ' . $definition['type']); + } + } + $query = 'CREATE ' . $type . 'INDEX ' . $name . ' ON ' . $table; + $query .= ' (' . $this->getIndexFieldDeclarationList() . ')'; + + return $query; + } + /** + * getDefaultDeclaration + * Obtain DBMS specific SQL code portion needed to set a default value + * declaration to be used in statements like CREATE TABLE. + * + * @param array $field field definition array + * @return string DBMS specific SQL code portion needed to set a default value + */ + public function getDefaultFieldDeclaration($field) + { + $default = ''; + if (isset($field['default']) && $field['length'] <= 255) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) + ? null : $this->valid_default_values[$field['type']]; + + if ($field['default'] === '' + && ($this->conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_EMPTY_TO_NULL) + ) { + $field['default'] = ' '; + } + } + + $default = ' DEFAULT ' . $this->conn->quote($field['default'], $field['type']); + } + return $default; + } + /** + * Obtain DBMS specific SQL code portion needed to set an index + * declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the index + * @param array $definition index definition + * @return string DBMS specific SQL code portion needed to set an index + */ + public function getIndexDeclaration($name, array $definition) + { + $name = $this->conn->formatter->getIndexName($name); + $type = ''; + if (isset($definition['type'])) { + switch (strtolower($definition['type'])) { + case 'fulltext': + case 'unique': + $type = strtoupper($definition['type']) . ' '; + break; + default: + throw new Doctrine_Export_Exception('Unknown index type ' . $definition['type']); + } + } + + if ( ! isset($definition['fields'])) { + throw new Doctrine_Export_Exception('No index columns given.'); + } + if ( ! is_array($definition['fields'])) { + $definition['fields'] = array($definition['fields']); + } + + $query = $type . 'INDEX ' . $this->conn->quoteIdentifier($name); + + $query .= ' (' . $this->getIndexFieldDeclarationList($definition['fields']) . ')'; + + return $query; + } + /** + * getIndexFieldDeclarationList + * Obtain DBMS specific SQL code portion needed to set an index + * declaration to be used in statements like CREATE TABLE. + * + * @return string + */ + public function getIndexFieldDeclarationList(array $fields) + { + $declFields = array(); + + foreach ($fields as $fieldName => $field) { + $fieldString = $this->conn->quoteIdentifier($fieldName); + + if (is_array($field)) { + if (isset($field['length'])) { + $fieldString .= '(' . $field['length'] . ')'; + } + + if (isset($field['sorting'])) { + $sort = strtoupper($field['sorting']); + switch ($sort) { + case 'ASC': + case 'DESC': + $fieldString .= ' ' . $sort; + break; + default: + throw new Doctrine_Export_Exception('Unknown index sorting option given.'); + } + } + } else { + $fieldString = $this->conn->quoteIdentifier($field); + } + $declFields[] = $fieldString; + } + return implode(', ', $declFields); + } + /** + * getAdvancedForeignKeyOptions + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param array $definition + * @return string + */ + public function getAdvancedForeignKeyOptions(array $definition) + { + $query = ''; + if ( ! empty($definition['match'])) { + $query .= ' MATCH ' . $definition['match']; + } + if ( ! empty($definition['onUpdate'])) { + $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialAction($definition['onUpdate']); + } + if ( ! empty($definition['onDelete'])) { + $query .= ' ON DELETE ' . $this->getForeignKeyReferentialAction($definition['onDelete']); + } + return $query; + } + /** + * drop existing index + * + * @param string $table name of table that should be used in method + * @param string $name name of the index to be dropped + * @return void + */ + public function dropIndexSql($table, $name) + { + $table = $this->conn->quoteIdentifier($table, true); + $name = $this->conn->quoteIdentifier($this->conn->formatter->getIndexName($name), true); + return 'DROP INDEX ' . $name . ' ON ' . $table; + } + /** + * dropTable + * + * @param string $table name of table that should be dropped from the database + * @throws PDOException + * @return void + */ + public function dropTableSql($table) + { + $table = $this->conn->quoteIdentifier($table, true); + return 'DROP TABLE ' . $table; + } } \ No newline at end of file diff --git a/lib/Doctrine/Export/Oracle.php b/lib/Doctrine/Export/Oracle.php index d46628c38..b42404931 100644 --- a/lib/Doctrine/Export/Oracle.php +++ b/lib/Doctrine/Export/Oracle.php @@ -423,7 +423,7 @@ END; if ( ! empty($changes['add']) && is_array($changes['add'])) { $fields = array(); foreach ($changes['add'] as $fieldName => $field) { - $fields[] = $this->conn->getDeclaration($field['type'], $fieldName, $field); + $fields[] = $this->conn->getDeclaration($fieldName, $field); } $result = $this->conn->exec('ALTER TABLE ' . $name . ' ADD (' . implode(', ', $fields) . ')'); } @@ -431,7 +431,7 @@ END; if ( ! empty($changes['change']) && is_array($changes['change'])) { $fields = array(); foreach ($changes['change'] as $fieldName => $field) { - $fields[] = $fieldName. ' ' . $this->conn->getDeclaration($field['definition']['type'], '', $field['definition']); + $fields[] = $fieldName. ' ' . $this->conn->getDeclaration('', $field['definition']); } $result = $this->conn->exec('ALTER TABLE ' . $name . ' MODIFY (' . implode(', ', $fields) . ')'); } diff --git a/lib/Doctrine/Export/Sqlite.php b/lib/Doctrine/Export/Sqlite.php index 904112805..683827892 100644 --- a/lib/Doctrine/Export/Sqlite.php +++ b/lib/Doctrine/Export/Sqlite.php @@ -360,7 +360,7 @@ class Doctrine_Export_Sqlite extends Doctrine_Export if ($query) { $query.= ', '; } - $query.= 'ADD ' . $this->getDeclaration($field['type'], $fieldName, $field); + $query.= 'ADD ' . $this->getDeclaration($fieldName, $field); } } @@ -384,7 +384,7 @@ class Doctrine_Export_Sqlite extends Doctrine_Export } $oldFieldName = $this->conn->quoteIdentifier($oldFieldName, true); $query .= 'CHANGE ' . $oldFieldName . ' ' - . $this->getDeclaration($field['definition']['type'], $fieldName, $field['definition']); + . $this->getDeclaration($fieldName, $field['definition']); } } @@ -396,7 +396,7 @@ class Doctrine_Export_Sqlite extends Doctrine_Export $field = $changes['rename'][$renamedField]; $renamedField = $this->conn->quoteIdentifier($renamedField, true); $query .= 'CHANGE ' . $renamedField . ' ' - . $this->getDeclaration($field['definition']['type'], $field['name'], $field['definition']); + . $this->getDeclaration($field['name'], $field['definition']); } }