MySqlSchemaManager.php 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <?php
  2. /*
  3. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14. *
  15. * This software consists of voluntary contributions made by many individuals
  16. * and is licensed under the LGPL. For more information, see
  17. * <http://www.doctrine-project.org>.
  18. */
  19. namespace Doctrine\DBAL\Schema;
  20. /**
  21. * Schema manager for the MySql RDBMS.
  22. *
  23. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
  24. * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
  25. * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
  26. * @author Roman Borschel <roman@code-factory.org>
  27. * @author Benjamin Eberlei <kontakt@beberlei.de>
  28. * @version $Revision$
  29. * @since 2.0
  30. */
  31. class MySqlSchemaManager extends AbstractSchemaManager
  32. {
  33. protected function _getPortableViewDefinition($view)
  34. {
  35. return new View($view['TABLE_NAME'], $view['VIEW_DEFINITION']);
  36. }
  37. protected function _getPortableTableDefinition($table)
  38. {
  39. return array_shift($table);
  40. }
  41. protected function _getPortableUserDefinition($user)
  42. {
  43. return array(
  44. 'user' => $user['User'],
  45. 'password' => $user['Password'],
  46. );
  47. }
  48. protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
  49. {
  50. foreach($tableIndexes AS $k => $v) {
  51. $v = array_change_key_case($v, CASE_LOWER);
  52. if($v['key_name'] == 'PRIMARY') {
  53. $v['primary'] = true;
  54. } else {
  55. $v['primary'] = false;
  56. }
  57. $tableIndexes[$k] = $v;
  58. }
  59. return parent::_getPortableTableIndexesList($tableIndexes, $tableName);
  60. }
  61. protected function _getPortableSequenceDefinition($sequence)
  62. {
  63. return end($sequence);
  64. }
  65. protected function _getPortableDatabaseDefinition($database)
  66. {
  67. return $database['Database'];
  68. }
  69. /**
  70. * Gets a portable column definition.
  71. *
  72. * The database type is mapped to a corresponding Doctrine mapping type.
  73. *
  74. * @param $tableColumn
  75. * @return array
  76. */
  77. protected function _getPortableTableColumnDefinition($tableColumn)
  78. {
  79. $tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
  80. $dbType = strtolower($tableColumn['type']);
  81. $dbType = strtok($dbType, '(), ');
  82. if (isset($tableColumn['length'])) {
  83. $length = $tableColumn['length'];
  84. $decimal = '';
  85. } else {
  86. $length = strtok('(), ');
  87. $decimal = strtok('(), ') ? strtok('(), '):null;
  88. }
  89. $type = array();
  90. $unsigned = $fixed = null;
  91. if ( ! isset($tableColumn['name'])) {
  92. $tableColumn['name'] = '';
  93. }
  94. $scale = null;
  95. $precision = null;
  96. $type = $this->_platform->getDoctrineTypeMapping($dbType);
  97. $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
  98. $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
  99. switch ($dbType) {
  100. case 'char':
  101. $fixed = true;
  102. break;
  103. case 'float':
  104. case 'double':
  105. case 'real':
  106. case 'numeric':
  107. case 'decimal':
  108. if(preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['type'], $match)) {
  109. $precision = $match[1];
  110. $scale = $match[2];
  111. $length = null;
  112. }
  113. break;
  114. case 'tinyint':
  115. case 'smallint':
  116. case 'mediumint':
  117. case 'int':
  118. case 'integer':
  119. case 'bigint':
  120. case 'tinyblob':
  121. case 'mediumblob':
  122. case 'longblob':
  123. case 'blob':
  124. case 'year':
  125. $length = null;
  126. break;
  127. }
  128. $length = ((int) $length == 0) ? null : (int) $length;
  129. $def = array(
  130. 'type' => $type,
  131. 'length' => $length,
  132. 'unsigned' => (bool) $unsigned,
  133. 'fixed' => (bool) $fixed
  134. );
  135. $options = array(
  136. 'length' => $length,
  137. 'unsigned' => (bool)$unsigned,
  138. 'fixed' => (bool)$fixed,
  139. 'default' => isset($tableColumn['default']) ? $tableColumn['default'] : null,
  140. 'notnull' => (bool) ($tableColumn['null'] != 'YES'),
  141. 'scale' => null,
  142. 'precision' => null,
  143. 'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false),
  144. 'comment' => (isset($tableColumn['comment'])) ? $tableColumn['comment'] : null
  145. );
  146. if ($scale !== null && $precision !== null) {
  147. $options['scale'] = $scale;
  148. $options['precision'] = $precision;
  149. }
  150. return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options);
  151. }
  152. protected function _getPortableTableForeignKeysList($tableForeignKeys)
  153. {
  154. $list = array();
  155. foreach ($tableForeignKeys as $key => $value) {
  156. $value = array_change_key_case($value, CASE_LOWER);
  157. if (!isset($list[$value['constraint_name']])) {
  158. if (!isset($value['delete_rule']) || $value['delete_rule'] == "RESTRICT") {
  159. $value['delete_rule'] = null;
  160. }
  161. if (!isset($value['update_rule']) || $value['update_rule'] == "RESTRICT") {
  162. $value['update_rule'] = null;
  163. }
  164. $list[$value['constraint_name']] = array(
  165. 'name' => $value['constraint_name'],
  166. 'local' => array(),
  167. 'foreign' => array(),
  168. 'foreignTable' => $value['referenced_table_name'],
  169. 'onDelete' => $value['delete_rule'],
  170. 'onUpdate' => $value['update_rule'],
  171. );
  172. }
  173. $list[$value['constraint_name']]['local'][] = $value['column_name'];
  174. $list[$value['constraint_name']]['foreign'][] = $value['referenced_column_name'];
  175. }
  176. $result = array();
  177. foreach($list AS $constraint) {
  178. $result[] = new ForeignKeyConstraint(
  179. array_values($constraint['local']), $constraint['foreignTable'],
  180. array_values($constraint['foreign']), $constraint['name'],
  181. array(
  182. 'onDelete' => $constraint['onDelete'],
  183. 'onUpdate' => $constraint['onUpdate'],
  184. )
  185. );
  186. }
  187. return $result;
  188. }
  189. }