blob: 31102c0c6a50324f14273f5a58138f26d2314dca [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
Derek Jonesf4a4bd82011-10-20 12:18:42 -05003 * CodeIgniter
Derek Allard2067d1a2008-11-13 22:59:24 +00004 *
Phil Sturgeon07c1ac82012-03-09 17:03:37 +00005 * An open source application development framework for PHP 5.2.4 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
Andrey Andreev24276a32012-01-08 02:44:38 +02008 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05009 * Licensed under the Open Software License version 3.0
Andrey Andreev24276a32012-01-08 02:44:38 +020010 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -050011 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Derek Allard2067d1a2008-11-13 22:59:24 +000019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
Greg Aker0defe5d2012-01-01 18:46:41 -060021 * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
Derek Jonesf4a4bd82011-10-20 12:18:42 -050022 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Derek Allard2067d1a2008-11-13 22:59:24 +000023 * @link http://codeigniter.com
24 * @since Version 1.0
25 * @filesource
26 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020027defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000028
Derek Allard2067d1a2008-11-13 22:59:24 +000029/**
30 * Database Utility Class
31 *
32 * @category Database
Derek Jonesf4a4bd82011-10-20 12:18:42 -050033 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000034 * @link http://codeigniter.com/user_guide/database/
35 */
Timothy Warren833d5042012-03-19 16:12:03 -040036abstract class CI_DB_utility extends CI_DB_forge {
Derek Allard2067d1a2008-11-13 22:59:24 +000037
Andrey Andreevae85eb42012-11-02 01:42:31 +020038 /**
39 * Database object
40 *
41 * @var object
42 */
Andrey Andreev24276a32012-01-08 02:44:38 +020043 public $db;
Derek Allard2067d1a2008-11-13 22:59:24 +000044
Andrey Andreevae85eb42012-11-02 01:42:31 +020045 // --------------------------------------------------------------------
46
47 /**
Andrey Andreevc98e93a2012-11-02 02:04:59 +020048 * List databases statement
49 *
50 * @var string
51 */
52 $_list_databases = FALSE;
53
54 /**
Andrey Andreevae85eb42012-11-02 01:42:31 +020055 * OPTIMIZE TABLE statement
56 *
Andrey Andreevc98e93a2012-11-02 02:04:59 +020057 * @var string
Andrey Andreevae85eb42012-11-02 01:42:31 +020058 */
Andrey Andreevb457a402012-04-09 16:11:56 +030059 protected $_optimize_table = FALSE;
Andrey Andreevae85eb42012-11-02 01:42:31 +020060
61 /**
62 * REPAIR TABLE statement
63 *
Andrey Andreevc98e93a2012-11-02 02:04:59 +020064 * @var string
Andrey Andreevae85eb42012-11-02 01:42:31 +020065 */
Andrey Andreevb457a402012-04-09 16:11:56 +030066 protected $_repair_table = FALSE;
67
Andrey Andreevae85eb42012-11-02 01:42:31 +020068 // --------------------------------------------------------------------
69
Andrey Andreev5fd3ae82012-10-24 14:55:35 +030070 /**
Andrey Andreevc98e93a2012-11-02 02:04:59 +020071 * Class constructor
Andrey Andreev5fd3ae82012-10-24 14:55:35 +030072 *
73 * @return void
74 */
Andrey Andreev24276a32012-01-08 02:44:38 +020075 public function __construct()
Derek Allard2067d1a2008-11-13 22:59:24 +000076 {
77 // Assign the main database object to $this->db
78 $CI =& get_instance();
79 $this->db =& $CI->db;
Andrey Andreev24276a32012-01-08 02:44:38 +020080 log_message('debug', 'Database Utility Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +000081 }
82
83 // --------------------------------------------------------------------
84
85 /**
86 * List databases
87 *
Andrey Andreevb457a402012-04-09 16:11:56 +030088 * @return array
Derek Allard2067d1a2008-11-13 22:59:24 +000089 */
Andrey Andreev24276a32012-01-08 02:44:38 +020090 public function list_databases()
Barry Mienydd671972010-10-04 16:33:58 +020091 {
Derek Allard2067d1a2008-11-13 22:59:24 +000092 // Is there a cached result?
Andrey Andreev5d281762012-06-11 22:05:40 +030093 if (isset($this->db->data_cache['db_names']))
Derek Allard2067d1a2008-11-13 22:59:24 +000094 {
Andrey Andreev5d281762012-06-11 22:05:40 +030095 return $this->db->data_cache['db_names'];
Derek Allard2067d1a2008-11-13 22:59:24 +000096 }
Andrey Andreevb457a402012-04-09 16:11:56 +030097 elseif ($this->_list_databases === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +000098 {
Andrey Andreevb457a402012-04-09 16:11:56 +030099 return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000100 }
Barry Mienydd671972010-10-04 16:33:58 +0200101
Andrey Andreev5d281762012-06-11 22:05:40 +0300102 $this->db->data_cache['db_names'] = array();
Andrey Andreevb457a402012-04-09 16:11:56 +0300103
104 $query = $this->db->query($this->_list_databases);
105 if ($query === FALSE)
106 {
Andrey Andreev5d281762012-06-11 22:05:40 +0300107 return $this->db->data_cache['db_names'];
Andrey Andreevb457a402012-04-09 16:11:56 +0300108 }
109
110 for ($i = 0, $c = count($query); $i < $c; $i++)
111 {
Andrey Andreev5d281762012-06-11 22:05:40 +0300112 $this->db->data_cache['db_names'] = current($query[$i]);
Andrey Andreevb457a402012-04-09 16:11:56 +0300113 }
114
Andrey Andreev5d281762012-06-11 22:05:40 +0300115 return $this->db->data_cache['db_names'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000116 }
117
118 // --------------------------------------------------------------------
119
120 /**
Derek Allarde7f03252010-02-04 16:47:01 +0000121 * Determine if a particular database exists
122 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200123 * @param string $database_name
Andrey Andreevb457a402012-04-09 16:11:56 +0300124 * @return bool
Derek Allarde7f03252010-02-04 16:47:01 +0000125 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200126 public function database_exists($database_name)
Derek Allard62396232010-02-04 17:45:47 +0000127 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300128 return in_array($database_name, $this->list_databases());
Derek Allarde7f03252010-02-04 16:47:01 +0000129 }
130
131 // --------------------------------------------------------------------
132
133 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000134 * Optimize Table
135 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200136 * @param string $table_name
Andrey Andreevb457a402012-04-09 16:11:56 +0300137 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000138 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200139 public function optimize_table($table_name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000140 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300141 if ($this->_optimize_table === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000142 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300143 return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000144 }
Barry Mienydd671972010-10-04 16:33:58 +0200145
Andrey Andreevb457a402012-04-09 16:11:56 +0300146 $query = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name)));
147 if ($query !== FALSE)
148 {
149 $query = $query->result_array();
150 return current($res);
151 }
Barry Mienydd671972010-10-04 16:33:58 +0200152
Andrey Andreevb457a402012-04-09 16:11:56 +0300153 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000154 }
155
156 // --------------------------------------------------------------------
157
158 /**
159 * Optimize Database
160 *
Andrey Andreevb457a402012-04-09 16:11:56 +0300161 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000162 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200163 public function optimize_database()
Derek Allard2067d1a2008-11-13 22:59:24 +0000164 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300165 if ($this->_optimize_table === FALSE)
166 {
167 return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
168 }
169
Derek Allard2067d1a2008-11-13 22:59:24 +0000170 $result = array();
171 foreach ($this->db->list_tables() as $table_name)
172 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300173 $res = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name)));
174 if (is_bool($res))
Derek Allard2067d1a2008-11-13 22:59:24 +0000175 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300176 return $res;
Derek Allard2067d1a2008-11-13 22:59:24 +0000177 }
Barry Mienydd671972010-10-04 16:33:58 +0200178
Derek Allard2067d1a2008-11-13 22:59:24 +0000179 // Build the result array...
Andrey Andreevb457a402012-04-09 16:11:56 +0300180 $res = $res->result_array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000181 $res = current($res);
182 $key = str_replace($this->db->database.'.', '', current($res));
183 $keys = array_keys($res);
184 unset($res[$keys[0]]);
Barry Mienydd671972010-10-04 16:33:58 +0200185
Derek Allard2067d1a2008-11-13 22:59:24 +0000186 $result[$key] = $res;
187 }
188
189 return $result;
190 }
191
192 // --------------------------------------------------------------------
193
194 /**
195 * Repair Table
196 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200197 * @param string $table_name
Andrey Andreevb457a402012-04-09 16:11:56 +0300198 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000199 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200200 public function repair_table($table_name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000201 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300202 if ($this->_repair_table === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000203 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300204 return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000205 }
Barry Mienydd671972010-10-04 16:33:58 +0200206
Andrey Andreevb457a402012-04-09 16:11:56 +0300207 $query = $this->db->query(sprintf($this->_repair_table, $this->db->escape_identifiers($table_name)));
208 if (is_bool($query))
209 {
210 return $query;
211 }
Barry Mienydd671972010-10-04 16:33:58 +0200212
Andrey Andreevb457a402012-04-09 16:11:56 +0300213 $query = $query->result_array();
214 return current($query);
Derek Allard2067d1a2008-11-13 22:59:24 +0000215 }
Barry Mienydd671972010-10-04 16:33:58 +0200216
Derek Allard2067d1a2008-11-13 22:59:24 +0000217 // --------------------------------------------------------------------
218
219 /**
220 * Generate CSV from a query result object
221 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200222 * @param object $query Query result object
223 * @param string $delim Delimiter (default: ,)
224 * @param string $newline Newline character (default: \n)
225 * @param string $enclosure Enclosure (default: ")
Derek Allard2067d1a2008-11-13 22:59:24 +0000226 * @return string
227 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200228 public function csv_from_result($query, $delim = ',', $newline = "\n", $enclosure = '"')
Derek Allard2067d1a2008-11-13 22:59:24 +0000229 {
Derek Jones47874132009-02-10 17:32:15 +0000230 if ( ! is_object($query) OR ! method_exists($query, 'list_fields'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000231 {
232 show_error('You must submit a valid result object');
Barry Mienydd671972010-10-04 16:33:58 +0200233 }
234
Derek Allard2067d1a2008-11-13 22:59:24 +0000235 $out = '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000236 // First generate the headings from the table column names
237 foreach ($query->list_fields() as $name)
238 {
239 $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $name).$enclosure.$delim;
240 }
Barry Mienydd671972010-10-04 16:33:58 +0200241
Andrey Andreev24276a32012-01-08 02:44:38 +0200242 $out = rtrim($out).$newline;
Barry Mienydd671972010-10-04 16:33:58 +0200243
Derek Allard2067d1a2008-11-13 22:59:24 +0000244 // Next blast through the result array and build out the rows
Andrey Andreevd06acd82012-05-25 00:29:09 +0300245 while ($row = $query->unbuffered_row('array'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000246 {
247 foreach ($row as $item)
248 {
Barry Mienydd671972010-10-04 16:33:58 +0200249 $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $item).$enclosure.$delim;
Derek Allard2067d1a2008-11-13 22:59:24 +0000250 }
Andrey Andreev24276a32012-01-08 02:44:38 +0200251 $out = rtrim($out).$newline;
Derek Allard2067d1a2008-11-13 22:59:24 +0000252 }
253
254 return $out;
255 }
Barry Mienydd671972010-10-04 16:33:58 +0200256
Derek Allard2067d1a2008-11-13 22:59:24 +0000257 // --------------------------------------------------------------------
258
259 /**
260 * Generate XML data from a query result object
261 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200262 * @param object $query Query result object
263 * @param array $params Any preferences
Derek Allard2067d1a2008-11-13 22:59:24 +0000264 * @return string
265 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200266 public function xml_from_result($query, $params = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000267 {
Pascal Kriete69b1fcc2009-08-24 16:42:52 +0000268 if ( ! is_object($query) OR ! method_exists($query, 'list_fields'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000269 {
270 show_error('You must submit a valid result object');
271 }
Barry Mienydd671972010-10-04 16:33:58 +0200272
Derek Allard2067d1a2008-11-13 22:59:24 +0000273 // Set our default values
274 foreach (array('root' => 'root', 'element' => 'element', 'newline' => "\n", 'tab' => "\t") as $key => $val)
275 {
276 if ( ! isset($params[$key]))
277 {
278 $params[$key] = $val;
279 }
280 }
Barry Mienydd671972010-10-04 16:33:58 +0200281
Derek Allard2067d1a2008-11-13 22:59:24 +0000282 // Create variables for convenience
283 extract($params);
Barry Mienydd671972010-10-04 16:33:58 +0200284
Derek Allard2067d1a2008-11-13 22:59:24 +0000285 // Load the xml helper
286 $CI =& get_instance();
287 $CI->load->helper('xml');
288
289 // Generate the result
Andrey Andreevb457a402012-04-09 16:11:56 +0300290 $xml = '<'.$root.'>'.$newline;
Andrey Andreevd06acd82012-05-25 00:29:09 +0300291 while ($row = $query->unbuffered_row())
Derek Allard2067d1a2008-11-13 22:59:24 +0000292 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300293 $xml .= $tab.'<'.$element.'>'.$newline;
Derek Allard2067d1a2008-11-13 22:59:24 +0000294 foreach ($row as $key => $val)
295 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300296 $xml .= $tab.$tab.'<'.$key.'>'.xml_convert($val).'</'.$key.'>'.$newline;
Derek Allard2067d1a2008-11-13 22:59:24 +0000297 }
Andrey Andreevb457a402012-04-09 16:11:56 +0300298 $xml .= $tab.'</'.$element.'>'.$newline;
Derek Allard2067d1a2008-11-13 22:59:24 +0000299 }
Barry Mienydd671972010-10-04 16:33:58 +0200300
Andrey Andreevb457a402012-04-09 16:11:56 +0300301 return $xml.'</'.$root.'>'.$newline;
Derek Allard2067d1a2008-11-13 22:59:24 +0000302 }
303
304 // --------------------------------------------------------------------
305
306 /**
307 * Database Backup
308 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200309 * @param array $params
Derek Allard2067d1a2008-11-13 22:59:24 +0000310 * @return void
311 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200312 public function backup($params = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000313 {
314 // If the parameters have not been submitted as an
315 // array then we know that it is simply the table
316 // name, which is a valid short cut.
317 if (is_string($params))
318 {
319 $params = array('tables' => $params);
320 }
Barry Mienydd671972010-10-04 16:33:58 +0200321
Derek Allard2067d1a2008-11-13 22:59:24 +0000322 // Set up our default preferences
323 $prefs = array(
Andrey Andreev24276a32012-01-08 02:44:38 +0200324 'tables' => array(),
325 'ignore' => array(),
326 'filename' => '',
327 'format' => 'gzip', // gzip, zip, txt
328 'add_drop' => TRUE,
329 'add_insert' => TRUE,
330 'newline' => "\n"
331 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000332
333 // Did the user submit any preferences? If so set them....
334 if (count($params) > 0)
335 {
336 foreach ($prefs as $key => $val)
337 {
338 if (isset($params[$key]))
339 {
340 $prefs[$key] = $params[$key];
341 }
342 }
343 }
344
Barry Mienydd671972010-10-04 16:33:58 +0200345 // Are we backing up a complete database or individual tables?
Derek Allard2067d1a2008-11-13 22:59:24 +0000346 // If no table names were submitted we'll fetch the entire table list
Andrey Andreev24276a32012-01-08 02:44:38 +0200347 if (count($prefs['tables']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000348 {
349 $prefs['tables'] = $this->db->list_tables();
350 }
Barry Mienydd671972010-10-04 16:33:58 +0200351
Derek Allard2067d1a2008-11-13 22:59:24 +0000352 // Validate the format
353 if ( ! in_array($prefs['format'], array('gzip', 'zip', 'txt'), TRUE))
354 {
355 $prefs['format'] = 'txt';
356 }
357
Andrey Andreev24276a32012-01-08 02:44:38 +0200358 // Is the encoder supported? If not, we'll either issue an
Derek Allard2067d1a2008-11-13 22:59:24 +0000359 // error or use plain text depending on the debug settings
Andrey Andreevb457a402012-04-09 16:11:56 +0300360 if (($prefs['format'] === 'gzip' && ! @function_exists('gzencode'))
361 OR ($prefs['format'] === 'zip' && ! @function_exists('gzcompress')))
Derek Allard2067d1a2008-11-13 22:59:24 +0000362 {
363 if ($this->db->db_debug)
364 {
365 return $this->db->display_error('db_unsuported_compression');
366 }
Barry Mienydd671972010-10-04 16:33:58 +0200367
Derek Allard2067d1a2008-11-13 22:59:24 +0000368 $prefs['format'] = 'txt';
369 }
370
Barry Mienydd671972010-10-04 16:33:58 +0200371 // Was a Zip file requested?
Andrey Andreev24276a32012-01-08 02:44:38 +0200372 if ($prefs['format'] === 'zip')
Derek Allard2067d1a2008-11-13 22:59:24 +0000373 {
Andrey Andreev24276a32012-01-08 02:44:38 +0200374 // Set the filename if not provided (only needed with Zip files)
Alex Bilbie48a2baf2012-06-02 11:09:54 +0100375 if ($prefs['filename'] === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000376 {
Andrey Andreev24276a32012-01-08 02:44:38 +0200377 $prefs['filename'] = (count($prefs['tables']) === 1 ? $prefs['tables'] : $this->db->database)
378 .date('Y-m-d_H-i', time()).'.sql';
Derek Allard2067d1a2008-11-13 22:59:24 +0000379 }
Andrey Andreev24276a32012-01-08 02:44:38 +0200380 else
Derek Allard2067d1a2008-11-13 22:59:24 +0000381 {
Andrey Andreev24276a32012-01-08 02:44:38 +0200382 // If they included the .zip file extension we'll remove it
383 if (preg_match('|.+?\.zip$|', $prefs['filename']))
384 {
385 $prefs['filename'] = str_replace('.zip', '', $prefs['filename']);
386 }
387
388 // Tack on the ".sql" file extension if needed
389 if ( ! preg_match('|.+?\.sql$|', $prefs['filename']))
390 {
391 $prefs['filename'] .= '.sql';
392 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000393 }
394
395 // Load the Zip class and output it
Derek Allard2067d1a2008-11-13 22:59:24 +0000396 $CI =& get_instance();
397 $CI->load->library('zip');
Barry Mienydd671972010-10-04 16:33:58 +0200398 $CI->zip->add_data($prefs['filename'], $this->_backup($prefs));
Derek Allard2067d1a2008-11-13 22:59:24 +0000399 return $CI->zip->get_zip();
400 }
Alex Bilbie48a2baf2012-06-02 11:09:54 +0100401 elseif ($prefs['format'] === 'txt') // Was a text file requested?
Andrey Andreev24276a32012-01-08 02:44:38 +0200402 {
403 return $this->_backup($prefs);
404 }
405 elseif ($prefs['format'] === 'gzip') // Was a Gzip file requested?
406 {
407 return gzencode($this->_backup($prefs));
408 }
Barry Mienydd671972010-10-04 16:33:58 +0200409
Andrey Andreev24276a32012-01-08 02:44:38 +0200410 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000411 }
412
413}
414
Derek Allard2067d1a2008-11-13 22:59:24 +0000415/* End of file DB_utility.php */
Timothy Warren215890b2012-03-20 09:38:16 -0400416/* Location: ./system/database/DB_utility.php */