blob: f7c986fc8bf181c69617d89061f53f9e1475e256 [file] [log] [blame]
Derek Jones0b59f272008-05-13 04:22:33 +00001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allardd2df9bc2007-04-15 17:41:17 +00002/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
Derek Allard3d879d52008-01-18 19:41:32 +00008 * @author ExpressionEngine Dev Team
Rick Ellis9ba2bf22008-09-12 23:34:39 +00009 * @copyright Copyright (c) 2008, EllisLab, Inc.
Derek Jones7a9193a2008-01-21 18:39:20 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
Derek Allardd2df9bc2007-04-15 17:41:17 +000012 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * MySQLi Database Adapter Class - MySQLi only works with PHP 5
20 *
21 * Note: _DB is an extender class that the app controller
22 * creates dynamically based on whether the active record
23 * class is being used or not.
24 *
25 * @package CodeIgniter
26 * @subpackage Drivers
27 * @category Database
Derek Allard3d879d52008-01-18 19:41:32 +000028 * @author ExpressionEngine Dev Team
Derek Jones7a9193a2008-01-21 18:39:20 +000029 * @link http://codeigniter.com/user_guide/database/
Derek Allardd2df9bc2007-04-15 17:41:17 +000030 */
31class CI_DB_mysqli_driver extends CI_DB {
32
Rick Ellis5aa8c602008-10-07 01:24:07 +000033 var $dbdriver = 'mysqli';
Rick Ellis605a07a2008-10-17 04:07:54 +000034
35 // The character used for escaping
36 var $_escape_char = '`';
Rick Ellis5aa8c602008-10-07 01:24:07 +000037
Derek Allardd2df9bc2007-04-15 17:41:17 +000038 /**
Derek Allard694b5b82007-12-18 15:58:03 +000039 * The syntax to count rows is slightly different across different
40 * database engines, so this string appears in each driver and is
41 * used for the count_all() and count_all_results() functions.
42 */
Derek Allard39b622d2008-01-16 21:10:09 +000043 var $_count_string = "SELECT COUNT(*) AS ";
Derek Allard6ddb5a12007-12-18 17:22:50 +000044 var $_random_keyword = ' RAND()'; // database specific random keyword
45
Derek Allard694b5b82007-12-18 15:58:03 +000046 /**
Derek Allardd2df9bc2007-04-15 17:41:17 +000047 * Whether to use the MySQL "delete hack" which allows the number
48 * of affected rows to be shown. Uses a preg_replace when enabled,
49 * adding a bit more processing to all queries.
50 */
51 var $delete_hack = TRUE;
52
53 // --------------------------------------------------------------------
54
55 /**
56 * Non-persistent database connection
57 *
58 * @access private called by the base class
59 * @return resource
60 */
61 function db_connect()
62 {
63 return @mysqli_connect($this->hostname, $this->username, $this->password);
64 }
65
66 // --------------------------------------------------------------------
67
68 /**
69 * Persistent database connection
70 *
71 * @access private called by the base class
72 * @return resource
73 */
74 function db_pconnect()
75 {
76 return $this->db_connect();
77 }
78
79 // --------------------------------------------------------------------
80
81 /**
82 * Select the database
83 *
84 * @access private called by the base class
85 * @return resource
86 */
87 function db_select()
88 {
89 return @mysqli_select_db($this->conn_id, $this->database);
90 }
91
92 // --------------------------------------------------------------------
93
94 /**
Derek Allard39b622d2008-01-16 21:10:09 +000095 * Set client character set
96 *
Rick Ellis605a07a2008-10-17 04:07:54 +000097 * @access private
Derek Allard39b622d2008-01-16 21:10:09 +000098 * @param string
99 * @param string
100 * @return resource
101 */
Rick Ellis605a07a2008-10-17 04:07:54 +0000102 function _db_set_charset($charset, $collation)
Derek Allard39b622d2008-01-16 21:10:09 +0000103 {
Derek Jonesb1f90db2008-02-13 05:22:38 +0000104 return @mysqli_query($this->conn_id, "SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'");
Derek Allard39b622d2008-01-16 21:10:09 +0000105 }
106
107 // --------------------------------------------------------------------
108
109 /**
Derek Allardd2df9bc2007-04-15 17:41:17 +0000110 * Version number query string
111 *
112 * @access public
113 * @return string
114 */
115 function _version()
116 {
117 return "SELECT version() AS ver";
118 }
119
120 // --------------------------------------------------------------------
121
122 /**
123 * Execute the query
124 *
125 * @access private called by the base class
126 * @param string an SQL query
127 * @return resource
128 */
129 function _execute($sql)
130 {
131 $sql = $this->_prep_query($sql);
132 $result = @mysqli_query($this->conn_id, $sql);
133 return $result;
134 }
135
136 // --------------------------------------------------------------------
137
138 /**
139 * Prep the query
140 *
141 * If needed, each database adapter can prep the query string
142 *
143 * @access private called by execute()
144 * @param string an SQL query
145 * @return string
146 */
147 function _prep_query($sql)
148 {
149 // "DELETE FROM TABLE" returns 0 affected rows This hack modifies
150 // the query so that it returns the number of affected rows
151 if ($this->delete_hack === TRUE)
152 {
153 if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
154 {
155 $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
156 }
157 }
158
159 return $sql;
160 }
161
162 // --------------------------------------------------------------------
163
164 /**
165 * Begin Transaction
166 *
167 * @access public
168 * @return bool
169 */
170 function trans_begin($test_mode = FALSE)
171 {
Derek Jones0b59f272008-05-13 04:22:33 +0000172 if ( ! $this->trans_enabled)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000173 {
174 return TRUE;
175 }
176
177 // When transactions are nested we only begin/commit/rollback the outermost ones
178 if ($this->_trans_depth > 0)
179 {
180 return TRUE;
181 }
182
183 // Reset the transaction failure flag.
184 // If the $test_mode flag is set to TRUE transactions will be rolled back
185 // even if the queries produce a successful result.
186 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
187
188 $this->simple_query('SET AUTOCOMMIT=0');
189 $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
190 return TRUE;
191 }
192
193 // --------------------------------------------------------------------
194
195 /**
196 * Commit Transaction
197 *
198 * @access public
199 * @return bool
200 */
201 function trans_commit()
202 {
Derek Jones0b59f272008-05-13 04:22:33 +0000203 if ( ! $this->trans_enabled)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000204 {
205 return TRUE;
206 }
207
208 // When transactions are nested we only begin/commit/rollback the outermost ones
209 if ($this->_trans_depth > 0)
210 {
211 return TRUE;
212 }
213
214 $this->simple_query('COMMIT');
215 $this->simple_query('SET AUTOCOMMIT=1');
216 return TRUE;
217 }
218
219 // --------------------------------------------------------------------
220
221 /**
222 * Rollback Transaction
223 *
224 * @access public
225 * @return bool
226 */
227 function trans_rollback()
228 {
Derek Jones0b59f272008-05-13 04:22:33 +0000229 if ( ! $this->trans_enabled)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000230 {
231 return TRUE;
232 }
233
234 // When transactions are nested we only begin/commit/rollback the outermost ones
235 if ($this->_trans_depth > 0)
236 {
237 return TRUE;
238 }
239
240 $this->simple_query('ROLLBACK');
241 $this->simple_query('SET AUTOCOMMIT=1');
242 return TRUE;
243 }
244
245 // --------------------------------------------------------------------
246
247 /**
248 * Escape String
249 *
250 * @access public
251 * @param string
252 * @return string
253 */
254 function escape_str($str)
Derek Allard694b5b82007-12-18 15:58:03 +0000255 {
Derek Jonesd33972b2008-02-13 04:16:27 +0000256 if (function_exists('mysqli_real_escape_string') AND is_object($this->conn_id))
Derek Allard694b5b82007-12-18 15:58:03 +0000257 {
258 return mysqli_real_escape_string($this->conn_id, $str);
259 }
260 elseif (function_exists('mysql_escape_string'))
261 {
262 return mysql_escape_string($str);
263 }
264 else
265 {
266 return addslashes($str);
267 }
Derek Allardd2df9bc2007-04-15 17:41:17 +0000268 }
269
270 // --------------------------------------------------------------------
271
272 /**
273 * Affected Rows
274 *
275 * @access public
276 * @return integer
277 */
278 function affected_rows()
279 {
280 return @mysqli_affected_rows($this->conn_id);
281 }
282
283 // --------------------------------------------------------------------
284
285 /**
286 * Insert ID
287 *
288 * @access public
289 * @return integer
290 */
291 function insert_id()
292 {
293 return @mysqli_insert_id($this->conn_id);
294 }
295
296 // --------------------------------------------------------------------
297
298 /**
299 * "Count All" query
300 *
301 * Generates a platform-specific query string that counts all records in
302 * the specified database
303 *
304 * @access public
305 * @param string
306 * @return string
307 */
308 function count_all($table = '')
309 {
310 if ($table == '')
311 return '0';
Rick Ellis605a07a2008-10-17 04:07:54 +0000312
313 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows'). " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
Derek Allardd2df9bc2007-04-15 17:41:17 +0000314
315 if ($query->num_rows() == 0)
316 return '0';
317
318 $row = $query->row();
319 return $row->numrows;
320 }
321
322 // --------------------------------------------------------------------
323
324 /**
325 * List table query
326 *
327 * Generates a platform-specific query string so that the table names can be fetched
328 *
329 * @access private
Derek Allard39b622d2008-01-16 21:10:09 +0000330 * @param boolean
Derek Allardd2df9bc2007-04-15 17:41:17 +0000331 * @return string
332 */
Derek Allard694b5b82007-12-18 15:58:03 +0000333 function _list_tables($prefix_limit = FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000334 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000335 $sql = "SHOW TABLES FROM ".$this->_escape_char.$this->database.$this->_escape_char;
Derek Allard694b5b82007-12-18 15:58:03 +0000336
Derek Allard39b622d2008-01-16 21:10:09 +0000337 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
Derek Allard694b5b82007-12-18 15:58:03 +0000338 {
Derek Allard39b622d2008-01-16 21:10:09 +0000339 $sql .= " LIKE '".$this->dbprefix."%'";
Derek Allard694b5b82007-12-18 15:58:03 +0000340 }
341
342 return $sql;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000343 }
344
345 // --------------------------------------------------------------------
346
347 /**
348 * Show column query
349 *
350 * Generates a platform-specific query string so that the column names can be fetched
351 *
352 * @access public
353 * @param string the table name
354 * @return string
355 */
356 function _list_columns($table = '')
357 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000358 return "SHOW COLUMNS FROM ".$table;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000359 }
360
361 // --------------------------------------------------------------------
362
363 /**
364 * Field data query
365 *
366 * Generates a platform-specific query so that the column data can be retrieved
367 *
368 * @access public
369 * @param string the table name
370 * @return object
371 */
372 function _field_data($table)
373 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000374 return "SELECT * FROM ".$table." LIMIT 1";
Derek Allardd2df9bc2007-04-15 17:41:17 +0000375 }
376
377 // --------------------------------------------------------------------
378
379 /**
380 * The error message string
381 *
382 * @access private
383 * @return string
384 */
385 function _error_message()
386 {
387 return mysqli_error($this->conn_id);
388 }
389
390 // --------------------------------------------------------------------
391
392 /**
393 * The error message number
394 *
395 * @access private
396 * @return integer
397 */
398 function _error_number()
399 {
400 return mysqli_errno($this->conn_id);
401 }
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000402
403 // --------------------------------------------------------------------
404
405 /**
Rick Ellis605a07a2008-10-17 04:07:54 +0000406 * Escape the SQL Identifiers
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000407 *
Rick Ellis605a07a2008-10-17 04:07:54 +0000408 * This function escapes column and table names
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000409 *
410 * @access private
Rick Ellis605a07a2008-10-17 04:07:54 +0000411 * @param string
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000412 * @return string
413 */
Rick Ellis605a07a2008-10-17 04:07:54 +0000414 function _escape_identifiers($item)
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000415 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000416 if ($this->_escape_char == '')
Derek Allardd2df9bc2007-04-15 17:41:17 +0000417 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000418 return $item;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000419 }
Rick Ellis605a07a2008-10-17 04:07:54 +0000420
421 if (strpos($item, '.') !== FALSE)
Derek Allard39b622d2008-01-16 21:10:09 +0000422 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000423 $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
Derek Allard61579382008-01-16 22:22:42 +0000424 }
425 else
426 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000427 $str = $this->_escape_char.$item.$this->_escape_char;
Derek Allard39b622d2008-01-16 21:10:09 +0000428 }
Derek Allard39b622d2008-01-16 21:10:09 +0000429
Rick Ellis605a07a2008-10-17 04:07:54 +0000430 // remove duplicates if the user already included the escape
431 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
Derek Allard39b622d2008-01-16 21:10:09 +0000432 }
433
434 // --------------------------------------------------------------------
435
436 /**
Derek Jonesc6ad0232008-01-29 18:44:54 +0000437 * From Tables
438 *
439 * This function implicitly groups FROM tables so there is no confusion
440 * about operator precedence in harmony with SQL standards
441 *
442 * @access public
443 * @param type
444 * @return type
445 */
446 function _from_tables($tables)
447 {
Derek Jones0b59f272008-05-13 04:22:33 +0000448 if ( ! is_array($tables))
Derek Jonesc6ad0232008-01-29 18:44:54 +0000449 {
450 $tables = array($tables);
451 }
452
453 return '('.implode(', ', $tables).')';
454 }
455
456 // --------------------------------------------------------------------
457
458 /**
Derek Allardd2df9bc2007-04-15 17:41:17 +0000459 * Insert statement
460 *
461 * Generates a platform-specific insert string from the supplied data
462 *
463 * @access public
464 * @param string the table name
465 * @param array the insert keys
466 * @param array the insert values
467 * @return string
468 */
469 function _insert($table, $keys, $values)
470 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000471 return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
Derek Allardd2df9bc2007-04-15 17:41:17 +0000472 }
473
474 // --------------------------------------------------------------------
475
476 /**
477 * Update statement
478 *
479 * Generates a platform-specific update string from the supplied data
480 *
481 * @access public
482 * @param string the table name
483 * @param array the update data
484 * @param array the where clause
Derek Allard39b622d2008-01-16 21:10:09 +0000485 * @param array the orderby clause
486 * @param array the limit clause
Derek Allardd2df9bc2007-04-15 17:41:17 +0000487 * @return string
488 */
Derek Allard39b622d2008-01-16 21:10:09 +0000489 function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000490 {
491 foreach($values as $key => $val)
492 {
493 $valstr[] = $key." = ".$val;
494 }
Derek Allardda6d2402007-12-19 14:49:29 +0000495
Derek Jones0b59f272008-05-13 04:22:33 +0000496 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
Derek Allard39b622d2008-01-16 21:10:09 +0000497
498 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
Derek Allardd2df9bc2007-04-15 17:41:17 +0000499
Rick Ellis605a07a2008-10-17 04:07:54 +0000500 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
501
Derek Allard32cf7eb2008-02-05 16:03:50 +0000502 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
Rick Ellis605a07a2008-10-17 04:07:54 +0000503
Derek Allard32cf7eb2008-02-05 16:03:50 +0000504 $sql .= $orderby.$limit;
505
506 return $sql;
Derek Allard39b622d2008-01-16 21:10:09 +0000507 }
508
509
510 // --------------------------------------------------------------------
511
512 /**
513 * Truncate statement
514 *
515 * Generates a platform-specific truncate string from the supplied data
516 * If the database does not support the truncate() command
517 * This function maps to "DELETE FROM table"
518 *
519 * @access public
520 * @param string the table name
521 * @return string
522 */
523 function _truncate($table)
524 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000525 return "TRUNCATE ".$table;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000526 }
527
528 // --------------------------------------------------------------------
529
530 /**
531 * Delete statement
532 *
533 * Generates a platform-specific delete string from the supplied data
534 *
535 * @access public
536 * @param string the table name
537 * @param array the where clause
Derek Allard39b622d2008-01-16 21:10:09 +0000538 * @param string the limit clause
Derek Allardd2df9bc2007-04-15 17:41:17 +0000539 * @return string
540 */
Derek Allard39b622d2008-01-16 21:10:09 +0000541 function _delete($table, $where = array(), $like = array(), $limit = FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000542 {
Derek Allard39b622d2008-01-16 21:10:09 +0000543 $conditions = '';
544
Derek Jones0b59f272008-05-13 04:22:33 +0000545 if (count($where) > 0 OR count($like) > 0)
Derek Allard39b622d2008-01-16 21:10:09 +0000546 {
547 $conditions = "\nWHERE ";
548 $conditions .= implode("\n", $this->ar_where);
549
550 if (count($where) > 0 && count($like) > 0)
551 {
552 $conditions .= " AND ";
553 }
554 $conditions .= implode("\n", $like);
555 }
556
Derek Jones0b59f272008-05-13 04:22:33 +0000557 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
Derek Allarde77d77c2007-12-19 15:01:55 +0000558
Derek Allard39b622d2008-01-16 21:10:09 +0000559 return "DELETE FROM ".$table.$conditions.$limit;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000560 }
561
562 // --------------------------------------------------------------------
563
564 /**
565 * Limit string
566 *
567 * Generates a platform-specific LIMIT clause
568 *
569 * @access public
570 * @param string the sql query string
571 * @param integer the number of rows to limit the query to
572 * @param integer the offset value
573 * @return string
574 */
575 function _limit($sql, $limit, $offset)
576 {
577 $sql .= "LIMIT ".$limit;
578
579 if ($offset > 0)
580 {
581 $sql .= " OFFSET ".$offset;
582 }
583
584 return $sql;
585 }
586
587 // --------------------------------------------------------------------
588
589 /**
590 * Close DB Connection
591 *
592 * @access public
593 * @param resource
594 * @return void
595 */
596 function _close($conn_id)
597 {
598 @mysqli_close($conn_id);
599 }
600
601
602}
603
Derek Jones0b59f272008-05-13 04:22:33 +0000604
605/* End of file mysqli_driver.php */
Derek Jonesa3ffbbb2008-05-11 18:18:29 +0000606/* Location: ./system/database/drivers/mysqli/mysqli_driver.php */