blob: f72db64b646c9c8e47d25caf04b44923d1ff587e [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 {
Derek Jones4ba802d2008-10-24 16:43:02 +000063 if ($this->port != '')
64 {
65 return @mysqli_connect($this->hostname, $this->username, $this->password, $this->database, $this->port);
66 }
67 else
68 {
69 return @mysqli_connect($this->hostname, $this->username, $this->password, $this->database);
70 }
71
Derek Allardd2df9bc2007-04-15 17:41:17 +000072 }
73
74 // --------------------------------------------------------------------
75
76 /**
77 * Persistent database connection
78 *
79 * @access private called by the base class
80 * @return resource
81 */
82 function db_pconnect()
83 {
84 return $this->db_connect();
85 }
86
87 // --------------------------------------------------------------------
88
89 /**
90 * Select the database
91 *
92 * @access private called by the base class
93 * @return resource
94 */
95 function db_select()
96 {
97 return @mysqli_select_db($this->conn_id, $this->database);
98 }
99
100 // --------------------------------------------------------------------
101
102 /**
Derek Allard39b622d2008-01-16 21:10:09 +0000103 * Set client character set
104 *
Rick Ellis605a07a2008-10-17 04:07:54 +0000105 * @access private
Derek Allard39b622d2008-01-16 21:10:09 +0000106 * @param string
107 * @param string
108 * @return resource
109 */
Rick Ellis605a07a2008-10-17 04:07:54 +0000110 function _db_set_charset($charset, $collation)
Derek Allard39b622d2008-01-16 21:10:09 +0000111 {
Derek Jonesb1f90db2008-02-13 05:22:38 +0000112 return @mysqli_query($this->conn_id, "SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'");
Derek Allard39b622d2008-01-16 21:10:09 +0000113 }
114
115 // --------------------------------------------------------------------
116
117 /**
Derek Allardd2df9bc2007-04-15 17:41:17 +0000118 * Version number query string
119 *
120 * @access public
121 * @return string
122 */
123 function _version()
124 {
125 return "SELECT version() AS ver";
126 }
127
128 // --------------------------------------------------------------------
129
130 /**
131 * Execute the query
132 *
133 * @access private called by the base class
134 * @param string an SQL query
135 * @return resource
136 */
137 function _execute($sql)
138 {
139 $sql = $this->_prep_query($sql);
140 $result = @mysqli_query($this->conn_id, $sql);
141 return $result;
142 }
143
144 // --------------------------------------------------------------------
145
146 /**
147 * Prep the query
148 *
149 * If needed, each database adapter can prep the query string
150 *
151 * @access private called by execute()
152 * @param string an SQL query
153 * @return string
154 */
155 function _prep_query($sql)
156 {
157 // "DELETE FROM TABLE" returns 0 affected rows This hack modifies
158 // the query so that it returns the number of affected rows
159 if ($this->delete_hack === TRUE)
160 {
161 if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
162 {
163 $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
164 }
165 }
166
167 return $sql;
168 }
169
170 // --------------------------------------------------------------------
171
172 /**
173 * Begin Transaction
174 *
175 * @access public
176 * @return bool
177 */
178 function trans_begin($test_mode = FALSE)
179 {
Derek Jones0b59f272008-05-13 04:22:33 +0000180 if ( ! $this->trans_enabled)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000181 {
182 return TRUE;
183 }
184
185 // When transactions are nested we only begin/commit/rollback the outermost ones
186 if ($this->_trans_depth > 0)
187 {
188 return TRUE;
189 }
190
191 // Reset the transaction failure flag.
192 // If the $test_mode flag is set to TRUE transactions will be rolled back
193 // even if the queries produce a successful result.
194 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
195
196 $this->simple_query('SET AUTOCOMMIT=0');
197 $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
198 return TRUE;
199 }
200
201 // --------------------------------------------------------------------
202
203 /**
204 * Commit Transaction
205 *
206 * @access public
207 * @return bool
208 */
209 function trans_commit()
210 {
Derek Jones0b59f272008-05-13 04:22:33 +0000211 if ( ! $this->trans_enabled)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000212 {
213 return TRUE;
214 }
215
216 // When transactions are nested we only begin/commit/rollback the outermost ones
217 if ($this->_trans_depth > 0)
218 {
219 return TRUE;
220 }
221
222 $this->simple_query('COMMIT');
223 $this->simple_query('SET AUTOCOMMIT=1');
224 return TRUE;
225 }
226
227 // --------------------------------------------------------------------
228
229 /**
230 * Rollback Transaction
231 *
232 * @access public
233 * @return bool
234 */
235 function trans_rollback()
236 {
Derek Jones0b59f272008-05-13 04:22:33 +0000237 if ( ! $this->trans_enabled)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000238 {
239 return TRUE;
240 }
241
242 // When transactions are nested we only begin/commit/rollback the outermost ones
243 if ($this->_trans_depth > 0)
244 {
245 return TRUE;
246 }
247
248 $this->simple_query('ROLLBACK');
249 $this->simple_query('SET AUTOCOMMIT=1');
250 return TRUE;
251 }
252
253 // --------------------------------------------------------------------
254
255 /**
256 * Escape String
257 *
258 * @access public
259 * @param string
260 * @return string
261 */
262 function escape_str($str)
Derek Allard694b5b82007-12-18 15:58:03 +0000263 {
Derek Jonesd33972b2008-02-13 04:16:27 +0000264 if (function_exists('mysqli_real_escape_string') AND is_object($this->conn_id))
Derek Allard694b5b82007-12-18 15:58:03 +0000265 {
266 return mysqli_real_escape_string($this->conn_id, $str);
267 }
268 elseif (function_exists('mysql_escape_string'))
269 {
270 return mysql_escape_string($str);
271 }
272 else
273 {
274 return addslashes($str);
275 }
Derek Allardd2df9bc2007-04-15 17:41:17 +0000276 }
277
278 // --------------------------------------------------------------------
279
280 /**
281 * Affected Rows
282 *
283 * @access public
284 * @return integer
285 */
286 function affected_rows()
287 {
288 return @mysqli_affected_rows($this->conn_id);
289 }
290
291 // --------------------------------------------------------------------
292
293 /**
294 * Insert ID
295 *
296 * @access public
297 * @return integer
298 */
299 function insert_id()
300 {
301 return @mysqli_insert_id($this->conn_id);
302 }
303
304 // --------------------------------------------------------------------
305
306 /**
307 * "Count All" query
308 *
309 * Generates a platform-specific query string that counts all records in
310 * the specified database
311 *
312 * @access public
313 * @param string
314 * @return string
315 */
316 function count_all($table = '')
317 {
318 if ($table == '')
319 return '0';
Rick Ellis605a07a2008-10-17 04:07:54 +0000320
321 $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 +0000322
323 if ($query->num_rows() == 0)
324 return '0';
325
326 $row = $query->row();
327 return $row->numrows;
328 }
329
330 // --------------------------------------------------------------------
331
332 /**
333 * List table query
334 *
335 * Generates a platform-specific query string so that the table names can be fetched
336 *
337 * @access private
Derek Allard39b622d2008-01-16 21:10:09 +0000338 * @param boolean
Derek Allardd2df9bc2007-04-15 17:41:17 +0000339 * @return string
340 */
Derek Allard694b5b82007-12-18 15:58:03 +0000341 function _list_tables($prefix_limit = FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000342 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000343 $sql = "SHOW TABLES FROM ".$this->_escape_char.$this->database.$this->_escape_char;
Derek Allard694b5b82007-12-18 15:58:03 +0000344
Derek Allard39b622d2008-01-16 21:10:09 +0000345 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
Derek Allard694b5b82007-12-18 15:58:03 +0000346 {
Derek Allard39b622d2008-01-16 21:10:09 +0000347 $sql .= " LIKE '".$this->dbprefix."%'";
Derek Allard694b5b82007-12-18 15:58:03 +0000348 }
349
350 return $sql;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000351 }
352
353 // --------------------------------------------------------------------
354
355 /**
356 * Show column query
357 *
358 * Generates a platform-specific query string so that the column names can be fetched
359 *
360 * @access public
361 * @param string the table name
362 * @return string
363 */
364 function _list_columns($table = '')
365 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000366 return "SHOW COLUMNS FROM ".$table;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000367 }
368
369 // --------------------------------------------------------------------
370
371 /**
372 * Field data query
373 *
374 * Generates a platform-specific query so that the column data can be retrieved
375 *
376 * @access public
377 * @param string the table name
378 * @return object
379 */
380 function _field_data($table)
381 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000382 return "SELECT * FROM ".$table." LIMIT 1";
Derek Allardd2df9bc2007-04-15 17:41:17 +0000383 }
384
385 // --------------------------------------------------------------------
386
387 /**
388 * The error message string
389 *
390 * @access private
391 * @return string
392 */
393 function _error_message()
394 {
395 return mysqli_error($this->conn_id);
396 }
397
398 // --------------------------------------------------------------------
399
400 /**
401 * The error message number
402 *
403 * @access private
404 * @return integer
405 */
406 function _error_number()
407 {
408 return mysqli_errno($this->conn_id);
409 }
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000410
411 // --------------------------------------------------------------------
412
413 /**
Rick Ellis605a07a2008-10-17 04:07:54 +0000414 * Escape the SQL Identifiers
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000415 *
Rick Ellis605a07a2008-10-17 04:07:54 +0000416 * This function escapes column and table names
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000417 *
418 * @access private
Rick Ellis605a07a2008-10-17 04:07:54 +0000419 * @param string
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000420 * @return string
421 */
Rick Ellis605a07a2008-10-17 04:07:54 +0000422 function _escape_identifiers($item)
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000423 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000424 if ($this->_escape_char == '')
Derek Allardd2df9bc2007-04-15 17:41:17 +0000425 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000426 return $item;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000427 }
Rick Ellis605a07a2008-10-17 04:07:54 +0000428
429 if (strpos($item, '.') !== FALSE)
Derek Allard39b622d2008-01-16 21:10:09 +0000430 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000431 $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
Derek Allard61579382008-01-16 22:22:42 +0000432 }
433 else
434 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000435 $str = $this->_escape_char.$item.$this->_escape_char;
Derek Allard39b622d2008-01-16 21:10:09 +0000436 }
Derek Allard39b622d2008-01-16 21:10:09 +0000437
Rick Ellis605a07a2008-10-17 04:07:54 +0000438 // remove duplicates if the user already included the escape
439 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
Derek Allard39b622d2008-01-16 21:10:09 +0000440 }
441
442 // --------------------------------------------------------------------
443
444 /**
Derek Jonesc6ad0232008-01-29 18:44:54 +0000445 * From Tables
446 *
447 * This function implicitly groups FROM tables so there is no confusion
448 * about operator precedence in harmony with SQL standards
449 *
450 * @access public
451 * @param type
452 * @return type
453 */
454 function _from_tables($tables)
455 {
Derek Jones0b59f272008-05-13 04:22:33 +0000456 if ( ! is_array($tables))
Derek Jonesc6ad0232008-01-29 18:44:54 +0000457 {
458 $tables = array($tables);
459 }
460
461 return '('.implode(', ', $tables).')';
462 }
463
464 // --------------------------------------------------------------------
465
466 /**
Derek Allardd2df9bc2007-04-15 17:41:17 +0000467 * Insert statement
468 *
469 * Generates a platform-specific insert string from the supplied data
470 *
471 * @access public
472 * @param string the table name
473 * @param array the insert keys
474 * @param array the insert values
475 * @return string
476 */
477 function _insert($table, $keys, $values)
478 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000479 return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
Derek Allardd2df9bc2007-04-15 17:41:17 +0000480 }
481
482 // --------------------------------------------------------------------
483
484 /**
485 * Update statement
486 *
487 * Generates a platform-specific update string from the supplied data
488 *
489 * @access public
490 * @param string the table name
491 * @param array the update data
492 * @param array the where clause
Derek Allard39b622d2008-01-16 21:10:09 +0000493 * @param array the orderby clause
494 * @param array the limit clause
Derek Allardd2df9bc2007-04-15 17:41:17 +0000495 * @return string
496 */
Derek Allard39b622d2008-01-16 21:10:09 +0000497 function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000498 {
499 foreach($values as $key => $val)
500 {
501 $valstr[] = $key." = ".$val;
502 }
Derek Allardda6d2402007-12-19 14:49:29 +0000503
Derek Jones0b59f272008-05-13 04:22:33 +0000504 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
Derek Allard39b622d2008-01-16 21:10:09 +0000505
506 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
Derek Allardd2df9bc2007-04-15 17:41:17 +0000507
Rick Ellis605a07a2008-10-17 04:07:54 +0000508 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
509
Derek Allard32cf7eb2008-02-05 16:03:50 +0000510 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
Rick Ellis605a07a2008-10-17 04:07:54 +0000511
Derek Allard32cf7eb2008-02-05 16:03:50 +0000512 $sql .= $orderby.$limit;
513
514 return $sql;
Derek Allard39b622d2008-01-16 21:10:09 +0000515 }
516
517
518 // --------------------------------------------------------------------
519
520 /**
521 * Truncate statement
522 *
523 * Generates a platform-specific truncate string from the supplied data
524 * If the database does not support the truncate() command
525 * This function maps to "DELETE FROM table"
526 *
527 * @access public
528 * @param string the table name
529 * @return string
530 */
531 function _truncate($table)
532 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000533 return "TRUNCATE ".$table;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000534 }
535
536 // --------------------------------------------------------------------
537
538 /**
539 * Delete statement
540 *
541 * Generates a platform-specific delete string from the supplied data
542 *
543 * @access public
544 * @param string the table name
545 * @param array the where clause
Derek Allard39b622d2008-01-16 21:10:09 +0000546 * @param string the limit clause
Derek Allardd2df9bc2007-04-15 17:41:17 +0000547 * @return string
548 */
Derek Allard39b622d2008-01-16 21:10:09 +0000549 function _delete($table, $where = array(), $like = array(), $limit = FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000550 {
Derek Allard39b622d2008-01-16 21:10:09 +0000551 $conditions = '';
552
Derek Jones0b59f272008-05-13 04:22:33 +0000553 if (count($where) > 0 OR count($like) > 0)
Derek Allard39b622d2008-01-16 21:10:09 +0000554 {
555 $conditions = "\nWHERE ";
556 $conditions .= implode("\n", $this->ar_where);
557
558 if (count($where) > 0 && count($like) > 0)
559 {
560 $conditions .= " AND ";
561 }
562 $conditions .= implode("\n", $like);
563 }
564
Derek Jones0b59f272008-05-13 04:22:33 +0000565 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
Derek Allarde77d77c2007-12-19 15:01:55 +0000566
Derek Allard39b622d2008-01-16 21:10:09 +0000567 return "DELETE FROM ".$table.$conditions.$limit;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000568 }
569
570 // --------------------------------------------------------------------
571
572 /**
573 * Limit string
574 *
575 * Generates a platform-specific LIMIT clause
576 *
577 * @access public
578 * @param string the sql query string
579 * @param integer the number of rows to limit the query to
580 * @param integer the offset value
581 * @return string
582 */
583 function _limit($sql, $limit, $offset)
584 {
585 $sql .= "LIMIT ".$limit;
586
587 if ($offset > 0)
588 {
589 $sql .= " OFFSET ".$offset;
590 }
591
592 return $sql;
593 }
594
595 // --------------------------------------------------------------------
596
597 /**
598 * Close DB Connection
599 *
600 * @access public
601 * @param resource
602 * @return void
603 */
604 function _close($conn_id)
605 {
606 @mysqli_close($conn_id);
607 }
608
609
610}
611
Derek Jones0b59f272008-05-13 04:22:33 +0000612
613/* End of file mysqli_driver.php */
Derek Jonesa3ffbbb2008-05-11 18:18:29 +0000614/* Location: ./system/database/drivers/mysqli/mysqli_driver.php */