blob: 3bd77c84b02ba46daea4ae9cf5a6c4dc39c523d4 [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 /**
48 * OPTIMIZE TABLE statement
49 *
50 * @var string|bool
51 */
Andrey Andreevb457a402012-04-09 16:11:56 +030052 protected $_optimize_table = FALSE;
Andrey Andreevae85eb42012-11-02 01:42:31 +020053
54 /**
55 * REPAIR TABLE statement
56 *
57 * @var string|bool
58 */
Andrey Andreevb457a402012-04-09 16:11:56 +030059 protected $_repair_table = FALSE;
60
Andrey Andreevae85eb42012-11-02 01:42:31 +020061 // --------------------------------------------------------------------
62
Andrey Andreev5fd3ae82012-10-24 14:55:35 +030063 /**
64 * Constructor
65 *
66 * @return void
67 */
Andrey Andreev24276a32012-01-08 02:44:38 +020068 public function __construct()
Derek Allard2067d1a2008-11-13 22:59:24 +000069 {
70 // Assign the main database object to $this->db
71 $CI =& get_instance();
72 $this->db =& $CI->db;
Andrey Andreev24276a32012-01-08 02:44:38 +020073 log_message('debug', 'Database Utility Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +000074 }
75
76 // --------------------------------------------------------------------
77
78 /**
79 * List databases
80 *
Andrey Andreevb457a402012-04-09 16:11:56 +030081 * @return array
Derek Allard2067d1a2008-11-13 22:59:24 +000082 */
Andrey Andreev24276a32012-01-08 02:44:38 +020083 public function list_databases()
Barry Mienydd671972010-10-04 16:33:58 +020084 {
Derek Allard2067d1a2008-11-13 22:59:24 +000085 // Is there a cached result?
Andrey Andreev5d281762012-06-11 22:05:40 +030086 if (isset($this->db->data_cache['db_names']))
Derek Allard2067d1a2008-11-13 22:59:24 +000087 {
Andrey Andreev5d281762012-06-11 22:05:40 +030088 return $this->db->data_cache['db_names'];
Derek Allard2067d1a2008-11-13 22:59:24 +000089 }
Andrey Andreevb457a402012-04-09 16:11:56 +030090 elseif ($this->_list_databases === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +000091 {
Andrey Andreevb457a402012-04-09 16:11:56 +030092 return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +000093 }
Barry Mienydd671972010-10-04 16:33:58 +020094
Andrey Andreev5d281762012-06-11 22:05:40 +030095 $this->db->data_cache['db_names'] = array();
Andrey Andreevb457a402012-04-09 16:11:56 +030096
97 $query = $this->db->query($this->_list_databases);
98 if ($query === FALSE)
99 {
Andrey Andreev5d281762012-06-11 22:05:40 +0300100 return $this->db->data_cache['db_names'];
Andrey Andreevb457a402012-04-09 16:11:56 +0300101 }
102
103 for ($i = 0, $c = count($query); $i < $c; $i++)
104 {
Andrey Andreev5d281762012-06-11 22:05:40 +0300105 $this->db->data_cache['db_names'] = current($query[$i]);
Andrey Andreevb457a402012-04-09 16:11:56 +0300106 }
107
Andrey Andreev5d281762012-06-11 22:05:40 +0300108 return $this->db->data_cache['db_names'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000109 }
110
111 // --------------------------------------------------------------------
112
113 /**
Derek Allarde7f03252010-02-04 16:47:01 +0000114 * Determine if a particular database exists
115 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200116 * @param string $database_name
Andrey Andreevb457a402012-04-09 16:11:56 +0300117 * @return bool
Derek Allarde7f03252010-02-04 16:47:01 +0000118 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200119 public function database_exists($database_name)
Derek Allard62396232010-02-04 17:45:47 +0000120 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300121 return in_array($database_name, $this->list_databases());
Derek Allarde7f03252010-02-04 16:47:01 +0000122 }
123
124 // --------------------------------------------------------------------
125
126 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000127 * Optimize Table
128 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200129 * @param string $table_name
Andrey Andreevb457a402012-04-09 16:11:56 +0300130 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000131 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200132 public function optimize_table($table_name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000133 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300134 if ($this->_optimize_table === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000135 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300136 return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000137 }
Barry Mienydd671972010-10-04 16:33:58 +0200138
Andrey Andreevb457a402012-04-09 16:11:56 +0300139 $query = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name)));
140 if ($query !== FALSE)
141 {
142 $query = $query->result_array();
143 return current($res);
144 }
Barry Mienydd671972010-10-04 16:33:58 +0200145
Andrey Andreevb457a402012-04-09 16:11:56 +0300146 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000147 }
148
149 // --------------------------------------------------------------------
150
151 /**
152 * Optimize Database
153 *
Andrey Andreevb457a402012-04-09 16:11:56 +0300154 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000155 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200156 public function optimize_database()
Derek Allard2067d1a2008-11-13 22:59:24 +0000157 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300158 if ($this->_optimize_table === FALSE)
159 {
160 return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
161 }
162
Derek Allard2067d1a2008-11-13 22:59:24 +0000163 $result = array();
164 foreach ($this->db->list_tables() as $table_name)
165 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300166 $res = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name)));
167 if (is_bool($res))
Derek Allard2067d1a2008-11-13 22:59:24 +0000168 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300169 return $res;
Derek Allard2067d1a2008-11-13 22:59:24 +0000170 }
Barry Mienydd671972010-10-04 16:33:58 +0200171
Derek Allard2067d1a2008-11-13 22:59:24 +0000172 // Build the result array...
Andrey Andreevb457a402012-04-09 16:11:56 +0300173 $res = $res->result_array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000174 $res = current($res);
175 $key = str_replace($this->db->database.'.', '', current($res));
176 $keys = array_keys($res);
177 unset($res[$keys[0]]);
Barry Mienydd671972010-10-04 16:33:58 +0200178
Derek Allard2067d1a2008-11-13 22:59:24 +0000179 $result[$key] = $res;
180 }
181
182 return $result;
183 }
184
185 // --------------------------------------------------------------------
186
187 /**
188 * Repair Table
189 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200190 * @param string $table_name
Andrey Andreevb457a402012-04-09 16:11:56 +0300191 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +0000192 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200193 public function repair_table($table_name)
Derek Allard2067d1a2008-11-13 22:59:24 +0000194 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300195 if ($this->_repair_table === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000196 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300197 return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000198 }
Barry Mienydd671972010-10-04 16:33:58 +0200199
Andrey Andreevb457a402012-04-09 16:11:56 +0300200 $query = $this->db->query(sprintf($this->_repair_table, $this->db->escape_identifiers($table_name)));
201 if (is_bool($query))
202 {
203 return $query;
204 }
Barry Mienydd671972010-10-04 16:33:58 +0200205
Andrey Andreevb457a402012-04-09 16:11:56 +0300206 $query = $query->result_array();
207 return current($query);
Derek Allard2067d1a2008-11-13 22:59:24 +0000208 }
Barry Mienydd671972010-10-04 16:33:58 +0200209
Derek Allard2067d1a2008-11-13 22:59:24 +0000210 // --------------------------------------------------------------------
211
212 /**
213 * Generate CSV from a query result object
214 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200215 * @param object $query Query result object
216 * @param string $delim Delimiter (default: ,)
217 * @param string $newline Newline character (default: \n)
218 * @param string $enclosure Enclosure (default: ")
Derek Allard2067d1a2008-11-13 22:59:24 +0000219 * @return string
220 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200221 public function csv_from_result($query, $delim = ',', $newline = "\n", $enclosure = '"')
Derek Allard2067d1a2008-11-13 22:59:24 +0000222 {
Derek Jones47874132009-02-10 17:32:15 +0000223 if ( ! is_object($query) OR ! method_exists($query, 'list_fields'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000224 {
225 show_error('You must submit a valid result object');
Barry Mienydd671972010-10-04 16:33:58 +0200226 }
227
Derek Allard2067d1a2008-11-13 22:59:24 +0000228 $out = '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000229 // First generate the headings from the table column names
230 foreach ($query->list_fields() as $name)
231 {
232 $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $name).$enclosure.$delim;
233 }
Barry Mienydd671972010-10-04 16:33:58 +0200234
Andrey Andreev24276a32012-01-08 02:44:38 +0200235 $out = rtrim($out).$newline;
Barry Mienydd671972010-10-04 16:33:58 +0200236
Derek Allard2067d1a2008-11-13 22:59:24 +0000237 // Next blast through the result array and build out the rows
Andrey Andreevd06acd82012-05-25 00:29:09 +0300238 while ($row = $query->unbuffered_row('array'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000239 {
240 foreach ($row as $item)
241 {
Barry Mienydd671972010-10-04 16:33:58 +0200242 $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $item).$enclosure.$delim;
Derek Allard2067d1a2008-11-13 22:59:24 +0000243 }
Andrey Andreev24276a32012-01-08 02:44:38 +0200244 $out = rtrim($out).$newline;
Derek Allard2067d1a2008-11-13 22:59:24 +0000245 }
246
247 return $out;
248 }
Barry Mienydd671972010-10-04 16:33:58 +0200249
Derek Allard2067d1a2008-11-13 22:59:24 +0000250 // --------------------------------------------------------------------
251
252 /**
253 * Generate XML data from a query result object
254 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200255 * @param object $query Query result object
256 * @param array $params Any preferences
Derek Allard2067d1a2008-11-13 22:59:24 +0000257 * @return string
258 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200259 public function xml_from_result($query, $params = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000260 {
Pascal Kriete69b1fcc2009-08-24 16:42:52 +0000261 if ( ! is_object($query) OR ! method_exists($query, 'list_fields'))
Derek Allard2067d1a2008-11-13 22:59:24 +0000262 {
263 show_error('You must submit a valid result object');
264 }
Barry Mienydd671972010-10-04 16:33:58 +0200265
Derek Allard2067d1a2008-11-13 22:59:24 +0000266 // Set our default values
267 foreach (array('root' => 'root', 'element' => 'element', 'newline' => "\n", 'tab' => "\t") as $key => $val)
268 {
269 if ( ! isset($params[$key]))
270 {
271 $params[$key] = $val;
272 }
273 }
Barry Mienydd671972010-10-04 16:33:58 +0200274
Derek Allard2067d1a2008-11-13 22:59:24 +0000275 // Create variables for convenience
276 extract($params);
Barry Mienydd671972010-10-04 16:33:58 +0200277
Derek Allard2067d1a2008-11-13 22:59:24 +0000278 // Load the xml helper
279 $CI =& get_instance();
280 $CI->load->helper('xml');
281
282 // Generate the result
Andrey Andreevb457a402012-04-09 16:11:56 +0300283 $xml = '<'.$root.'>'.$newline;
Andrey Andreevd06acd82012-05-25 00:29:09 +0300284 while ($row = $query->unbuffered_row())
Derek Allard2067d1a2008-11-13 22:59:24 +0000285 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300286 $xml .= $tab.'<'.$element.'>'.$newline;
Derek Allard2067d1a2008-11-13 22:59:24 +0000287 foreach ($row as $key => $val)
288 {
Andrey Andreevb457a402012-04-09 16:11:56 +0300289 $xml .= $tab.$tab.'<'.$key.'>'.xml_convert($val).'</'.$key.'>'.$newline;
Derek Allard2067d1a2008-11-13 22:59:24 +0000290 }
Andrey Andreevb457a402012-04-09 16:11:56 +0300291 $xml .= $tab.'</'.$element.'>'.$newline;
Derek Allard2067d1a2008-11-13 22:59:24 +0000292 }
Barry Mienydd671972010-10-04 16:33:58 +0200293
Andrey Andreevb457a402012-04-09 16:11:56 +0300294 return $xml.'</'.$root.'>'.$newline;
Derek Allard2067d1a2008-11-13 22:59:24 +0000295 }
296
297 // --------------------------------------------------------------------
298
299 /**
300 * Database Backup
301 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200302 * @param array $params
Derek Allard2067d1a2008-11-13 22:59:24 +0000303 * @return void
304 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200305 public function backup($params = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000306 {
307 // If the parameters have not been submitted as an
308 // array then we know that it is simply the table
309 // name, which is a valid short cut.
310 if (is_string($params))
311 {
312 $params = array('tables' => $params);
313 }
Barry Mienydd671972010-10-04 16:33:58 +0200314
Derek Allard2067d1a2008-11-13 22:59:24 +0000315 // Set up our default preferences
316 $prefs = array(
Andrey Andreev24276a32012-01-08 02:44:38 +0200317 'tables' => array(),
318 'ignore' => array(),
319 'filename' => '',
320 'format' => 'gzip', // gzip, zip, txt
321 'add_drop' => TRUE,
322 'add_insert' => TRUE,
323 'newline' => "\n"
324 );
Derek Allard2067d1a2008-11-13 22:59:24 +0000325
326 // Did the user submit any preferences? If so set them....
327 if (count($params) > 0)
328 {
329 foreach ($prefs as $key => $val)
330 {
331 if (isset($params[$key]))
332 {
333 $prefs[$key] = $params[$key];
334 }
335 }
336 }
337
Barry Mienydd671972010-10-04 16:33:58 +0200338 // Are we backing up a complete database or individual tables?
Derek Allard2067d1a2008-11-13 22:59:24 +0000339 // If no table names were submitted we'll fetch the entire table list
Andrey Andreev24276a32012-01-08 02:44:38 +0200340 if (count($prefs['tables']) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000341 {
342 $prefs['tables'] = $this->db->list_tables();
343 }
Barry Mienydd671972010-10-04 16:33:58 +0200344
Derek Allard2067d1a2008-11-13 22:59:24 +0000345 // Validate the format
346 if ( ! in_array($prefs['format'], array('gzip', 'zip', 'txt'), TRUE))
347 {
348 $prefs['format'] = 'txt';
349 }
350
Andrey Andreev24276a32012-01-08 02:44:38 +0200351 // Is the encoder supported? If not, we'll either issue an
Derek Allard2067d1a2008-11-13 22:59:24 +0000352 // error or use plain text depending on the debug settings
Andrey Andreevb457a402012-04-09 16:11:56 +0300353 if (($prefs['format'] === 'gzip' && ! @function_exists('gzencode'))
354 OR ($prefs['format'] === 'zip' && ! @function_exists('gzcompress')))
Derek Allard2067d1a2008-11-13 22:59:24 +0000355 {
356 if ($this->db->db_debug)
357 {
358 return $this->db->display_error('db_unsuported_compression');
359 }
Barry Mienydd671972010-10-04 16:33:58 +0200360
Derek Allard2067d1a2008-11-13 22:59:24 +0000361 $prefs['format'] = 'txt';
362 }
363
Barry Mienydd671972010-10-04 16:33:58 +0200364 // Was a Zip file requested?
Andrey Andreev24276a32012-01-08 02:44:38 +0200365 if ($prefs['format'] === 'zip')
Derek Allard2067d1a2008-11-13 22:59:24 +0000366 {
Andrey Andreev24276a32012-01-08 02:44:38 +0200367 // Set the filename if not provided (only needed with Zip files)
Alex Bilbie48a2baf2012-06-02 11:09:54 +0100368 if ($prefs['filename'] === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000369 {
Andrey Andreev24276a32012-01-08 02:44:38 +0200370 $prefs['filename'] = (count($prefs['tables']) === 1 ? $prefs['tables'] : $this->db->database)
371 .date('Y-m-d_H-i', time()).'.sql';
Derek Allard2067d1a2008-11-13 22:59:24 +0000372 }
Andrey Andreev24276a32012-01-08 02:44:38 +0200373 else
Derek Allard2067d1a2008-11-13 22:59:24 +0000374 {
Andrey Andreev24276a32012-01-08 02:44:38 +0200375 // If they included the .zip file extension we'll remove it
376 if (preg_match('|.+?\.zip$|', $prefs['filename']))
377 {
378 $prefs['filename'] = str_replace('.zip', '', $prefs['filename']);
379 }
380
381 // Tack on the ".sql" file extension if needed
382 if ( ! preg_match('|.+?\.sql$|', $prefs['filename']))
383 {
384 $prefs['filename'] .= '.sql';
385 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000386 }
387
388 // Load the Zip class and output it
Derek Allard2067d1a2008-11-13 22:59:24 +0000389 $CI =& get_instance();
390 $CI->load->library('zip');
Barry Mienydd671972010-10-04 16:33:58 +0200391 $CI->zip->add_data($prefs['filename'], $this->_backup($prefs));
Derek Allard2067d1a2008-11-13 22:59:24 +0000392 return $CI->zip->get_zip();
393 }
Alex Bilbie48a2baf2012-06-02 11:09:54 +0100394 elseif ($prefs['format'] === 'txt') // Was a text file requested?
Andrey Andreev24276a32012-01-08 02:44:38 +0200395 {
396 return $this->_backup($prefs);
397 }
398 elseif ($prefs['format'] === 'gzip') // Was a Gzip file requested?
399 {
400 return gzencode($this->_backup($prefs));
401 }
Barry Mienydd671972010-10-04 16:33:58 +0200402
Andrey Andreev24276a32012-01-08 02:44:38 +0200403 return;
Derek Allard2067d1a2008-11-13 22:59:24 +0000404 }
405
406}
407
Derek Allard2067d1a2008-11-13 22:59:24 +0000408/* End of file DB_utility.php */
Timothy Warren215890b2012-03-20 09:38:16 -0400409/* Location: ./system/database/DB_utility.php */