Pelzini

This is the code documentation for the Pelzini project

source of /processor/mysql_outputter.php

Contains the MysqlOutputter class
  1. <?php
  2. /*
  3. Copyright 2008 Josh Heidenreich
  4.  
  5. This file is part of Pelzini.
  6.  
  7. Pelzini is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 3 of the License, or
  10. (at your option) any later version.
  11.  
  12. Pelzini is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Pelzini. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20.  
  21.  
  22. /**
  23.  * Contains the {@link MysqlOutputter} class
  24.  *
  25.  * @package Outputters
  26.  * @author Josh
  27.  * @since 0.1
  28.  **/
  29.  
  30. /**
  31.  * Outputs the tree as MySQL
  32.  **/
  33. class MysqlOutputter extends DatabaseOutputter {
  34. private $username;
  35. private $password;
  36. private $server;
  37. private $database;
  38. private $db;
  39.  
  40. /**
  41.   * Connects to the db
  42.   */
  43. public function __construct($username, $password, $server, $database)
  44. {
  45. $this->username = $username;
  46. $this->password = $password;
  47. $this->server = $server;
  48. $this->database = $database;
  49. }
  50.  
  51.  
  52. /**
  53.   * Closes connection to the db
  54.   */
  55. public function __destruct()
  56. {
  57. if ($this->db) mysql_close($this->db);
  58. }
  59.  
  60.  
  61.  
  62. /**
  63.   * Connects to the MySQL database
  64.   **/
  65. protected function connect()
  66. {
  67. $this->db = @mysql_connect($this->server, $this->username, $this->password);
  68. if ($this->db == false) return false;
  69. mysql_select_db($this->database, $this->db);
  70. return true;
  71. }
  72.  
  73.  
  74. /**
  75.   * Executes a MySQL query
  76.   */
  77. protected function query($query)
  78. {
  79. $return = mysql_query($query, $this->db);
  80. if ($return === false) {
  81. echo "<p>Error in query <em>{$query}</em>. MySQL reported the following: <em>" . mysql_error() . "</em></p>";
  82. }
  83. return $return;
  84. }
  85.  
  86.  
  87. /**
  88.   * Safens some input
  89.   * @param string $input The input to safen
  90.   **/
  91. protected function sql_safen($input)
  92. {
  93. if ($input === null) {
  94. return 'NULL';
  95. } else if (is_integer($input)) {
  96. return $input;
  97. } else {
  98. return "'" . mysql_real_escape_string($input, $this->db) . "'";
  99. }
  100. }
  101.  
  102.  
  103. /**
  104.   * Fetches a row from the database (numerical)
  105.   **/
  106. protected function fetch_row($res)
  107. {
  108. return mysql_fetch_row($res);
  109. }
  110.  
  111.  
  112. /**
  113.   * Fetches a row from the database (assoc)
  114.   **/
  115. protected function fetch_assoc($res)
  116. {
  117. return mysql_fetch_assoc($res);
  118. }
  119.  
  120.  
  121. /**
  122.   * Returns the number of rows affected in the last query
  123.   **/
  124. protected function affected_rows($res)
  125. {
  126. }
  127.  
  128.  
  129. /**
  130.   * Returns the autogenerated id created in the last query
  131.   **/
  132. protected function insert_id()
  133. {
  134. return mysql_insert_id();
  135. }
  136.  
  137.  
  138. /**
  139.   * Returns an array of the tables in this database
  140.   **/
  141. protected function get_table_list()
  142. {
  143. $q = "SHOW TABLES";
  144. $res = $this->query ($q);
  145.  
  146. $tables = array();
  147. while ($row = $this->fetch_row($res)) {
  148. $tables[] = $row[0];
  149. }
  150.  
  151. return $tables;
  152. }
  153.  
  154.  
  155. /**
  156.   * Converts an internal type into the database-specific SQL type.
  157.   * The defined internal types are:
  158.   * - serial: a number that automatically increments whenever a record is added
  159.   * - smallnum: a small number. needs to be able to hold at least 32,767 possible values (e.g. a 16-bit signed integer)
  160.   * - largenum: a large number. needs to be the same size or larger than a serial type
  161.   * - string: a character field long enough to hold identifiers of objects (e.g. function names)
  162.   * - text: a field that can hold arbitary pieces of text larger than 65536 chars in length.
  163.   *
  164.   * @param string $internal_type_name The internal type name.
  165.   * @return string The name used by the SQL database.
  166.   **/
  167. protected function get_sql_type($internal_type_name)
  168. {
  169. switch ($internal_type_name) {
  170. case 'serial': return 'SERIAL';
  171. case 'smallnum': return 'SMALLINT UNSIGNED';
  172. case 'largenum': return 'BIGINT UNSIGNED';
  173. case 'string': return 'VARCHAR(255)';
  174. case 'text': return 'MEDIUMTEXT';
  175. default:
  176. throw new Exception ("Undefined type '{$internal_type_name}' specified");
  177. break;
  178. }
  179. }
  180.  
  181.  
  182. /**
  183.   * Should return a multi-dimentional array of the column details
  184.   * Format:
  185.   * Array [
  186.   * [0] => Array [
  187.   * 'Field' => field name
  188.   * 'Type' => field type, (e.g. 'serial', 'smallnum' or 'identifier')
  189.   * 'NotNull' => nullable?, (true or false)
  190.   * 'Key' => indexed?, ('PRI' for primary key)
  191.   * ]
  192.   * [1] => ...
  193.   * [n] => ...
  194.   **/
  195. protected function get_column_details($table_name)
  196. {
  197. $q = 'SHOW COLUMNS IN ' . $table_name;
  198. $res = $this->query ($q);
  199.  
  200. $columns = array();
  201. while ($row = $this->fetch_assoc($res)) {
  202. if ($row['Null'] == 'YES') {
  203. $row['NotNull'] = false;
  204. } else {
  205. $row['NotNull'] = true;
  206. }
  207.  
  208. // Remap the SQL types back to Pelzini type
  209. $row['Type'] = preg_replace('/\(.+\)/', '', $row['Type']);
  210. $row['Type'] = strtolower($row['Type']);
  211. switch ($row['Type']) {
  212. case 'smallint unsigned': $row['Type'] = 'smallnum'; break;
  213. case 'smallint': $row['Type'] = 'smallnum'; break;
  214. case 'bigint unsigned':
  215. $row['Type'] = 'largenum';
  216. if ($row['NotNull'] and stripos('auto_increment', $row['Extra']) !== false) {
  217. $row['Type'] = 'serial';
  218. }
  219. break;
  220. case 'bigint': $row['Type'] = 'largenum'; break;
  221. case 'int unsigned': $row['Type'] = 'largenum'; break;
  222. case 'int': $row['Type'] = 'largenum'; break;
  223. case 'varchar': $row['Type'] = 'string'; break;
  224. case 'mediumtext': $row['Type'] = 'text'; break;
  225. }
  226.  
  227. unset ($row['Extra'], $row['Default']);
  228. $columns[] = $row;
  229. }
  230.  
  231. return $columns;
  232. }
  233.  
  234.  
  235. /**
  236.   * Should return a multi-dimentional array of the index details
  237.   * Format:
  238.   * Array [
  239.   * [0] => Array [
  240.   * 'Fields' => array of field names
  241.   * ]
  242.   * [1] => ...
  243.   * [n] => ...
  244.   **/
  245. protected function get_index_details($table_name)
  246. {
  247. $q = 'SHOW INDEXES IN ' . $table_name;
  248. $res = $this->query ($q);
  249.  
  250. $indexes = array();
  251. while ($row = $this->fetch_assoc($res)) {
  252. if (!isset($indexes[$row['Key_name']])) {
  253. $indexes[$row['Key_name']] = array('Fields' => array());
  254. }
  255.  
  256. $indexes[$row['Key_name']]['Fields'][] = $row['Column_name'];
  257. }
  258.  
  259. return $indexes;
  260. }
  261.  
  262.  
  263. /**
  264.   * Gets the query that alters a column to match the new SQL definition
  265.   **/
  266. protected function get_alter_column_query($table, $column_name, $new_type, $not_null)
  267. {
  268. $new_type = $this->get_sql_type($new_type);
  269.  
  270. $q = "ALTER TABLE {$table} MODIFY COLUMN {$column_name} {$new_type}";
  271. return $q;
  272. }
  273.  
  274.  
  275. /**
  276.   * Creates a table
  277.   **/
  278. protected function create_table($table_name, $dest_table)
  279. {
  280. $q = "CREATE TABLE {$table_name} (\n";
  281. foreach ($dest_table['Columns'] as $col_name => $col_def) {
  282. $dest_sql = $this->get_sql_type($col_def['Type']);
  283. if ($col_def['NotNull']) $dest_sql .= ' not null';
  284.  
  285. $q .= " {$col_name} {$dest_sql},\n";
  286. }
  287. foreach ($dest_table['Indexes'] as $col_name) {
  288. $q .= " INDEX ({$col_name}),\n";
  289. }
  290. $q .= " PRIMARY KEY ({$dest_table['PK']})\n";
  291. $q .= ") ENGINE=MyISAM";
  292. echo "<b>Query:\n{$q}</b>\n";
  293.  
  294. $res = $this->query ($q);
  295. if ($res) echo 'Affected rows: ', $this->affected_rows($res), "\n";
  296. }
  297.  
  298.  
  299. /**
  300.   * The database engine should start a transaction. If transactions are not supported, it should do nothing.
  301.   **/
  302. protected function start_transaction()
  303. {
  304. $this->query('START TRANSACTION');
  305. }
  306.  
  307.  
  308. /**
  309.   * The database engine should commit a transaction. If transactions are not supported, it should do nothing.
  310.   **/
  311. protected function commit_transaction()
  312. {
  313. $this->query('COMMIT');
  314. }
  315.  
  316.  
  317. /**
  318.   * The database engine should rollback a transaction. If transactions are not supported, it should do nothing.
  319.   **/
  320. protected function rollback_transaction()
  321. {
  322. $this->query('ROLLBACK');
  323. }
  324.  
  325.  
  326. }
  327.  
  328.  
  329. ?>
  330.