PageRenderTime 42ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/jelix/plugins/db/mysql/mysql.dbschema.php

https://github.com/foxmask/Booster
PHP | 304 lines | 221 code | 51 blank | 32 comment | 64 complexity | 0dc318e4449cfa484bfe8c680f0b3b84 MD5 | raw file
  1. <?php
  2. /**
  3. * @package jelix
  4. * @subpackage db
  5. * @author Laurent Jouanneau
  6. * @copyright 2005-2010 Laurent Jouanneau
  7. * @link http://www.jelix.org
  8. * @licence http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public Licence, see LICENCE file
  9. */
  10. /**
  11. *
  12. * @package jelix
  13. * @subpackage db_driver
  14. */
  15. class mysqlDbTable extends jDbTable {
  16. public $attributes = array();
  17. protected function _loadColumns() {
  18. $this->columns = array ();
  19. $this->primaryKey = false;
  20. $conn = $this->schema->getConn();
  21. $tools = $conn->tools();
  22. $rs = $conn->query ('SHOW FIELDS FROM '.$conn->encloseName($this->name));
  23. while ($line = $rs->fetch ()) {
  24. $length = 0;
  25. if (preg_match('/^(\w+)\s*(\((\d+)\))?.*$/',$line->Type,$m)) {
  26. $type = strtolower($m[1]);
  27. if ($type == 'varchar' && isset($m[3])) {
  28. $length = intval($m[3]);
  29. }
  30. } else {
  31. $type = $line->Type;
  32. }
  33. $notNull = ($line->Null == 'NO');
  34. $autoIncrement = ($line->Extra == 'auto_increment');
  35. $hasDefault = ($line->Default != '' || !($line->Default == null && $notNull));
  36. // to fix a bug in php 5.2.5 or mysql 5.0.51
  37. if($notNull && $line->Default === null && !$autoIncrement)
  38. $default ='';
  39. else
  40. $default = $line->Default;
  41. $col = new jDbColumn($line->Field, $type, $length, $hasDefault, $default, $notNull);
  42. $col->autoIncrement = $autoIncrement;
  43. $typeinfo = $tools->getTypeInfo($type);
  44. //$col->unifiedType = $typeinfo[1];
  45. $col->maxValue = $typeinfo[3];
  46. $col->minValue = $typeinfo[2];
  47. $col->maxLength = $typeinfo[5];
  48. $col->minLength = $typeinfo[4];
  49. if ($col->length !=0)
  50. $col->maxLength = $col->length;
  51. if ($line->Key == 'PRI') {
  52. if (!$this->primaryKey)
  53. $this->primaryKey = new jDbPrimaryKey($line->Field);
  54. else
  55. $this->primaryKey->columns[] = $line->Field;
  56. }
  57. $this->columns[$line->Field] = $col;
  58. }
  59. }
  60. protected function _alterColumn(jDbColumn $old, jDbColumn $new) {
  61. $conn = $this->schema->getConn();
  62. $pk = $this->getPrimaryKey();
  63. $isPk = ($pk && in_array($new->name, $pk->columns));
  64. $sql = 'ALTER TABLE '.$conn->encloseName($this->name)
  65. .' CHANGE COLUMN '.$conn->encloseName($old->name)
  66. .' '.$this->schema->_prepareSqlColumn($new);
  67. if ($isPk && $col->autoIncrement)
  68. $sql .= ' AUTO_INCREMENT';
  69. $conn->exec($sql);
  70. }
  71. protected function _addColumn(jDbColumn $new) {
  72. $conn = $this->schema->getConn();
  73. $pk = $this->getPrimaryKey();
  74. $isPk = ($pk && in_array($new->name, $pk->columns));
  75. $sql = 'ALTER TABLE '.$conn->encloseName($this->name)
  76. .' ADD COLUMN '.$this->schema->_prepareSqlColumn($new);
  77. if ($isPk && $col->autoIncrement)
  78. $sql .= ' AUTO_INCREMENT';
  79. $conn->exec($sql);
  80. }
  81. protected function _loadIndexesAndKeys() {
  82. $conn = $this->schema->getConn();
  83. $rs = $conn->query('SHOW INDEX FROM '.$conn->encloseName($this->name));
  84. $this->uniqueKeys = $this->indexes = array();
  85. $this->primaryKey = false;
  86. while ($idx = $rs->fetch ()) {
  87. if ($idx->Key_name == 'PRIMARY') {
  88. if (!$this->primaryKey)
  89. $this->primaryKey = new jDbPrimaryKey($idx->Column_name);
  90. else
  91. $this->primaryKey->columns[$idx->Seq_in_index-1] = $idx->Column_name;
  92. }
  93. else if ($idx->Non_unique == 0) {
  94. if(!isset($this->uniqueKeys[$idx->Key_name])) {
  95. $this->uniqueKeys[$idx->Key_name] = new jDbUniqueKey($idx->Key_name);
  96. }
  97. $this->uniqueKeys[$idx->Key_name]->columns[$idx->Seq_in_index-1] = $idx->Column_name;
  98. }
  99. else {
  100. if(!isset($this->indexes[$idx->Key_name])) {
  101. $this->indexes[$idx->Key_name] = new jDbIndex($idx->Key_name, $idx->Index_type);
  102. }
  103. $this->indexes[$idx->Key_name]->columns[$idx->Seq_in_index-1] = $idx->Column_name;
  104. }
  105. }
  106. }
  107. protected function _createIndex(jDbIndex $index) {
  108. $conn = $this->schema->getConn();
  109. $sql = 'ALTER TABLE '.$conn->encloseName($this->name).' ADD ';
  110. if ($index instanceof jDbPrimaryKey) {
  111. $sql .= 'PRIMARY KEY';
  112. }
  113. else if ($index instanceof jDbUniqueKey) {
  114. $sql .= 'CONSTRAINT UNIQUE KEY '.$conn->encloseName($index->name);
  115. }
  116. else {
  117. $sql .= 'INDEX '.$conn->encloseName($index->name);
  118. if ($index->type != '')
  119. $sql.= ' USING '.$index->type;
  120. }
  121. $f = '';
  122. foreach ($index->columns as $col) {
  123. $f .= ','.$conn->encloseName($col);
  124. }
  125. $conn->exec($sql.'('.substr($f,1).')');
  126. }
  127. protected function _dropIndex(jDbIndex $index) {
  128. $conn = $this->schema->getConn();
  129. $sql = 'ALTER TABLE '.$conn->encloseName($this->name).' DROP ';
  130. if ($index instanceof jDbPrimaryKey) {
  131. $sql .= 'PRIMARY KEY';
  132. }
  133. else {
  134. $sql .= 'INDEX '.$conn->encloseName($index->name);
  135. }
  136. $conn->exec($sql);
  137. }
  138. protected function _loadReferences() {
  139. $conn = $this->schema->getConn();
  140. $sql = 'SHOW CREATE TABLE '.$conn->encloseName($this->name);
  141. $rs = $conn->query($sql);
  142. $rec = $rs->fetch();
  143. /*
  144. CONSTRAINT [symbol] FOREIGN KEY [index_name] (col_name [(length)] [ASC | DESC],...)
  145. REFERENCES tbl_name (col_name [(length)] [ASC | DESC],...)
  146. [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
  147. [ON DELETE RESTRICT | CASCADE | SET NULL | NO ACTION]
  148. [ON UPDATE RESTRICT | CASCADE | SET NULL | NO ACTION]
  149. */
  150. preg_match_all('/^\s*(?:CONSTRAINT(?:\s+`(.+?)`)?\s+)?FOREIGN\s+KEY(?:\s+`(.+?)`)?\s+\((.+?)\)\s+REFERENCES\s+`(.+?)`\s+\((.+?)\)(?:\s+MATCH\s+(FULL|PARTIAL|SIMPLE))?(?:\s+ON DELETE\s+(RESTRICT|CASCADE|SET NULL|NO ACTION))?(?:\s+ON UPDATE\s+(RESTRICT|CASCADE|SET NULL|NO ACTION))?,?$/msi', $s, $m);
  151. foreach ($m[1] as $i => $symbol) {
  152. //$match = $m[6][$i];
  153. $ref = new jDbReference();
  154. $ref->name = ($m[2][$i] != ''?$m[2][$i]:$symbol) ;
  155. $ref->fTable = $m[4][$i];
  156. $ref->onDelete = $m[7][$i];
  157. $ref->onUpdate = $m[8][$i];
  158. if (preg_match_all('/`([^`]+)`/', $m[3][$i], $mc))
  159. $ref->columns = $mc[1];
  160. if (preg_match_all('/`([^`]+)`/', $m[5][$i], $mc))
  161. $ref->fColumns = $mc[1];
  162. if ($ref->name && count($ref->columns) && count($ref->fColumns))
  163. $this->references[$ref->name] = $ref;
  164. }
  165. }
  166. protected function _createReference(jDbReference $ref) {
  167. $conn = $this->schema->getConn();
  168. $sql = 'ALTER TABLE '.$conn->encloseName($this->name).' ADD CONSTRAINT ';
  169. $sql.= $conn->encloseName($ref->name). ' FOREIGN KEY (';
  170. $cols = array();
  171. $fcols = array();
  172. foreach ($ref->columns as $c) {
  173. $cols[] = $conn->encloseName($c);
  174. }
  175. foreach ($ref->fColumns as $c) {
  176. $fcols[] = $conn->encloseName($c);
  177. }
  178. $sql .= impode(',', $cols).') REFERENCES '.$conn->encloseName($ref->fTable).'(';
  179. $sql .= implode(',', $fcols).')';
  180. if ($ref->onUpdate) {
  181. $sql .= 'ON UPDATE '.$ref->onUpdate.' ';
  182. }
  183. if ($ref->onDelete) {
  184. $sql .= 'ON DELETE '.$ref->onDelete.' ';
  185. }
  186. $conn->exec($sql);
  187. }
  188. protected function _dropReference(jDbReference $ref) {
  189. $conn = $this->schema->getConn();
  190. $sql = 'ALTER TABLE '.$conn->encloseName($this->name).' DROP FOREIGN KEY '.$conn->encloseName($ref->name);
  191. $conn->exec($sql);
  192. }
  193. }
  194. /**
  195. *
  196. * @package jelix
  197. * @subpackage db_driver
  198. */
  199. class mysqlDbSchema extends jDbSchema {
  200. /**
  201. * @param string $name
  202. * @param array[jDbColumn] $columns
  203. */
  204. function _createTable($name, $columns, $primaryKey, $attributes=array()) {
  205. $cols = array();
  206. if (is_string($primaryKey))
  207. $primaryKey = array($primaryKey);
  208. foreach ($columns as $col) {
  209. $colstr = $this->_prepareSqlColumn($col);
  210. if (in_array($col->name, $primaryKey) && $col->autoIncrement) {
  211. $colstr .= ' AUTO_INCREMENT';
  212. }
  213. $cols[] = $colstr;
  214. }
  215. $sql = 'CREATE TABLE '.$this->conn->encloseName($name).' ('.implode(", ",$cols);
  216. if (count($primaryKey))
  217. $sql .= ', PRIMARY KEY ('.implode(',', $primaryKey).')';
  218. $sql .= ')';
  219. if (isset($attributes['engine'])) {
  220. $sql.= ' ENGINE='.$attributes['engine'];
  221. }
  222. if (isset($attributes['charset'])) {
  223. $sql.= ' CHARACTER SET '.$attributes['charset'];
  224. }
  225. if (isset($attributes['collate'])) {
  226. $sql.= ' COLLATE '.$attributes['collate'];
  227. }
  228. $this->conn->exec($sql);
  229. $table = new mysqlDbTable($name, $this);
  230. $table->attributes = $attributes;
  231. return $table;
  232. }
  233. protected function _getTables() {
  234. $results = array ();
  235. $conn = $this->conn;
  236. if (isset($this->conn->profile['database'])) {
  237. $db = $this->conn->profile['database'];
  238. }
  239. else if (isset($this->conn->profile['dsn'])
  240. && preg_match('/dbname=([a-z0-9_ ]*)/', $this->conn->profile['dsn'], $m)){
  241. $db = $m[1];
  242. }
  243. else {
  244. throw new jException("jelix~error.no.database.name", $this->conn->profile['name']);
  245. }
  246. $rs = $this->conn->query ('SHOW TABLES FROM '.$this->conn->encloseName($db));
  247. $col_name = 'Tables_in_'.$db;
  248. while ($line = $rs->fetch ()){
  249. $results[$line->$col_name] = new mysqlDbTable($line->$col_name, $this);
  250. }
  251. return $results;
  252. }
  253. }