PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/Varien/Db/Ddl/Table.php

https://bitbucket.org/claudiu_marginean/magento-hg-mirror
PHP | 567 lines | 310 code | 45 blank | 212 comment | 36 complexity | 395911ce48769538453a38e8999aa3d6 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Varien
  22. * @package Varien_Db
  23. * @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Data Definition for table
  28. *
  29. * @category Varien
  30. * @package Varien_Db
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Varien_Db_Ddl_Table
  34. {
  35. const TYPE_BOOLEAN = 'boolean';
  36. const TYPE_TINYINT = 'tinyint';
  37. const TYPE_SMALLINT = 'smallint';
  38. const TYPE_INTEGER = 'integer';
  39. const TYPE_BIGINT = 'bigint';
  40. const TYPE_DOUBLE = 'double';
  41. const TYPE_FLOAT = 'float';
  42. const TYPE_REAL = 'real';
  43. const TYPE_NUMERIC = 'numeric';
  44. const TYPE_DECIMAL = 'decimal';
  45. const TYPE_DATE = 'date';
  46. const TYPE_TIME = 'time';
  47. const TYPE_TIMESTAMP = 'timestamp';
  48. const TYPE_CHAR = 'char';
  49. const TYPE_VARCHAR = 'varchar';
  50. const TYPE_LONGVARCHAR = 'longvarchar';
  51. const TYPE_CLOB = 'cblob';
  52. const TYPE_BINARY = 'binary';
  53. const TYPE_VARBINARY = 'varbinary';
  54. const TYPE_LONGVARBINARY = 'longvarbinary';
  55. const TYPE_BLOB = 'blob';
  56. const ACTION_CASCADE = 'CASCADE';
  57. const ACTION_SET_NULL = 'SET NULL';
  58. const ACTION_NO_ACTION = 'NO ACTION';
  59. const ACTION_RESTRICT = 'RESTRICT';
  60. const ACTION_SET_DEFAULT = 'SET DEFAULT';
  61. /**
  62. * Name of table
  63. *
  64. * @var string
  65. */
  66. protected $_tableName;
  67. /**
  68. * Column descriptions for a table
  69. *
  70. * Is an associative array keyed by the uppercase column name
  71. * The value of each array element is an associative array
  72. * with the following keys:
  73. *
  74. * COLUMN_NAME => string; column name
  75. * COLUMN_POSITION => number; ordinal position of column in table
  76. * DATA_TYPE => string; constant datatype of column
  77. * DEFAULT => string; default expression of column, null if none
  78. * NULLABLE => boolean; true if column can have nulls
  79. * LENGTH => number; length of CHAR/VARCHAR/INT
  80. * SCALE => number; scale of NUMERIC/DECIMAL
  81. * PRECISION => number; precision of NUMERIC/DECIMAL
  82. * UNSIGNED => boolean; unsigned property of an integer type
  83. * PRIMARY => boolean; true if column is part of the primary key
  84. * PRIMARY_POSITION => integer; position of column in primary key
  85. * IDENTITY => integer; true if column is auto-generated with unique values
  86. *
  87. * @var array
  88. */
  89. protected $_columns = array();
  90. /**
  91. * Index descriptions for a table
  92. *
  93. * Is an associative array keyed by the uppercase index name
  94. * The value of each array element is an associative array
  95. * with the following keys:
  96. *
  97. * INDEX_NAME => string; index name
  98. * UNIQUE => boolean; true if unique index
  99. * COLUMNS => array; array of index columns
  100. * TYPE => string; Optional special index type
  101. *
  102. * COLUMNS is an associative array keyed by the uppercase column name
  103. * The value of each COLUMNS array element is an associative array
  104. * with the following keys:
  105. *
  106. * NAME => string; The column name
  107. * SIZE => int|null; Length of index column (always null if index is unique)
  108. * POSITION => int; Position in index
  109. *
  110. * @var array
  111. */
  112. protected $_indexes = array();
  113. /**
  114. * Foreign key descriptions for a table
  115. *
  116. * Is an associative array keyed by the uppercase foreign key name
  117. * The value of each array element is an associative array
  118. * with the following keys:
  119. *
  120. * FK_NAME => string; The foreign key name
  121. * COLUMN_NAME => string; The column name in table
  122. * REF_TABLE_NAME => string; Reference table name
  123. * REF_COLUMN_NAME => string; Reference table column name
  124. * ON_DELETE => string; Integrity Actions, default NO ACTION
  125. * ON_UPDATE => string; Integrity Actions, default NO ACTION
  126. *
  127. * Valid Integrity Actions:
  128. * CASCADE | SET NULL | NONE | RESTRICT | SET DEFAULT
  129. *
  130. * @var array
  131. */
  132. protected $_foreignKeys = array();
  133. /**
  134. * Additional table options
  135. *
  136. * @var array
  137. */
  138. protected $_options = array(
  139. 'type' => 'INNODB',
  140. 'charset' => 'utf8',
  141. 'collate' => 'utf8_unicode_ci',
  142. 'description' => null
  143. );
  144. /**
  145. * Set table name
  146. *
  147. * @param string $name
  148. * @return Varien_Db_Ddl_Table
  149. */
  150. public function setName($name)
  151. {
  152. $this->_tableName = $name;
  153. return $this;
  154. }
  155. /**
  156. * Retrieve name of table
  157. *
  158. * @throws Zend_Db_Exception
  159. * @return string
  160. */
  161. public function getName()
  162. {
  163. if (is_null($this->_tableName)) {
  164. throw new Zend_Db_Exception('Table name is not defined');
  165. }
  166. return $this->_tableName;
  167. }
  168. /**
  169. * Add column to table
  170. *
  171. * @param string $name the column name
  172. * @param string $type the column data type
  173. * @param string|int $length the column length
  174. * @param array $options array of additional options
  175. * @throws Zend_Db_Exception
  176. * @return Varien_Db_Ddl_Table
  177. */
  178. public function addColumn($name, $type, $size = null, $options = array())
  179. {
  180. $position = count($this->_columns);
  181. $default = null;
  182. $nullable = true;
  183. $length = null;
  184. $scale = null;
  185. $precision = null;
  186. $unsigned = false;
  187. $primary = false;
  188. $primaryPosition = 0;
  189. $identity = false;
  190. switch ($type) {
  191. case self::TYPE_BOOLEAN:
  192. break;
  193. case self::TYPE_TINYINT:
  194. case self::TYPE_SMALLINT:
  195. case self::TYPE_INTEGER:
  196. case self::TYPE_BIGINT:
  197. if (!empty($options['unsigned'])) {
  198. $unsigned = true;
  199. }
  200. $length = $size;
  201. break;
  202. case self::TYPE_DOUBLE:
  203. case self::TYPE_FLOAT:
  204. if (!empty($options['unsigned'])) {
  205. $unsigned = true;
  206. }
  207. break;
  208. case self::TYPE_REAL:
  209. break;
  210. case self::TYPE_DECIMAL:
  211. case self::TYPE_NUMERIC:
  212. $match = array();
  213. $scale = 10;
  214. $precision = 0;
  215. // parse size value
  216. if (is_array($size)) {
  217. if (count($size) == 2) {
  218. $size = array_values($size);
  219. $scale = $size[0];
  220. $precision = $size[1];
  221. }
  222. } else if (preg_match('#^(\d+),(\d+)$#', $size, $match)) {
  223. $scale = $match[1];
  224. $precision = $match[2];
  225. }
  226. // check options
  227. if (isset($options['precision'])) {
  228. $scale = $options['precision'];
  229. }
  230. if (isset($options['precision'])) {
  231. $precision = $options['precision'];
  232. }
  233. if (!empty($options['unsigned'])) {
  234. $unsigned = true;
  235. }
  236. break;
  237. case self::TYPE_DATE:
  238. case self::TYPE_TIME:
  239. case self::TYPE_TIMESTAMP:
  240. break;
  241. case self::TYPE_CHAR:
  242. case self::TYPE_VARCHAR:
  243. case self::TYPE_LONGVARCHAR:
  244. case self::TYPE_CLOB:
  245. case self::TYPE_BINARY:
  246. case self::TYPE_VARBINARY:
  247. case self::TYPE_LONGVARBINARY:
  248. case self::TYPE_BLOB:
  249. if (!is_null($size)) {
  250. $length = $size;
  251. }
  252. break;
  253. default:
  254. throw new Zend_Db_Exception('Invalid column data type "' . $type . '"');
  255. }
  256. if (array_key_exists('default', $options)) {
  257. $default = $options['default'];
  258. }
  259. if (array_key_exists('nullable', $options)) {
  260. $nullable = (bool)$options['nullable'];
  261. }
  262. if (!empty($options['primary'])) {
  263. $primary = true;
  264. if (isset($options['primary_position'])) {
  265. $primaryPosition = (int)$options['primary_position'];
  266. } else {
  267. $primaryPosition = 0;
  268. foreach ($this->_columns as $v) {
  269. if ($v['PRIMARY']) {
  270. $primaryPosition ++;
  271. }
  272. }
  273. }
  274. }
  275. if (!empty($options['identity']) || !empty($options['auto_increment'])) {
  276. $identity = true;
  277. }
  278. $upperName = strtoupper($name);
  279. $this->_columns[$upperName] = array(
  280. 'COLUMN_NAME' => $name,
  281. 'COLUMN_TYPE' => $type,
  282. 'COLUMN_POSITION' => $position,
  283. 'DATA_TYPE' => $type,
  284. 'DEFAULT' => $default,
  285. 'NULLABLE' => $nullable,
  286. 'LENGTH' => $length,
  287. 'SCALE' => $scale,
  288. 'PRECISION' => $precision,
  289. 'UNSIGNED' => $unsigned,
  290. 'PRIMARY' => $primary,
  291. 'PRIMARY_POSITION' => $primaryPosition,
  292. 'IDENTITY' => $identity
  293. );
  294. return $this;
  295. }
  296. /**
  297. * Add Foreign Key to table
  298. *
  299. * @param string $fkName the foreign key name
  300. * @param string $column the foregn key column name
  301. * @param string $refTable the reference table name
  302. * @param string $refColumn the reference table column name
  303. * @param string $onDelete the action on delete row
  304. * @param string $onUpdate the action on update
  305. * @throws Zend_Db_Exception
  306. * @return Varien_Db_Ddl_Table
  307. */
  308. public function addForeignKey($fkName, $column, $refTable, $refColumn, $onDelete = null, $onUpdate = null)
  309. {
  310. $upperName = strtoupper($fkName);
  311. // validate column name
  312. if (!isset($this->_columns[strtoupper($column)])) {
  313. throw new Zend_Db_Exception('Undefined column "' . $column . '"');
  314. }
  315. switch ($onDelete) {
  316. case self::ACTION_CASCADE:
  317. case self::ACTION_RESTRICT:
  318. case self::ACTION_SET_DEFAULT:
  319. case self::ACTION_SET_NULL:
  320. break;
  321. default:
  322. $onDelete = self::ACTION_NO_ACTION;
  323. }
  324. switch ($onUpdate) {
  325. case self::ACTION_CASCADE:
  326. case self::ACTION_RESTRICT:
  327. case self::ACTION_SET_DEFAULT:
  328. case self::ACTION_SET_NULL:
  329. break;
  330. default:
  331. $onUpdate = self::ACTION_NO_ACTION;
  332. }
  333. $this->_foreignKeys[$upperName] = array(
  334. 'FK_NAME' => $fkName,
  335. 'COLUMN_NAME' => $column,
  336. 'REF_TABLE_NAME' => $refTable,
  337. 'REF_COLUMN_NAME' => $refColumn,
  338. 'ON_DELETE' => $onDelete,
  339. 'ON_UPDATE' => $onUpdate
  340. );
  341. return $this;
  342. }
  343. /**
  344. * Add index to table
  345. *
  346. * @param string $indexName the index name
  347. * @param array|string $columns array of columns or column string
  348. * @param array $options array of additional options
  349. * @return Varien_Db_Ddl_Table
  350. */
  351. public function addIndex($indexName, $fields, $options = array())
  352. {
  353. $idxType = null;
  354. $unique = false;
  355. $position = 0;
  356. $columns = array();
  357. if (!is_array($fields)) {
  358. $fields = array($fields);
  359. }
  360. foreach ($fields as $columnData) {
  361. $columnSize = null;
  362. $columnPos = $position;
  363. if (is_string($columnData)) {
  364. $columnName = $columnData;
  365. } else if (is_array($columnData)) {
  366. if (!isset($columnData['name'])) {
  367. throw new Zend_Db_Exception('Invalid index column data');
  368. }
  369. $columnName = $columnData['name'];
  370. if (!empty($columnData['size'])) {
  371. $columnSize = (int)$columnData['size'];
  372. }
  373. if (!empty($columnData['position'])) {
  374. $columnPos = (int)$columnData['position'];
  375. }
  376. } else {
  377. continue;
  378. }
  379. $columns[strtoupper($columnName)] = array(
  380. 'NAME' => $columnName,
  381. 'SIZE' => $columnSize,
  382. 'POSITION' => $columnPos
  383. );
  384. $position ++;
  385. }
  386. if (empty($columns)) {
  387. throw new Zend_Db_Exception('Columns for index are not defined');
  388. }
  389. if (!empty($options['unique'])) {
  390. $unique = true;
  391. }
  392. if (!empty($options['type'])) {
  393. $idxType = $options['type'];
  394. }
  395. $this->_indexes[strtoupper($indexName)] = array(
  396. 'INDEX_NAME' => $indexName,
  397. 'UNIQUE' => $unique,
  398. 'COLUMNS' => $this->_normalizeIndexColumnPosition($columns),
  399. 'TYPE' => $idxType
  400. );
  401. return $this;
  402. }
  403. /**
  404. * Retrieve array of table columns
  405. *
  406. * @see $this->_columns
  407. * @return array
  408. */
  409. public function getColumns()
  410. {
  411. return $this->_normalizeColumnPosition($this->_columns);
  412. }
  413. /**
  414. * Retrieve array of table indexes
  415. *
  416. * @see $this->_indexes
  417. * @return array
  418. */
  419. public function getIndexes()
  420. {
  421. return $this->_indexes;
  422. }
  423. /**
  424. * Retrieve array of table foreign keys
  425. *
  426. * @see $this->_foreignKeys
  427. * @return array
  428. */
  429. public function getForeignKeys()
  430. {
  431. return $this->_foreignKeys;
  432. }
  433. /**
  434. * Set table option
  435. *
  436. * @param string $key
  437. * @param string $value
  438. * @return string
  439. */
  440. public function setOption($key, $value)
  441. {
  442. $this->_options[$key] = $value;
  443. return $this;
  444. }
  445. /**
  446. * Retrieve table option value by option name
  447. * Return null if option does not exits
  448. *
  449. * @param string $key
  450. * @return mixed
  451. */
  452. public function getOption($key)
  453. {
  454. if (!isset($this->_options[$key])) {
  455. return null;
  456. }
  457. return $this->_options[$key];
  458. }
  459. /**
  460. * Retrieve array of table options
  461. *
  462. * @return array
  463. */
  464. public function getOptions()
  465. {
  466. return $this->_options;
  467. }
  468. /**
  469. * Index column position comparison function
  470. *
  471. * @param array $a
  472. * @param array $b
  473. * @return int
  474. */
  475. protected function _sortIndexColumnPosition($a, $b)
  476. {
  477. return $a['POSITION'] - $b['POSITION'];
  478. }
  479. /**
  480. * table column position comparison function
  481. *
  482. * @param array $a
  483. * @param array $b
  484. * @return int
  485. */
  486. protected function _sortColumnPosition($a, $b)
  487. {
  488. return $a['COLUMN_POSITION'] - $b['COLUMN_POSITION'];
  489. }
  490. /**
  491. * Normalize positon of index columns array
  492. *
  493. * @param array $columns
  494. * @return array
  495. */
  496. protected function _normalizeIndexColumnPosition($columns)
  497. {
  498. uasort($columns, array($this, '_sortIndexColumnPosition'));
  499. $position = 0;
  500. foreach (array_keys($columns) as $columnId) {
  501. $columns[$columnId]['POSITION'] = $position;
  502. $position ++;
  503. }
  504. return $columns;
  505. }
  506. /**
  507. * Normalize positon of table columns array
  508. *
  509. * @param array $columns
  510. * @return array
  511. */
  512. protected function _normalizeColumnPosition($columns)
  513. {
  514. uasort($columns, array($this, '_sortColumnPosition'));
  515. $position = 0;
  516. foreach (array_keys($columns) as $columnId) {
  517. $columns[$columnId]['COLUMN_POSITION'] = $position;
  518. $position ++;
  519. }
  520. return $columns;
  521. }
  522. }