PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/system/schema/mysql/connection.php

https://github.com/HabariMag/habarimag-old
PHP | 276 lines | 208 code | 16 blank | 52 comment | 47 complexity | 5fe98a160c428aacffc559dcf4b2d86e MD5 | raw file
Possible License(s): Apache-2.0
  1. <?php
  2. /**
  3. * Habari database specific connection class
  4. *
  5. * @package Habari
  6. */
  7. class MySQLConnection extends DatabaseConnection
  8. {
  9. /**
  10. * Extends default connection method. It will be useful in order to
  11. * allow accents and other DB-centric global commands.
  12. *
  13. * @param string $connect_string a PDO connection string
  14. * @param string $db_user the database user name
  15. * @param string $db_pass the database user password
  16. * @return boolean true on success, false on error
  17. */
  18. public function connect ( $connect_string, $db_user, $db_pass )
  19. {
  20. // If something went wrong, we don't need to exec the specific commands.
  21. if ( !parent::connect( $connect_string, $db_user, $db_pass ) ) {
  22. return false;
  23. }
  24. $this->pdo->setAttribute( PDO::ATTR_EMULATE_PREPARES, true );
  25. // Everything is OK. Let's update the charset!
  26. if ( !defined('MYSQL_CHAR_SET') ) {
  27. define('MYSQL_CHAR_SET', 'UTF8');
  28. }
  29. // SET CHARACTER SET might get the character_set_connection wrong, thus we also need SET NAMES. See http://dev.mysql.com/doc/refman/5.0/en/charset-connection.html
  30. $this->exec('SET CHARACTER SET ' . MYSQL_CHAR_SET);
  31. $this->exec('SET NAMES ' . MYSQL_CHAR_SET);
  32. return true;
  33. }
  34. /**
  35. * Database specific SQL translation function, loosely modelled on the
  36. * internationalization _t() function.
  37. * Call with a database independent SQL string and it will be translated
  38. * to a MySQL specific SQL string.
  39. *
  40. * @param $sql database independent SQL
  41. * @return string translated SQL string
  42. * @todo Actually implement this.
  43. */
  44. function sql_t( $sql )
  45. {
  46. return $sql;
  47. }
  48. /**
  49. * automatic diffing function - used for determining required database upgrades
  50. * based on Owen Winkler's microwiki upgrade function
  51. *
  52. * @param queries array of create table and insert statements which constitute a fresh install
  53. * @param (optional) execute should the queries be executed against the database or just simulated. default = true
  54. * @param (optional) silent silent running with no messages printed? default = true
  55. * @param boolean $doinserts (optional) Execute all insert queries found, default=false
  56. * @return array list of updates made
  57. */
  58. function dbdelta( $queries, $execute = true, $silent = true, $doinserts = false )
  59. {
  60. $queries = preg_replace("/({\$prefix})/",$this->prefix,$queries); //Converts {$prefix}table_name to prefix__table_name
  61. $queries = $this->filter_tables( $queries ); //Converts {table_name} to prefix__table_name
  62. if ( !is_array($queries) ) {
  63. $queries = explode( ';', $queries );
  64. if ( '' == $queries[count($queries) - 1] ) {
  65. array_pop($queries);
  66. }
  67. }
  68. $cqueries = array();
  69. $iqueries = array();
  70. $for_update = array();
  71. $indices = array();
  72. foreach ( $queries as $qry ) {
  73. if ( preg_match("|CREATE TABLE\s+(\w*)|", $qry, $matches) ) {
  74. $cqueries[strtolower($matches[1])] = $qry;
  75. $for_update[$matches[1]] = 'Created table '.$matches[1];
  76. }
  77. else if ( preg_match("|CREATE DATABASE ([^ ]*)|", $qry, $matches) ) {
  78. array_unshift($cqueries, $qry);
  79. }
  80. else if ( preg_match("|INSERT INTO ([^ ]*)|", $qry, $matches) ) {
  81. $iqueries[] = $qry;
  82. }
  83. else if ( preg_match("|UPDATE ([^ ]*)|", $qry, $matches) ) {
  84. $iqueries[] = $qry;
  85. }
  86. else {
  87. // Unrecognized query type
  88. }
  89. }
  90. if ( $tables = $this->get_column('SHOW TABLES;') ) {
  91. foreach ( $tables as $table ) {
  92. if ( array_key_exists(strtolower($table), $cqueries) ) {
  93. unset($cfields);
  94. $cfields = array();
  95. unset($indices);
  96. $indices = array();
  97. preg_match("|\((.*)\)|ms", $cqueries[strtolower($table)], $match2);
  98. $qryline = trim($match2[1]);
  99. $flds = explode("\n", $qryline);
  100. foreach ( $flds as $fld ) {
  101. preg_match("|^([^ ]*)|", trim($fld), $fvals);
  102. $fieldname = $fvals[1];
  103. $validfield = true;
  104. switch ( strtolower($fieldname) ) {
  105. case '':
  106. case 'primary':
  107. case 'index':
  108. case 'fulltext':
  109. case 'unique':
  110. case 'key':
  111. $validfield = false;
  112. $indices[] = trim(trim($fld), ", \n");
  113. break;
  114. }
  115. $fld = trim($fld);
  116. if ( $validfield ) {
  117. $cfields[strtolower($fieldname)] = trim($fld, ", \n");
  118. }
  119. }
  120. $tablefields = $this->get_results("DESCRIBE {$table};");
  121. foreach ( (array)$tablefields as $tablefield ) {
  122. if ( array_key_exists(strtolower($tablefield->Field), $cfields) ) {
  123. preg_match("|".$tablefield->Field." ([^ ]*( unsigned)?)|i", $cfields[strtolower($tablefield->Field)], $matches);
  124. $fieldtype = $matches[1];
  125. // Use default field sizes
  126. $field_default_names = array('/(?'.'>\bint\s*)(?!\(.*$)/i','/(?'.'>smallint\s*)(?!\(.*$)/i','/(?'.'>tinyint\s*)(?!\(.*$)/i','/(?'.'>bigint\s*)(?!\(.*$)/i');
  127. $field_sized_names = array('int(10) ','smallint(5) ','tinyint(3) ','bigint(20) ');
  128. $fieldtype = preg_replace($field_default_names, $field_sized_names, $fieldtype);
  129. if ( strtolower($tablefield->Type) != strtolower($fieldtype) ) {
  130. $cqueries[] = "ALTER TABLE {$table} CHANGE COLUMN {$tablefield->Field} " . $cfields[strtolower($tablefield->Field)];
  131. $for_update[$table.'.'.$tablefield->Field] = "Changed type of {$table}.{$tablefield->Field} from {$tablefield->Type} to {$fieldtype}";
  132. }
  133. if ( preg_match("| DEFAULT ([^ ]*)|i", $cfields[strtolower($tablefield->Field)], $matches) ) {
  134. $default_value = $matches[1];
  135. if ( $tablefield->Default != $default_value ) {
  136. $cqueries[] = "ALTER TABLE {$table} ALTER COLUMN {$tablefield->Field} SET DEFAULT {$default_value}";
  137. $for_update[$table.'.'.$tablefield->Field] = "Changed default value of {$table}.{$tablefield->Field} from {$tablefield->Default} to {$default_value}";
  138. }
  139. }
  140. elseif ( strlen( $tablefield->Default) > 0 ) {
  141. $cqueries[] = "ALTER TABLE {$table} ALTER COLUMN {$tablefield->Field} DROP DEFAULT";
  142. $for_update[$table.'.'.$tablefield->Field] = "Dropped default value of {$table}.{$tablefield->Field}";
  143. }
  144. unset($cfields[strtolower($tablefield->Field)]);
  145. }
  146. else {
  147. // This field exists in the table, but not in the creation queries?
  148. }
  149. }
  150. foreach ( $cfields as $fieldname => $fielddef ) {
  151. $cqueries[] = "ALTER TABLE {$table} ADD COLUMN $fielddef";
  152. $for_update[$table.'.'.$fieldname] = 'Added column '.$table.'.'.$fieldname;
  153. }
  154. $tableindices = $this->get_results("SHOW INDEX FROM {$table};");
  155. if ( $tableindices ) {
  156. unset($index_ary);
  157. $index_ary = array();
  158. foreach ( $tableindices as $tableindex ) {
  159. $keyname = $tableindex->Key_name;
  160. $index_ary[$keyname]['columns'][] = array('fieldname' => $tableindex->Column_name, 'subpart' => $tableindex->Sub_part);
  161. $index_ary[$keyname]['unique'] = ($tableindex->Non_unique == 0)?true:false;
  162. }
  163. foreach ( $index_ary as $index_name => $index_data ) {
  164. $index_string = '';
  165. if ( $index_name == 'PRIMARY' ) {
  166. $index_string .= 'PRIMARY ';
  167. }
  168. else if ( $index_data['unique'] ) {
  169. $index_string .= 'UNIQUE ';
  170. }
  171. $index_string .= 'KEY ';
  172. if ( $index_name != 'PRIMARY' ) {
  173. $index_string .= $index_name;
  174. }
  175. $index_columns = '';
  176. foreach ( $index_data['columns'] as $column_data ) {
  177. if ( $index_columns != '' ) {
  178. $index_columns .= ',';
  179. }
  180. $index_columns .= $column_data['fieldname'];
  181. if ( $column_data['subpart'] != '' ) {
  182. $index_columns .= '('.$column_data['subpart'].')';
  183. }
  184. }
  185. $index_string = rtrim($index_string, ' ');
  186. $index_string .= ' ('.$index_columns.')';
  187. if ( !(($aindex = array_search($index_string, $indices)) === false) ) {
  188. unset($indices[$aindex]);
  189. }
  190. else {
  191. preg_match( '|(^.*)\((.*)\)|', $index_string, $matches );
  192. $tindextype = $matches[1];
  193. if ( preg_match( '/^KEY|UNIQUE KEY/i', $tindextype ) > 0 ) {
  194. $cqueries[] = "ALTER TABLE {$table} DROP INDEX {$index_name}";
  195. }
  196. else {
  197. $cqueries[] = "ALTER TABLE {$table} DROP PRIMARY KEY";
  198. }
  199. }
  200. }
  201. }
  202. foreach ( $indices as $index ) {
  203. $cqueries[] = "ALTER TABLE {$table} ADD $index";
  204. $for_update[$table.'.'.$fieldname] = 'Added index '.$table.' '.$index;
  205. }
  206. unset($cqueries[strtolower($table)]);
  207. unset($for_update[strtolower($table)]);
  208. }
  209. else {
  210. }
  211. }
  212. }
  213. $allqueries = $cqueries;
  214. if ( $doinserts ) {
  215. $allqueries = array_merge($allqueries, $iqueries);
  216. }
  217. if ( $execute ) {
  218. foreach ( $allqueries as $query ) {
  219. if ( !$this->exec($query) ) {
  220. $this->get_errors();
  221. return false;
  222. }
  223. }
  224. }
  225. if ( !$silent ) {
  226. if ( count($for_update) > 0) {
  227. echo "<ul>\n";
  228. foreach ( $for_update as $upgrade ) {
  229. echo "<li>{$upgrade}</li>\n";
  230. }
  231. echo "</ul>\n";
  232. }
  233. else {
  234. echo "<ul><li>" . _t('No Upgrades') . "</li></ul>";
  235. }
  236. }
  237. return $for_update;
  238. }
  239. /**
  240. * Run all of the upgrades slated for pre-dbdelta since the last database revision.
  241. *
  242. * @param integer $old_version The current version of the database that is being upgraded
  243. * @return boolean True on success
  244. */
  245. public function upgrade_pre( $old_version, $upgrade_path = '' )
  246. {
  247. return parent::upgrade( $old_version, dirname(__FILE__) . '/upgrades/pre');
  248. }
  249. /**
  250. * Run all of the upgrades slated for post-dbdelta since the last database revision.
  251. *
  252. * @param integer $old_version The current version of the database that is being upgraded
  253. * @return boolean True on success
  254. */
  255. public function upgrade_post( $old_version, $upgrade_path = '' )
  256. {
  257. return parent::upgrade( $old_version, dirname(__FILE__) . '/upgrades/post');
  258. }
  259. }
  260. ?>