PageRenderTime 29ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/DatabaseSchema/src/handlers/mysql/writer.php

https://github.com/xc/zetacomponents
PHP | 332 lines | 157 code | 31 blank | 144 comment | 16 complexity | 96cd9d2c921c036ecd65329b038575e3 MD5 | raw file
  1. <?php
  2. /**
  3. * File containing the ezcDbSchemaMysqlWriter class.
  4. *
  5. * Licensed to the Apache Software Foundation (ASF) under one
  6. * or more contributor license agreements. See the NOTICE file
  7. * distributed with this work for additional information
  8. * regarding copyright ownership. The ASF licenses this file
  9. * to you under the Apache License, Version 2.0 (the
  10. * "License"); you may not use this file except in compliance
  11. * with the License. You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing,
  16. * software distributed under the License is distributed on an
  17. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18. * KIND, either express or implied. See the License for the
  19. * specific language governing permissions and limitations
  20. * under the License.
  21. *
  22. * @package DatabaseSchema
  23. * @version //autogentag//
  24. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25. */
  26. /**
  27. * Handler for storing database schemas and applying differences that uses MySQL as backend.
  28. *
  29. * @package DatabaseSchema
  30. * @version //autogentag//
  31. */
  32. class ezcDbSchemaMysqlWriter extends ezcDbSchemaCommonSqlWriter implements ezcDbSchemaDbWriter, ezcDbSchemaDiffDbWriter
  33. {
  34. /**
  35. * Contains a type map from DbSchema types to MySQL native types.
  36. *
  37. * @var array
  38. */
  39. private $typeMap = array(
  40. 'integer' => 'bigint',
  41. 'boolean' => 'boolean',
  42. 'float' => 'double',
  43. 'decimal' => 'numeric',
  44. 'date' => 'date',
  45. 'timestamp' => 'timestamp',
  46. 'text' => 'varchar',
  47. 'blob' => 'longblob',
  48. 'clob' => 'longtext'
  49. );
  50. /**
  51. * Returns what type of schema writer this class implements.
  52. *
  53. * This method always returns ezcDbSchema::DATABASE
  54. *
  55. * @return int
  56. */
  57. public function getWriterType()
  58. {
  59. return ezcDbSchema::DATABASE;
  60. }
  61. /**
  62. * Returns what type of schema difference writer this class implements.
  63. *
  64. * This method always returns ezcDbSchema::DATABASE
  65. *
  66. * @return int
  67. */
  68. public function getDiffWriterType()
  69. {
  70. return ezcDbSchema::DATABASE;
  71. }
  72. /**
  73. * Applies the differences defined in $dbSchemaDiff to the database referenced by $db.
  74. *
  75. * This method uses {@link convertDiffToDDL} to create SQL for the
  76. * differences and then executes the returned SQL statements on the
  77. * database handler $db.
  78. *
  79. * @todo check for failed transaction
  80. *
  81. * @param ezcDbHandler $db
  82. * @param ezcDbSchemaDiff $dbSchemaDiff
  83. */
  84. public function applyDiffToDb( ezcDbHandler $db, ezcDbSchemaDiff $dbSchemaDiff )
  85. {
  86. $db->beginTransaction();
  87. foreach ( $this->convertDiffToDDL( $dbSchemaDiff ) as $query )
  88. {
  89. $db->exec( $query );
  90. }
  91. $db->commit();
  92. }
  93. /**
  94. * Returns the differences definition in $dbSchema as database specific SQL DDL queries.
  95. *
  96. * @param ezcDbSchemaDiff $dbSchemaDiff
  97. *
  98. * @return array(string)
  99. */
  100. public function convertDiffToDDL( ezcDbSchemaDiff $dbSchemaDiff )
  101. {
  102. $this->diffSchema = $dbSchemaDiff;
  103. // reset queries
  104. $this->queries = array();
  105. $this->context = array();
  106. $this->generateDiffSchemaAsSql();
  107. return $this->queries;
  108. }
  109. /**
  110. * Adds a "drop table" query for the table $tableName to the internal list of queries.
  111. *
  112. * @param string $tableName
  113. */
  114. protected function generateDropTableSql( $tableName )
  115. {
  116. $this->queries[] = "DROP TABLE IF EXISTS `$tableName`";
  117. }
  118. /**
  119. * Converts the generic field type contained in $fieldDefinition to a database specific field definition.
  120. *
  121. * @param ezcDbSchemaField $fieldDefinition
  122. * @return string
  123. */
  124. protected function convertFromGenericType( ezcDbSchemaField $fieldDefinition )
  125. {
  126. $typeAddition = '';
  127. if ( in_array( $fieldDefinition->type, array( 'decimal', 'text' ) ) )
  128. {
  129. if ( $fieldDefinition->length !== false && $fieldDefinition->length !== 0 )
  130. {
  131. $typeAddition = "({$fieldDefinition->length})";
  132. }
  133. }
  134. if ( $fieldDefinition->type == 'text' && !$fieldDefinition->length )
  135. {
  136. $typeAddition = "(255)";
  137. }
  138. if ( !isset( $this->typeMap[$fieldDefinition->type] ) )
  139. {
  140. throw new ezcDbSchemaUnsupportedTypeException( 'MySQL', $fieldDefinition->type );
  141. }
  142. $type = $this->typeMap[$fieldDefinition->type];
  143. return "$type$typeAddition";
  144. }
  145. /**
  146. * Returns a "CREATE TABLE" SQL statement part for the table $tableName.
  147. *
  148. * @param string $tableName
  149. * @return string
  150. */
  151. protected function generateCreateTableSqlStatement( $tableName )
  152. {
  153. return "CREATE TABLE `{$tableName}`";
  154. }
  155. /**
  156. * Adds a "create table" query for the table $tableName with definition $tableDefinition to the internal list of queries.
  157. *
  158. * @param string $tableName
  159. * @param ezcDbSchemaTable $tableDefinition
  160. */
  161. protected function generateCreateTableSql( $tableName, ezcDbSchemaTable $tableDefinition )
  162. {
  163. $this->context['skip_primary'] = false;
  164. parent::generateCreateTableSql( $tableName, $tableDefinition );
  165. }
  166. /**
  167. * Generates queries to upgrade a the table $tableName with the differences in $tableDiff.
  168. *
  169. * This method generates queries to migrate a table to a new version
  170. * with the changes that are stored in the $tableDiff property. It
  171. * will call different subfunctions for the different types of changes, and
  172. * those functions will add queries to the internal list of queries that is
  173. * stored in $this->queries.
  174. *
  175. * @param string $tableName
  176. * @param ezcDbSchemaTableDiff $tableDiff
  177. */
  178. protected function generateDiffSchemaTableAsSql( $tableName, ezcDbSchemaTableDiff $tableDiff )
  179. {
  180. $this->context['skip_primary'] = false;
  181. parent::generateDiffSchemaTableAsSql( $tableName, $tableDiff );
  182. }
  183. /**
  184. * Adds a "alter table" query to add the field $fieldName to $tableName with the definition $fieldDefinition.
  185. *
  186. * @param string $tableName
  187. * @param string $fieldName
  188. * @param ezcDbSchemaField $fieldDefinition
  189. */
  190. protected function generateAddFieldSql( $tableName, $fieldName, ezcDbSchemaField $fieldDefinition )
  191. {
  192. $this->queries[] = "ALTER TABLE `$tableName` ADD " . $this->generateFieldSql( $fieldName, $fieldDefinition );
  193. }
  194. /**
  195. * Adds a "alter table" query to change the field $fieldName to $tableName with the definition $fieldDefinition.
  196. *
  197. * @param string $tableName
  198. * @param string $fieldName
  199. * @param ezcDbSchemaField $fieldDefinition
  200. */
  201. protected function generateChangeFieldSql( $tableName, $fieldName, ezcDbSchemaField $fieldDefinition )
  202. {
  203. $this->queries[] = "ALTER TABLE `$tableName` CHANGE `$fieldName` " . $this->generateFieldSql( $fieldName, $fieldDefinition );
  204. }
  205. /**
  206. * Adds a "alter table" query to drop the field $fieldName from $tableName.
  207. *
  208. * @param string $tableName
  209. * @param string $fieldName
  210. */
  211. protected function generateDropFieldSql( $tableName, $fieldName )
  212. {
  213. $this->queries[] = "ALTER TABLE `$tableName` DROP `$fieldName`";
  214. }
  215. /**
  216. * Returns a column definition for $fieldName with definition $fieldDefinition.
  217. *
  218. * @param string $fieldName
  219. * @param ezcDbSchemaField $fieldDefinition
  220. * @return string
  221. */
  222. protected function generateFieldSql( $fieldName, ezcDbSchemaField $fieldDefinition )
  223. {
  224. $sqlDefinition = "`$fieldName` ";
  225. $defList = array();
  226. $type = $this->convertFromGenericType( $fieldDefinition );
  227. $defList[] = $type;
  228. if ( $fieldDefinition->notNull )
  229. {
  230. $defList[] = 'NOT NULL';
  231. }
  232. if ( $fieldDefinition->autoIncrement )
  233. {
  234. $defList[] = "AUTO_INCREMENT PRIMARY KEY";
  235. $this->context['skip_primary'] = true;
  236. }
  237. if ( !is_null( $fieldDefinition->default ) && !$fieldDefinition->autoIncrement )
  238. {
  239. $default = $this->generateDefault( $fieldDefinition->type, $fieldDefinition->default );
  240. $defList[] = "DEFAULT $default";
  241. }
  242. $sqlDefinition .= join( ' ', $defList );
  243. return $sqlDefinition;
  244. }
  245. /**
  246. * Adds a "alter table" query to add the index $indexName to the table $tableName with definition $indexDefinition to the internal list of queries
  247. *
  248. * @param string $tableName
  249. * @param string $indexName
  250. * @param ezcDbSchemaIndex $indexDefinition
  251. */
  252. protected function generateAddIndexSql( $tableName, $indexName, ezcDbSchemaIndex $indexDefinition )
  253. {
  254. $sql = "ALTER TABLE `$tableName` ADD ";
  255. if ( $indexDefinition->primary )
  256. {
  257. if ( $this->context['skip_primary'] )
  258. {
  259. return;
  260. }
  261. $sql .= 'PRIMARY KEY';
  262. }
  263. else if ( $indexDefinition->unique )
  264. {
  265. $sql .= "UNIQUE `$indexName`";
  266. }
  267. else
  268. {
  269. $sql .= "INDEX `$indexName`";
  270. }
  271. $sql .= " ( ";
  272. $indexFieldSql = array();
  273. foreach ( $indexDefinition->indexFields as $indexFieldName => $dummy )
  274. {
  275. if ( isset( $this->schema[$tableName] ) &&
  276. isset( $this->schema[$tableName]->fields[$indexFieldName] ) &&
  277. isset( $this->schema[$tableName]->fields[$indexFieldName]->type ) &&
  278. in_array( $this->schema[$tableName]->fields[$indexFieldName]->type, array( 'blob', 'clob' ) ) )
  279. {
  280. $indexFieldSql[] = "`{$indexFieldName}`(250)";
  281. }
  282. else
  283. {
  284. $indexFieldSql[] = "`$indexFieldName`";
  285. }
  286. }
  287. $sql .= join( ', ', $indexFieldSql ) . " )";
  288. $this->queries[] = $sql;
  289. }
  290. /**
  291. * Adds a "alter table" query to remote the index $indexName from the table $tableName to the internal list of queries.
  292. *
  293. * @param string $tableName
  294. * @param string $indexName
  295. */
  296. protected function generateDropIndexSql( $tableName, $indexName )
  297. {
  298. $this->queries[] = "ALTER TABLE `$tableName` DROP INDEX `$indexName`";
  299. }
  300. }
  301. ?>