sqlite_outputter.php | ||||
|
||||
Coverage | ||||||||||
Classes | Functions / Methods | Lines | ||||||||
Total |
|
0.00% | 0 / 1 |
|
0.00% | 0 / 19 | CRAP |
|
0.00% | 0 / 75 |
SqliteOutputter |
|
0.00% | 0 / 1 |
|
0.00% | 0 / 19 | 2450 |
|
0.00% | 0 / 75 |
__construct($filename) |
|
0.00% | 0 / 1 | 2 |
|
0.00% | 0 / 2 | |||
__destruct() |
|
0.00% | 0 / 1 | 6 |
|
0.00% | 0 / 2 | |||
connect() |
|
0.00% | 0 / 1 | 6 |
|
0.00% | 0 / 3 | |||
query($query) |
|
0.00% | 0 / 1 | 6 |
|
0.00% | 0 / 6 | |||
sql_safen($input) |
|
0.00% | 0 / 1 | 12 |
|
0.00% | 0 / 5 | |||
fetch_row($res) |
|
0.00% | 0 / 1 | 2 |
|
0.00% | 0 / 1 | |||
fetch_assoc($res) |
|
0.00% | 0 / 1 | 2 |
|
0.00% | 0 / 1 | |||
affected_rows($res) |
|
0.00% | 0 / 1 | 6 |
|
0.00% | 0 / 2 | |||
insert_id() |
|
0.00% | 0 / 1 | 2 |
|
0.00% | 0 / 1 | |||
do_multiple_insert($table, $data) |
|
0.00% | 0 / 1 | 6 |
|
0.00% | 0 / 4 | |||
get_table_list() |
|
0.00% | 0 / 1 | 6 |
|
0.00% | 0 / 7 | |||
get_sql_type($internal_type_name) |
|
0.00% | 0 / 1 | 42 |
|
0.00% | 0 / 8 | |||
check_layout($layout_filename) |
|
0.00% | 0 / 1 | 20 |
|
0.00% | 0 / 11 | |||
get_column_details($table_name) |
|
0.00% | 0 / 1 | 156 |
|
0.00% | 0 / 1 | |||
get_alter_column_query($table, $column_name, $new_type, $not_null) |
|
0.00% | 0 / 1 | 2 |
|
0.00% | 0 / 3 | |||
create_table($table_name, $dest_table) |
|
0.00% | 0 / 1 | 20 |
|
0.00% | 0 / 12 | |||
start_transaction() |
|
0.00% | 0 / 1 | 2 |
|
0.00% | 0 / 2 | |||
commit_transaction() |
|
0.00% | 0 / 1 | 2 |
|
0.00% | 0 / 2 | |||
rollback_transaction() |
|
0.00% | 0 / 1 | 2 |
|
0.00% | 0 / 2 |
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 SqliteOutputter} class 24 : * 25 : * @package Outputters 26 : * @author Josh 27 : * @since 0.2 28 : **/ 29 : 30 : /** 31 : * Outputs the tree to a SQLite database 32 : **/ 33 : class SqliteOutputter extends DatabaseOutputter { 34 : private $filename; 35 : private $db; 36 : 37 : /** 38 : * Connects to the db 39 : */ 40 : public function __construct($filename) 41 : { 42 0 : $this->filename = $filename; 43 0 : } 44 : 45 : 46 : /** 47 : * Closes connection to the db 48 : */ 49 : public function __destruct() 50 : { 51 0 : if ($this->db) sqlite_close($this->db); 52 0 : } 53 : 54 : 55 : 56 : /** 57 : * Connects to the MySQL database 58 : **/ 59 : protected function connect() 60 : { 61 0 : $this->db = @sqlite_open($this->filename); 62 0 : if ($this->db == false) return false; 63 0 : return true; 64 : } 65 : 66 : 67 : /** 68 : * Executes a MySQL query 69 : */ 70 : protected function query($query) 71 : { 72 0 : $query = str_ireplace('TRUNCATE', 'DELETE FROM', $query); 73 : 74 0 : $return = sqlite_query($query, $this->db, SQLITE_BOTH, $error); 75 0 : if ($return === false) { 76 0 : echo "<p>Error in query <em>{$query}</em>. SQLite reported the following: <em>{$error}</em></p>"; 77 0 : } 78 0 : return $return; 79 : } 80 : 81 : 82 : /** 83 : * Safens some input 84 : * @param string $input The input to safen 85 : **/ 86 : protected function sql_safen($input) 87 : { 88 0 : if ($input === null) { 89 0 : return 'NULL'; 90 0 : } else if (is_integer($input)) { 91 0 : return $input; 92 : } else { 93 0 : return "'" . sqlite_escape_string($input) . "'"; 94 : } 95 : } 96 : 97 : 98 : /** 99 : * Fetches a row from the database (numerical) 100 : **/ 101 : protected function fetch_row($res) 102 : { 103 0 : return sqlite_fetch_array($res, SQLITE_NUM); 104 : } 105 : 106 : 107 : /** 108 : * Fetches a row from the database (assoc) 109 : **/ 110 : protected function fetch_assoc($res) 111 : { 112 0 : return sqlite_fetch_array($res, SQLITE_ASSOC); 113 : } 114 : 115 : 116 : /** 117 : * Returns the number of rows affected in the last query 118 : * SQLite has no affected rows system. Assume if there is a result, that rows were affected. 119 : **/ 120 : protected function affected_rows($res) 121 : { 122 0 : if ($res) return 1; 123 0 : return 0; 124 : } 125 : 126 : 127 : /** 128 : * Returns the autogenerated id created in the last query 129 : **/ 130 : protected function insert_id() 131 : { 132 0 : return sqlite_last_insert_rowid($this->db); 133 : } 134 : 135 : 136 : /** 137 : * SQLite doesn't support multiple insert, so run each insert as a separate query 138 : **/ 139 : protected function do_multiple_insert($table, $data) 140 : { 141 0 : foreach ($data as $row) { 142 0 : $this->do_insert($table, $row); 143 0 : } 144 0 : } 145 : 146 : 147 : /** 148 : * Returns an array of the tables in this database 149 : **/ 150 : protected function get_table_list() 151 : { 152 : $q = "SELECT name FROM sqlite_master 153 : WHERE type='table' 154 0 : ORDER BY name"; 155 0 : $res = $this->query ($q); 156 : 157 0 : $tables = array(); 158 0 : while ($row = $this->fetch_row($res)) { 159 0 : $tables[] = $row[0]; 160 0 : } 161 : 162 0 : return $tables; 163 : } 164 : 165 : 166 : /** 167 : * Converts an internal type into the database-specific SQL type. 168 : * The defined internal types are: 169 : * - serial: a number that automatically increments whenever a record is added 170 : * - smallnum: a small number. needs to be able to hold at least 32,767 possible values (e.g. a 16-bit signed integer) 171 : * - largenum: a large number. needs to be the same size or larger than a serial type 172 : * - string: a character field long enough to hold identifiers of objects (e.g. function names) 173 : * - text: a field that can hold arbitary pieces of text larger than 65536 chars in length. 174 : * 175 : * @param string $internal_type_name The internal type name. 176 : * @return string The name used by the SQL database. 177 : **/ 178 : protected function get_sql_type($internal_type_name) 179 : { 180 : switch ($internal_type_name) { 181 0 : case 'serial': return 'INTEGER'; 182 0 : case 'smallnum': return 'INTEGER'; 183 0 : case 'largenum': return 'INTEGER'; 184 0 : case 'string': return 'TEXT'; 185 0 : case 'text': return 'TEXT'; 186 0 : default: 187 0 : throw new Exception ("Undefined type '{$internal_type_name}' specified"); 188 : break; 189 0 : } 190 : } 191 : 192 : 193 : /** 194 : * Updates the database layout to match the layout file 195 : * NOTE: currently only supports column and table adding and updating, not removal. 196 : * 197 : * @param string $layout_filename The name of the layout file to match 198 : **/ 199 : public function check_layout($layout_filename) 200 : { 201 : // Unfortunately, SQLite is a bit light-on when it comes to getting information 202 : // back about tables and columns 203 : // Thus, instead of doing a re-sync, we'll just try to wipe the db instead. 204 : 205 0 : if ($this->db) sqlite_close($this->db); 206 : 207 0 : $fp = @fopen($this->filename, 'wb'); 208 0 : if ($fp) { 209 0 : ftruncate($fp, 0); 210 0 : fclose($fp); 211 0 : } 212 : 213 0 : $this->db = @sqlite_open($this->filename); 214 0 : if ($this->db == false) { 215 0 : throw new Exception('Failed to reconnect to db'); 216 : } 217 : 218 0 : parent::check_layout($layout_filename); 219 0 : } 220 : 221 : /** 222 : * Should return a multi-dimentional array of the column details 223 : * Format: 224 : * Array [ 225 : * [0] => Array [ 226 : * 'Field' => field name 227 : * 'Type' => field type, (e.g. 'serial', 'smallnum' or 'identifier') 228 : * 'NotNull' => nullable?, (true or false) 229 : * 'Key' => indexed?, ('PRI' for primary key) 230 : * ] 231 : * [1] => ... 232 : * [n] => ... 233 : **/ 234 : protected function get_column_details($table_name) 235 : { 236 : //$q = "SELECT sql FROM sqlite_master WHERE type='table' AND name='{$table_name}'" 237 : //$res = $this->query ($q); 238 : 239 : // TODO: parse CREATE TABLE statement. 240 : // This is going to be painful I think 241 0 : return; 242 : 243 : $columns = array(); 244 : while ($row = $this->fetch_assoc($res)) { 245 : if ($row['Null'] == 'YES') { 246 : $row['NotNull'] = false; 247 : } else { 248 : $row['NotNull'] = true; 249 : } 250 : 251 : // Remap the SQL types back to Pelzini type 252 : $row['Type'] = preg_replace('/\(.+\)/', '', $row['Type']); 253 : $row['Type'] = strtolower($row['Type']); 254 : switch ($row['Type']) { 255 : case 'smallint unsigned': $row['Type'] = 'smallnum'; break; 256 : case 'smallint': $row['Type'] = 'smallnum'; break; 257 : case 'int unsigned': $row['Type'] = 'largenum'; break; 258 : case 'int': $row['Type'] = 'largenum'; break; 259 : case 'varchar': $row['Type'] = 'string'; break; 260 : case 'mediumtext': $row['Type'] = 'text'; break; 261 : } 262 : 263 : // SERIAL takes a touch more thinking 264 : if (strcasecmp('bigint unsigned', $row['Type']) == 0 265 : and $row['NotNull'] 266 : and stripos('auto_increment', $row['Extra']) !== false) { 267 : $row['Type'] = 'serial'; 268 : } 269 : 270 : unset ($row['Extra'], $row['Default']); 271 : $columns[] = $row; 272 : } 273 : 274 : return $columns; 275 : } 276 : 277 : 278 : /** 279 : * Gets the query that alters a column to match the new SQL definition 280 : **/ 281 : protected function get_alter_column_query($table, $column_name, $new_type, $not_null) 282 : { 283 0 : $new_type = $this->get_sql_type($new_type); 284 : 285 0 : $q = "ALTER TABLE {$table} MODIFY COLUMN {$column_name} {$new_type}"; 286 0 : return $q; 287 : } 288 : 289 : 290 : /** 291 : * Creates a table 292 : **/ 293 : protected function create_table($table_name, $dest_table) 294 : { 295 0 : $q = "CREATE TABLE {$table_name} (\n"; 296 0 : foreach ($dest_table['Columns'] as $col_name => $col_def) { 297 0 : $dest_sql = $this->get_sql_type($col_def['Type']); 298 0 : if ($col_def['NotNull']) $dest_sql .= ' not null'; 299 : 300 0 : $q .= " {$col_name} {$dest_sql},\n"; 301 0 : } 302 0 : $q .= " PRIMARY KEY ({$dest_table['PK']})\n"; 303 0 : $q .= ")"; 304 0 : echo "<b>Query:\n{$q}</b>\n"; 305 : 306 0 : $res = $this->query ($q); 307 0 : if ($res) echo 'Affected rows: ', $this->affected_rows($res), "\n"; 308 0 : } 309 : 310 : 311 : /** 312 : * The database engine should start a transaction. If transactions are not supported, it should do nothing. 313 : **/ 314 : protected function start_transaction() 315 : { 316 0 : $this->query ('BEGIN TRANSACTION'); 317 0 : } 318 : 319 : 320 : /** 321 : * The database engine should commit a transaction. If transactions are not supported, it should do nothing. 322 : **/ 323 : protected function commit_transaction() 324 : { 325 0 : $this->query ('COMMIT TRANSACTION'); 326 0 : } 327 : 328 : 329 : /** 330 : * The database engine should rollback a transaction. If transactions are not supported, it should do nothing. 331 : **/ 332 : protected function rollback_transaction() 333 : { 334 0 : $this->query ('ROLLBACK TRANSACTION'); 335 0 : } 336 : 337 : 338 : } 339 : 340 : 341 : ?> |
Generated by PHP_CodeCoverage 1.1.2 using PHP 5.4.39-0+deb7u2 and PHPUnit 3.6.10 at Fri Sep 11 11:35:19 WIT 2015. |