DB2SchemaManager.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <?php
  2. namespace Doctrine\DBAL\Schema;
  3. use Doctrine\DBAL\Platforms\DB2Platform;
  4. use Doctrine\DBAL\Types\Type;
  5. use function array_change_key_case;
  6. use function assert;
  7. use function preg_match;
  8. use function str_replace;
  9. use function strpos;
  10. use function strtolower;
  11. use function substr;
  12. use const CASE_LOWER;
  13. /**
  14. * IBM Db2 Schema Manager.
  15. */
  16. class DB2SchemaManager extends AbstractSchemaManager
  17. {
  18. /**
  19. * {@inheritdoc}
  20. *
  21. * Apparently creator is the schema not the user who created it:
  22. * {@link http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.sqlref/db2z_sysibmsystablestable.htm}
  23. */
  24. public function listTableNames()
  25. {
  26. $sql = $this->_platform->getListTablesSQL();
  27. $sql .= ' AND CREATOR = UPPER(' . $this->_conn->quote($this->_conn->getUsername()) . ')';
  28. $tables = $this->_conn->fetchAllAssociative($sql);
  29. return $this->filterAssetNames($this->_getPortableTablesList($tables));
  30. }
  31. /**
  32. * {@inheritdoc}
  33. */
  34. protected function _getPortableTableColumnDefinition($tableColumn)
  35. {
  36. $tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
  37. $length = null;
  38. $fixed = null;
  39. $scale = false;
  40. $precision = false;
  41. $default = null;
  42. if ($tableColumn['default'] !== null && $tableColumn['default'] !== 'NULL') {
  43. $default = $tableColumn['default'];
  44. if (preg_match('/^\'(.*)\'$/s', $default, $matches)) {
  45. $default = str_replace("''", "'", $matches[1]);
  46. }
  47. }
  48. $type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']);
  49. if (isset($tableColumn['comment'])) {
  50. $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
  51. $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
  52. }
  53. switch (strtolower($tableColumn['typename'])) {
  54. case 'varchar':
  55. $length = $tableColumn['length'];
  56. $fixed = false;
  57. break;
  58. case 'character':
  59. $length = $tableColumn['length'];
  60. $fixed = true;
  61. break;
  62. case 'clob':
  63. $length = $tableColumn['length'];
  64. break;
  65. case 'decimal':
  66. case 'double':
  67. case 'real':
  68. $scale = $tableColumn['scale'];
  69. $precision = $tableColumn['length'];
  70. break;
  71. }
  72. $options = [
  73. 'length' => $length,
  74. 'unsigned' => false,
  75. 'fixed' => (bool) $fixed,
  76. 'default' => $default,
  77. 'autoincrement' => (bool) $tableColumn['autoincrement'],
  78. 'notnull' => $tableColumn['nulls'] === 'N',
  79. 'scale' => null,
  80. 'precision' => null,
  81. 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== ''
  82. ? $tableColumn['comment']
  83. : null,
  84. 'platformOptions' => [],
  85. ];
  86. if ($scale !== null && $precision !== null) {
  87. $options['scale'] = $scale;
  88. $options['precision'] = $precision;
  89. }
  90. return new Column($tableColumn['colname'], Type::getType($type), $options);
  91. }
  92. /**
  93. * {@inheritdoc}
  94. */
  95. protected function _getPortableTablesList($tables)
  96. {
  97. $tableNames = [];
  98. foreach ($tables as $tableRow) {
  99. $tableRow = array_change_key_case($tableRow, CASE_LOWER);
  100. $tableNames[] = $tableRow['name'];
  101. }
  102. return $tableNames;
  103. }
  104. /**
  105. * {@inheritdoc}
  106. */
  107. protected function _getPortableTableIndexesList($tableIndexes, $tableName = null)
  108. {
  109. foreach ($tableIndexes as &$tableIndexRow) {
  110. $tableIndexRow = array_change_key_case($tableIndexRow, CASE_LOWER);
  111. $tableIndexRow['primary'] = (bool) $tableIndexRow['primary'];
  112. }
  113. return parent::_getPortableTableIndexesList($tableIndexes, $tableName);
  114. }
  115. /**
  116. * {@inheritdoc}
  117. */
  118. protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
  119. {
  120. return new ForeignKeyConstraint(
  121. $tableForeignKey['local_columns'],
  122. $tableForeignKey['foreign_table'],
  123. $tableForeignKey['foreign_columns'],
  124. $tableForeignKey['name'],
  125. $tableForeignKey['options']
  126. );
  127. }
  128. /**
  129. * {@inheritdoc}
  130. */
  131. protected function _getPortableTableForeignKeysList($tableForeignKeys)
  132. {
  133. $foreignKeys = [];
  134. foreach ($tableForeignKeys as $tableForeignKey) {
  135. $tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER);
  136. if (! isset($foreignKeys[$tableForeignKey['index_name']])) {
  137. $foreignKeys[$tableForeignKey['index_name']] = [
  138. 'local_columns' => [$tableForeignKey['local_column']],
  139. 'foreign_table' => $tableForeignKey['foreign_table'],
  140. 'foreign_columns' => [$tableForeignKey['foreign_column']],
  141. 'name' => $tableForeignKey['index_name'],
  142. 'options' => [
  143. 'onUpdate' => $tableForeignKey['on_update'],
  144. 'onDelete' => $tableForeignKey['on_delete'],
  145. ],
  146. ];
  147. } else {
  148. $foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column'];
  149. $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column'];
  150. }
  151. }
  152. return parent::_getPortableTableForeignKeysList($foreignKeys);
  153. }
  154. /**
  155. * @param string $def
  156. *
  157. * @return string|null
  158. */
  159. protected function _getPortableForeignKeyRuleDef($def)
  160. {
  161. if ($def === 'C') {
  162. return 'CASCADE';
  163. }
  164. if ($def === 'N') {
  165. return 'SET NULL';
  166. }
  167. return null;
  168. }
  169. /**
  170. * {@inheritdoc}
  171. */
  172. protected function _getPortableViewDefinition($view)
  173. {
  174. $view = array_change_key_case($view, CASE_LOWER);
  175. $sql = '';
  176. $pos = strpos($view['text'], ' AS ');
  177. if ($pos !== false) {
  178. $sql = substr($view['text'], $pos + 4);
  179. }
  180. return new View($view['name'], $sql);
  181. }
  182. /**
  183. * {@inheritdoc}
  184. */
  185. public function listTableDetails($name): Table
  186. {
  187. $table = parent::listTableDetails($name);
  188. $platform = $this->_platform;
  189. assert($platform instanceof DB2Platform);
  190. $sql = $platform->getListTableCommentsSQL($name);
  191. $tableOptions = $this->_conn->fetchAssociative($sql);
  192. if ($tableOptions !== false) {
  193. $table->addOption('comment', $tableOptions['REMARKS']);
  194. }
  195. return $table;
  196. }
  197. }