MySqlSchemaManager.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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 MIT license. 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. * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
  24. * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
  25. * @author Roman Borschel <roman@code-factory.org>
  26. * @author Benjamin Eberlei <kontakt@beberlei.de>
  27. * @since 2.0
  28. */
  29. class MySqlSchemaManager extends AbstractSchemaManager
  30. {
  31. /**
  32. * {@inheritdoc}
  33. */
  34. protected function _getPortableViewDefinition($view)
  35. {
  36. return new View($view['TABLE_NAME'], $view['VIEW_DEFINITION']);
  37. }
  38. /**
  39. * {@inheritdoc}
  40. */
  41. protected function _getPortableTableDefinition($table)
  42. {
  43. return array_shift($table);
  44. }
  45. /**
  46. * {@inheritdoc}
  47. */
  48. protected function _getPortableUserDefinition($user)
  49. {
  50. return array(
  51. 'user' => $user['User'],
  52. 'password' => $user['Password'],
  53. );
  54. }
  55. /**
  56. * {@inheritdoc}
  57. */
  58. protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
  59. {
  60. foreach($tableIndexes as $k => $v) {
  61. $v = array_change_key_case($v, CASE_LOWER);
  62. if($v['key_name'] == 'PRIMARY') {
  63. $v['primary'] = true;
  64. } else {
  65. $v['primary'] = false;
  66. }
  67. if (strpos($v['index_type'], 'FULLTEXT') !== false) {
  68. $v['flags'] = array('FULLTEXT');
  69. }
  70. $tableIndexes[$k] = $v;
  71. }
  72. return parent::_getPortableTableIndexesList($tableIndexes, $tableName);
  73. }
  74. /**
  75. * {@inheritdoc}
  76. */
  77. protected function _getPortableSequenceDefinition($sequence)
  78. {
  79. return end($sequence);
  80. }
  81. /**
  82. * {@inheritdoc}
  83. */
  84. protected function _getPortableDatabaseDefinition($database)
  85. {
  86. return $database['Database'];
  87. }
  88. /**
  89. * {@inheritdoc}
  90. */
  91. protected function _getPortableTableColumnDefinition($tableColumn)
  92. {
  93. $tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
  94. $dbType = strtolower($tableColumn['type']);
  95. $dbType = strtok($dbType, '(), ');
  96. if (isset($tableColumn['length'])) {
  97. $length = $tableColumn['length'];
  98. } else {
  99. $length = strtok('(), ');
  100. }
  101. $fixed = null;
  102. if ( ! isset($tableColumn['name'])) {
  103. $tableColumn['name'] = '';
  104. }
  105. $scale = null;
  106. $precision = null;
  107. $type = $this->_platform->getDoctrineTypeMapping($dbType);
  108. // In cases where not connected to a database DESCRIBE $table does not return 'Comment'
  109. if (isset($tableColumn['comment'])) {
  110. $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
  111. $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
  112. }
  113. switch ($dbType) {
  114. case 'char':
  115. $fixed = true;
  116. break;
  117. case 'float':
  118. case 'double':
  119. case 'real':
  120. case 'numeric':
  121. case 'decimal':
  122. if(preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['type'], $match)) {
  123. $precision = $match[1];
  124. $scale = $match[2];
  125. $length = null;
  126. }
  127. break;
  128. case 'tinyint':
  129. case 'smallint':
  130. case 'mediumint':
  131. case 'int':
  132. case 'integer':
  133. case 'bigint':
  134. case 'tinyblob':
  135. case 'mediumblob':
  136. case 'longblob':
  137. case 'blob':
  138. case 'year':
  139. $length = null;
  140. break;
  141. }
  142. $length = ((int) $length == 0) ? null : (int) $length;
  143. $options = array(
  144. 'length' => $length,
  145. 'unsigned' => (bool) (strpos($tableColumn['type'], 'unsigned') !== false),
  146. 'fixed' => (bool) $fixed,
  147. 'default' => isset($tableColumn['default']) ? $tableColumn['default'] : null,
  148. 'notnull' => (bool) ($tableColumn['null'] != 'YES'),
  149. 'scale' => null,
  150. 'precision' => null,
  151. 'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false),
  152. 'comment' => (isset($tableColumn['comment'])) ? $tableColumn['comment'] : null
  153. );
  154. if ($scale !== null && $precision !== null) {
  155. $options['scale'] = $scale;
  156. $options['precision'] = $precision;
  157. }
  158. return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options);
  159. }
  160. /**
  161. * {@inheritdoc}
  162. */
  163. protected function _getPortableTableForeignKeysList($tableForeignKeys)
  164. {
  165. $list = array();
  166. foreach ($tableForeignKeys as $value) {
  167. $value = array_change_key_case($value, CASE_LOWER);
  168. if (!isset($list[$value['constraint_name']])) {
  169. if (!isset($value['delete_rule']) || $value['delete_rule'] == "RESTRICT") {
  170. $value['delete_rule'] = null;
  171. }
  172. if (!isset($value['update_rule']) || $value['update_rule'] == "RESTRICT") {
  173. $value['update_rule'] = null;
  174. }
  175. $list[$value['constraint_name']] = array(
  176. 'name' => $value['constraint_name'],
  177. 'local' => array(),
  178. 'foreign' => array(),
  179. 'foreignTable' => $value['referenced_table_name'],
  180. 'onDelete' => $value['delete_rule'],
  181. 'onUpdate' => $value['update_rule'],
  182. );
  183. }
  184. $list[$value['constraint_name']]['local'][] = $value['column_name'];
  185. $list[$value['constraint_name']]['foreign'][] = $value['referenced_column_name'];
  186. }
  187. $result = array();
  188. foreach($list as $constraint) {
  189. $result[] = new ForeignKeyConstraint(
  190. array_values($constraint['local']), $constraint['foreignTable'],
  191. array_values($constraint['foreign']), $constraint['name'],
  192. array(
  193. 'onDelete' => $constraint['onDelete'],
  194. 'onUpdate' => $constraint['onUpdate'],
  195. )
  196. );
  197. }
  198. return $result;
  199. }
  200. }