blob: 34b6012cd8fa1b74602ec64b015883f621e02c33 [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 * MySQL Database Adapter Class
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_mysql_driver extends CI_DB {
32
Rick Ellis5aa8c602008-10-07 01:24:07 +000033 var $dbdriver = 'mysql';
34
Rick Ellis605a07a2008-10-17 04:07:54 +000035 // The character used for escaping
36 var $_escape_char = '`';
37
Derek Allardd2df9bc2007-04-15 17:41:17 +000038 /**
39 * Whether to use the MySQL "delete hack" which allows the number
40 * of affected rows to be shown. Uses a preg_replace when enabled,
41 * adding a bit more processing to all queries.
42 */
43 var $delete_hack = TRUE;
Derek Allard6ddb5a12007-12-18 17:22:50 +000044
45 /**
46 * The syntax to count rows is slightly different across different
47 * database engines, so this string appears in each driver and is
48 * used for the count_all() and count_all_results() functions.
49 */
Derek Allard39b622d2008-01-16 21:10:09 +000050 var $_count_string = 'SELECT COUNT(*) AS ';
Derek Allard6ddb5a12007-12-18 17:22:50 +000051 var $_random_keyword = ' RAND()'; // database specific random keyword
Derek Allardd2df9bc2007-04-15 17:41:17 +000052
53 /**
54 * Non-persistent database connection
55 *
56 * @access private called by the base class
57 * @return resource
58 */
59 function db_connect()
60 {
61 return @mysql_connect($this->hostname, $this->username, $this->password, TRUE);
62 }
63
64 // --------------------------------------------------------------------
65
66 /**
67 * Persistent database connection
68 *
69 * @access private called by the base class
70 * @return resource
71 */
72 function db_pconnect()
73 {
74 return @mysql_pconnect($this->hostname, $this->username, $this->password);
75 }
76
77 // --------------------------------------------------------------------
78
79 /**
80 * Select the database
81 *
82 * @access private called by the base class
83 * @return resource
84 */
85 function db_select()
86 {
87 return @mysql_select_db($this->database, $this->conn_id);
88 }
89
90 // --------------------------------------------------------------------
91
92 /**
Derek Allard39b622d2008-01-16 21:10:09 +000093 * Set client character set
94 *
95 * @access public
96 * @param string
97 * @param string
98 * @return resource
99 */
100 function db_set_charset($charset, $collation)
101 {
102 return @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id);
103 }
104
105 // --------------------------------------------------------------------
106
107 /**
Derek Allardd2df9bc2007-04-15 17:41:17 +0000108 * Version number query string
109 *
110 * @access public
111 * @return string
112 */
113 function _version()
114 {
115 return "SELECT version() AS ver";
116 }
117
118 // --------------------------------------------------------------------
119
120 /**
121 * Execute the query
122 *
123 * @access private called by the base class
124 * @param string an SQL query
125 * @return resource
126 */
127 function _execute($sql)
128 {
129 $sql = $this->_prep_query($sql);
130 return @mysql_query($sql, $this->conn_id);
131 }
132
133 // --------------------------------------------------------------------
134
135 /**
136 * Prep the query
137 *
138 * If needed, each database adapter can prep the query string
139 *
140 * @access private called by execute()
141 * @param string an SQL query
142 * @return string
143 */
144 function _prep_query($sql)
145 {
146 // "DELETE FROM TABLE" returns 0 affected rows This hack modifies
147 // the query so that it returns the number of affected rows
148 if ($this->delete_hack === TRUE)
149 {
150 if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
151 {
152 $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
153 }
154 }
155
156 return $sql;
157 }
158
159 // --------------------------------------------------------------------
160
161 /**
162 * Begin Transaction
163 *
164 * @access public
165 * @return bool
166 */
167 function trans_begin($test_mode = FALSE)
168 {
Derek Jones0b59f272008-05-13 04:22:33 +0000169 if ( ! $this->trans_enabled)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000170 {
171 return TRUE;
172 }
173
174 // When transactions are nested we only begin/commit/rollback the outermost ones
175 if ($this->_trans_depth > 0)
176 {
177 return TRUE;
178 }
179
180 // Reset the transaction failure flag.
181 // If the $test_mode flag is set to TRUE transactions will be rolled back
182 // even if the queries produce a successful result.
183 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
184
185 $this->simple_query('SET AUTOCOMMIT=0');
186 $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
187 return TRUE;
188 }
189
190 // --------------------------------------------------------------------
191
192 /**
193 * Commit Transaction
194 *
195 * @access public
196 * @return bool
197 */
198 function trans_commit()
199 {
Derek Jones0b59f272008-05-13 04:22:33 +0000200 if ( ! $this->trans_enabled)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000201 {
202 return TRUE;
203 }
204
205 // When transactions are nested we only begin/commit/rollback the outermost ones
206 if ($this->_trans_depth > 0)
207 {
208 return TRUE;
209 }
210
211 $this->simple_query('COMMIT');
212 $this->simple_query('SET AUTOCOMMIT=1');
213 return TRUE;
214 }
215
216 // --------------------------------------------------------------------
217
218 /**
219 * Rollback Transaction
220 *
221 * @access public
222 * @return bool
223 */
224 function trans_rollback()
225 {
Derek Jones0b59f272008-05-13 04:22:33 +0000226 if ( ! $this->trans_enabled)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000227 {
228 return TRUE;
229 }
230
231 // When transactions are nested we only begin/commit/rollback the outermost ones
232 if ($this->_trans_depth > 0)
233 {
234 return TRUE;
235 }
236
237 $this->simple_query('ROLLBACK');
238 $this->simple_query('SET AUTOCOMMIT=1');
239 return TRUE;
240 }
241
242 // --------------------------------------------------------------------
243
244 /**
245 * Escape String
246 *
247 * @access public
248 * @param string
249 * @return string
250 */
251 function escape_str($str)
252 {
Derek Allard694b5b82007-12-18 15:58:03 +0000253 if (is_array($str))
Derek Allard993925b2008-08-21 12:43:31 +0000254 {
255 foreach($str as $key => $val)
256 {
257 $str[$key] = $this->escape_str($val);
258 }
259
260 return $str;
261 }
262
Derek Allard694b5b82007-12-18 15:58:03 +0000263 if (function_exists('mysql_real_escape_string') AND is_resource($this->conn_id))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000264 {
265 return mysql_real_escape_string($str, $this->conn_id);
266 }
267 elseif (function_exists('mysql_escape_string'))
268 {
269 return mysql_escape_string($str);
270 }
271 else
272 {
273 return addslashes($str);
274 }
275 }
276
277 // --------------------------------------------------------------------
278
279 /**
280 * Affected Rows
281 *
282 * @access public
283 * @return integer
284 */
285 function affected_rows()
286 {
287 return @mysql_affected_rows($this->conn_id);
288 }
289
290 // --------------------------------------------------------------------
291
292 /**
293 * Insert ID
294 *
295 * @access public
296 * @return integer
297 */
298 function insert_id()
299 {
300 return @mysql_insert_id($this->conn_id);
301 }
302
303 // --------------------------------------------------------------------
304
305 /**
306 * "Count All" query
307 *
308 * Generates a platform-specific query string that counts all records in
309 * the specified database
310 *
311 * @access public
312 * @param string
313 * @return string
314 */
315 function count_all($table = '')
316 {
317 if ($table == '')
318 return '0';
319
Rick Ellis605a07a2008-10-17 04:07:54 +0000320 $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 +0000321
Rick Ellisff734012008-09-30 20:38:12 +0000322 if ($query->num_rows() == 0)
323 return '0';
324
Derek Allardd2df9bc2007-04-15 17:41:17 +0000325 $row = $query->row();
Derek Allardb94b89c2008-04-28 23:18:00 +0000326 return (int)$row->numrows;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000327 }
328
329 // --------------------------------------------------------------------
330
331 /**
332 * List table query
333 *
334 * Generates a platform-specific query string so that the table names can be fetched
335 *
336 * @access private
Derek Allard39b622d2008-01-16 21:10:09 +0000337 * @param boolean
Derek Allardd2df9bc2007-04-15 17:41:17 +0000338 * @return string
339 */
Derek Allard694b5b82007-12-18 15:58:03 +0000340 function _list_tables($prefix_limit = FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000341 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000342 $sql = "SHOW TABLES FROM ".$this->_escape_char.$this->database.$this->_escape_char;
Derek Allard39b622d2008-01-16 21:10:09 +0000343
344 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
Derek Allard694b5b82007-12-18 15:58:03 +0000345 {
Derek Allard39b622d2008-01-16 21:10:09 +0000346 $sql .= " LIKE '".$this->dbprefix."%'";
Derek Allard694b5b82007-12-18 15:58:03 +0000347 }
Derek Allard39b622d2008-01-16 21:10:09 +0000348
Derek Allard694b5b82007-12-18 15:58:03 +0000349 return $sql;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000350 }
351
352 // --------------------------------------------------------------------
353
354 /**
355 * Show column query
356 *
357 * Generates a platform-specific query string so that the column names can be fetched
358 *
359 * @access public
360 * @param string the table name
361 * @return string
362 */
363 function _list_columns($table = '')
364 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000365 return "SHOW COLUMNS FROM ".$table;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000366 }
367
368 // --------------------------------------------------------------------
369
370 /**
371 * Field data query
372 *
373 * Generates a platform-specific query so that the column data can be retrieved
374 *
375 * @access public
376 * @param string the table name
377 * @return object
378 */
379 function _field_data($table)
380 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000381 return "SELECT * FROM ".$table." LIMIT 1";
Derek Allardd2df9bc2007-04-15 17:41:17 +0000382 }
383
384 // --------------------------------------------------------------------
385
386 /**
387 * The error message string
388 *
389 * @access private
390 * @return string
391 */
392 function _error_message()
393 {
394 return mysql_error($this->conn_id);
395 }
396
397 // --------------------------------------------------------------------
398
399 /**
400 * The error message number
401 *
402 * @access private
403 * @return integer
404 */
405 function _error_number()
406 {
407 return mysql_errno($this->conn_id);
408 }
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000409
410 // --------------------------------------------------------------------
411
412 /**
Rick Ellis605a07a2008-10-17 04:07:54 +0000413 * Escape the SQL Identifiers
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000414 *
Rick Ellis605a07a2008-10-17 04:07:54 +0000415 * This function escapes column and table names
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000416 *
417 * @access private
Rick Ellis605a07a2008-10-17 04:07:54 +0000418 * @param string
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000419 * @return string
420 */
Rick Ellis605a07a2008-10-17 04:07:54 +0000421 function _escape_identifiers($item)
Rick Ellis52dc8ca2008-09-30 19:53:52 +0000422 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000423 if ($this->_escape_char == '')
Derek Allardd2df9bc2007-04-15 17:41:17 +0000424 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000425 return $item;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000426 }
Rick Ellis605a07a2008-10-17 04:07:54 +0000427
428 if (strpos($item, '.') !== FALSE)
Derek Allard39b622d2008-01-16 21:10:09 +0000429 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000430 $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
Derek Allard39b622d2008-01-16 21:10:09 +0000431 }
Derek Jones91f50b62008-01-16 21:48:18 +0000432 else
433 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000434 $str = $this->_escape_char.$item.$this->_escape_char;
Derek Jones91f50b62008-01-16 21:48:18 +0000435 }
Derek Allardd2df9bc2007-04-15 17:41:17 +0000436
Rick Ellis605a07a2008-10-17 04:07:54 +0000437 // remove duplicates if the user already included the escape
438 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
Derek Allard39b622d2008-01-16 21:10:09 +0000439 }
440
Derek Allardd2df9bc2007-04-15 17:41:17 +0000441 // --------------------------------------------------------------------
442
443 /**
Derek Jonesc6ad0232008-01-29 18:44:54 +0000444 * From Tables
445 *
446 * This function implicitly groups FROM tables so there is no confusion
447 * about operator precedence in harmony with SQL standards
448 *
449 * @access public
450 * @param type
451 * @return type
452 */
453 function _from_tables($tables)
454 {
Derek Jones0b59f272008-05-13 04:22:33 +0000455 if ( ! is_array($tables))
Derek Jonesc6ad0232008-01-29 18:44:54 +0000456 {
457 $tables = array($tables);
458 }
459
460 return '('.implode(', ', $tables).')';
461 }
462
463 // --------------------------------------------------------------------
464
465 /**
Derek Allardd2df9bc2007-04-15 17:41:17 +0000466 * Insert statement
467 *
468 * Generates a platform-specific insert string from the supplied data
469 *
470 * @access public
471 * @param string the table name
472 * @param array the insert keys
473 * @param array the insert values
474 * @return string
475 */
476 function _insert($table, $keys, $values)
477 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000478 return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
Derek Allardd2df9bc2007-04-15 17:41:17 +0000479 }
480
481 // --------------------------------------------------------------------
482
483 /**
484 * Update statement
485 *
486 * Generates a platform-specific update string from the supplied data
487 *
488 * @access public
489 * @param string the table name
490 * @param array the update data
491 * @param array the where clause
Derek Allard39b622d2008-01-16 21:10:09 +0000492 * @param array the orderby clause
493 * @param array the limit clause
Derek Allardd2df9bc2007-04-15 17:41:17 +0000494 * @return string
495 */
Derek Allard39b622d2008-01-16 21:10:09 +0000496 function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000497 {
498 foreach($values as $key => $val)
499 {
500 $valstr[] = $key." = ".$val;
501 }
Derek Allardda6d2402007-12-19 14:49:29 +0000502
Derek Jones0b59f272008-05-13 04:22:33 +0000503 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
Derek Allard39b622d2008-01-16 21:10:09 +0000504
505 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
Derek Allardd2df9bc2007-04-15 17:41:17 +0000506
Rick Ellis605a07a2008-10-17 04:07:54 +0000507 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
508
Derek Allard32cf7eb2008-02-05 16:03:50 +0000509 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
Rick Ellis605a07a2008-10-17 04:07:54 +0000510
Derek Allard32cf7eb2008-02-05 16:03:50 +0000511 $sql .= $orderby.$limit;
512
513 return $sql;
Derek Allard39b622d2008-01-16 21:10:09 +0000514 }
515
516 // --------------------------------------------------------------------
517
518 /**
519 * Truncate statement
520 *
521 * Generates a platform-specific truncate string from the supplied data
522 * If the database does not support the truncate() command
523 * This function maps to "DELETE FROM table"
524 *
525 * @access public
526 * @param string the table name
527 * @return string
528 */
529 function _truncate($table)
530 {
Rick Ellis605a07a2008-10-17 04:07:54 +0000531 return "TRUNCATE ".$table;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000532 }
533
534 // --------------------------------------------------------------------
535
536 /**
537 * Delete statement
538 *
539 * Generates a platform-specific delete string from the supplied data
540 *
541 * @access public
542 * @param string the table name
543 * @param array the where clause
Derek Allard39b622d2008-01-16 21:10:09 +0000544 * @param string the limit clause
Derek Allardd2df9bc2007-04-15 17:41:17 +0000545 * @return string
546 */
Derek Allard39b622d2008-01-16 21:10:09 +0000547 function _delete($table, $where = array(), $like = array(), $limit = FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000548 {
Derek Allard39b622d2008-01-16 21:10:09 +0000549 $conditions = '';
550
Derek Jones0b59f272008-05-13 04:22:33 +0000551 if (count($where) > 0 OR count($like) > 0)
Derek Allard39b622d2008-01-16 21:10:09 +0000552 {
553 $conditions = "\nWHERE ";
554 $conditions .= implode("\n", $this->ar_where);
555
556 if (count($where) > 0 && count($like) > 0)
557 {
558 $conditions .= " AND ";
559 }
560 $conditions .= implode("\n", $like);
561 }
562
Derek Jones0b59f272008-05-13 04:22:33 +0000563 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
Derek Allarde77d77c2007-12-19 15:01:55 +0000564
Derek Allard39b622d2008-01-16 21:10:09 +0000565 return "DELETE FROM ".$table.$conditions.$limit;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000566 }
567
568 // --------------------------------------------------------------------
569
570 /**
571 * Limit string
572 *
573 * Generates a platform-specific LIMIT clause
574 *
575 * @access public
576 * @param string the sql query string
577 * @param integer the number of rows to limit the query to
578 * @param integer the offset value
579 * @return string
580 */
581 function _limit($sql, $limit, $offset)
582 {
583 if ($offset == 0)
584 {
585 $offset = '';
586 }
587 else
588 {
589 $offset .= ", ";
590 }
591
592 return $sql."LIMIT ".$offset.$limit;
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 @mysql_close($conn_id);
607 }
608
609}
610
Derek Jones0b59f272008-05-13 04:22:33 +0000611
612/* End of file mysql_driver.php */
Derek Jonesa3ffbbb2008-05-11 18:18:29 +0000613/* Location: ./system/database/drivers/mysql/mysql_driver.php */