converted to unix-style eol
[www-register-wizard.git] / database / drivers / mysql / mysql_driver.php
1 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 /**
3  * CodeIgniter
4  *
5  * An open source application development framework for PHP 4.3.2 or newer
6  *
7  * @package             CodeIgniter
8  * @author              ExpressionEngine Dev Team
9  * @copyright   Copyright (c) 2008, EllisLab, Inc.
10  * @license             http://codeigniter.com/user_guide/license.html
11  * @link                http://codeigniter.com
12  * @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
28  * @author              ExpressionEngine Dev Team
29  * @link                http://codeigniter.com/user_guide/database/
30  */
31 class CI_DB_mysql_driver extends CI_DB {
32
33         var $dbdriver = 'mysql';
34
35         // The character used for escaping
36         var     $_escape_char = '`';
37         
38         /**
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;
44         
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          */
50         var $_count_string = 'SELECT COUNT(*) AS ';
51         var $_random_keyword = ' RAND()'; // database specific random keyword
52
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                 if ($this->port != '')
62                 {
63                         $this->hostname .= ':'.$this->port;
64                 }
65                 
66                 return @mysql_connect($this->hostname, $this->username, $this->password, TRUE);
67         }
68         
69         // --------------------------------------------------------------------
70
71         /**
72          * Persistent database connection
73          *
74          * @access      private called by the base class
75          * @return      resource
76          */     
77         function db_pconnect()
78         {
79                 if ($this->port != '')
80                 {
81                         $this->hostname .= ':'.$this->port;
82                 }
83
84                 return @mysql_pconnect($this->hostname, $this->username, $this->password);
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 @mysql_select_db($this->database, $this->conn_id);
98         }
99
100         // --------------------------------------------------------------------
101
102         /**
103          * Set client character set
104          *
105          * @access      public
106          * @param       string
107          * @param       string
108          * @return      resource
109          */
110         function db_set_charset($charset, $collation)
111         {
112                 return @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id);
113         }
114
115         // --------------------------------------------------------------------
116         
117         /**
118          * 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                 return @mysql_query($sql, $this->conn_id);
141         }
142         
143         // --------------------------------------------------------------------
144
145         /**
146          * Prep the query
147          *
148          * If needed, each database adapter can prep the query string
149          *
150          * @access      private called by execute()
151          * @param       string  an SQL query
152          * @return      string
153          */     
154         function _prep_query($sql)
155         {
156                 // "DELETE FROM TABLE" returns 0 affected rows This hack modifies
157                 // the query so that it returns the number of affected rows
158                 if ($this->delete_hack === TRUE)
159                 {
160                         if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
161                         {
162                                 $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
163                         }
164                 }
165                 
166                 return $sql;
167         }
168
169         // --------------------------------------------------------------------
170
171         /**
172          * Begin Transaction
173          *
174          * @access      public
175          * @return      bool            
176          */     
177         function trans_begin($test_mode = FALSE)
178         {
179                 if ( ! $this->trans_enabled)
180                 {
181                         return TRUE;
182                 }
183                 
184                 // When transactions are nested we only begin/commit/rollback the outermost ones
185                 if ($this->_trans_depth > 0)
186                 {
187                         return TRUE;
188                 }
189
190                 // Reset the transaction failure flag.
191                 // If the $test_mode flag is set to TRUE transactions will be rolled back
192                 // even if the queries produce a successful result.
193                 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
194                 
195                 $this->simple_query('SET AUTOCOMMIT=0');
196                 $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
197                 return TRUE;
198         }
199
200         // --------------------------------------------------------------------
201
202         /**
203          * Commit Transaction
204          *
205          * @access      public
206          * @return      bool            
207          */     
208         function trans_commit()
209         {
210                 if ( ! $this->trans_enabled)
211                 {
212                         return TRUE;
213                 }
214
215                 // When transactions are nested we only begin/commit/rollback the outermost ones
216                 if ($this->_trans_depth > 0)
217                 {
218                         return TRUE;
219                 }
220
221                 $this->simple_query('COMMIT');
222                 $this->simple_query('SET AUTOCOMMIT=1');
223                 return TRUE;
224         }
225
226         // --------------------------------------------------------------------
227
228         /**
229          * Rollback Transaction
230          *
231          * @access      public
232          * @return      bool            
233          */     
234         function trans_rollback()
235         {
236                 if ( ! $this->trans_enabled)
237                 {
238                         return TRUE;
239                 }
240
241                 // When transactions are nested we only begin/commit/rollback the outermost ones
242                 if ($this->_trans_depth > 0)
243                 {
244                         return TRUE;
245                 }
246
247                 $this->simple_query('ROLLBACK');
248                 $this->simple_query('SET AUTOCOMMIT=1');
249                 return TRUE;
250         }
251         
252         // --------------------------------------------------------------------
253
254         /**
255          * Escape String
256          *
257          * @access      public
258          * @param       string
259          * @return      string
260          */
261         function escape_str($str)       
262         {       
263                 if (is_array($str))
264                 {
265                         foreach($str as $key => $val)
266                         {
267                                 $str[$key] = $this->escape_str($val);
268                         }
269                 
270                         return $str;
271                 }
272
273                 if (function_exists('mysql_real_escape_string') AND is_resource($this->conn_id))
274                 {
275                         return mysql_real_escape_string($str, $this->conn_id);
276                 }
277                 elseif (function_exists('mysql_escape_string'))
278                 {
279                         return mysql_escape_string($str);
280                 }
281                 else
282                 {
283                         return addslashes($str);
284                 }
285         }
286                 
287         // --------------------------------------------------------------------
288
289         /**
290          * Affected Rows
291          *
292          * @access      public
293          * @return      integer
294          */
295         function affected_rows()
296         {
297                 return @mysql_affected_rows($this->conn_id);
298         }
299         
300         // --------------------------------------------------------------------
301
302         /**
303          * Insert ID
304          *
305          * @access      public
306          * @return      integer
307          */
308         function insert_id()
309         {
310                 return @mysql_insert_id($this->conn_id);
311         }
312
313         // --------------------------------------------------------------------
314
315         /**
316          * "Count All" query
317          *
318          * Generates a platform-specific query string that counts all records in
319          * the specified database
320          *
321          * @access      public
322          * @param       string
323          * @return      string
324          */
325         function count_all($table = '')
326         {
327                 if ($table == '')
328                         return '0';
329         
330                 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows'). " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
331                 
332                 if ($query->num_rows() == 0)
333                         return '0';
334
335                 $row = $query->row();
336                 return (int)$row->numrows;
337         }
338
339         // --------------------------------------------------------------------
340
341         /**
342          * List table query
343          *
344          * Generates a platform-specific query string so that the table names can be fetched
345          *
346          * @access      private
347          * @param       boolean
348          * @return      string
349          */
350         function _list_tables($prefix_limit = FALSE)
351         {
352                 $sql = "SHOW TABLES FROM ".$this->_escape_char.$this->database.$this->_escape_char;     
353
354                 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
355                 {
356                         $sql .= " LIKE '".$this->dbprefix."%'";
357                 }
358
359                 return $sql;
360         }
361         
362         // --------------------------------------------------------------------
363
364         /**
365          * Show column query
366          *
367          * Generates a platform-specific query string so that the column names can be fetched
368          *
369          * @access      public
370          * @param       string  the table name
371          * @return      string
372          */
373         function _list_columns($table = '')
374         {
375                 return "SHOW COLUMNS FROM ".$table;
376         }
377
378         // --------------------------------------------------------------------
379
380         /**
381          * Field data query
382          *
383          * Generates a platform-specific query so that the column data can be retrieved
384          *
385          * @access      public
386          * @param       string  the table name
387          * @return      object
388          */
389         function _field_data($table)
390         {
391                 return "SELECT * FROM ".$table." LIMIT 1";
392         }
393
394         // --------------------------------------------------------------------
395
396         /**
397          * The error message string
398          *
399          * @access      private
400          * @return      string
401          */
402         function _error_message()
403         {
404                 return mysql_error($this->conn_id);
405         }
406         
407         // --------------------------------------------------------------------
408
409         /**
410          * The error message number
411          *
412          * @access      private
413          * @return      integer
414          */
415         function _error_number()
416         {
417                 return mysql_errno($this->conn_id);
418         }
419
420         // --------------------------------------------------------------------
421
422         /**
423          * Escape the SQL Identifiers
424          *
425          * This function escapes column and table names
426          *
427          * @access      private
428          * @param       string
429          * @return      string
430          */
431         function _escape_identifiers($item)
432         {
433                 if ($this->_escape_char == '')
434                 {
435                         return $item;
436                 }
437         
438                 if (strpos($item, '.') !== FALSE)
439                 {
440                         $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;                    
441                 }
442                 else
443                 {
444                         $str = $this->_escape_char.$item.$this->_escape_char;
445                 }
446                 
447                 // remove duplicates if the user already included the escape
448                 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
449         }
450                         
451         // --------------------------------------------------------------------
452
453         /**
454          * From Tables
455          *
456          * This function implicitly groups FROM tables so there is no confusion
457          * about operator precedence in harmony with SQL standards
458          *
459          * @access      public
460          * @param       type
461          * @return      type
462          */
463         function _from_tables($tables)
464         {
465                 if ( ! is_array($tables))
466                 {
467                         $tables = array($tables);
468                 }
469                 
470                 return '('.implode(', ', $tables).')';
471         }
472
473         // --------------------------------------------------------------------
474         
475         /**
476          * Insert statement
477          *
478          * Generates a platform-specific insert string from the supplied data
479          *
480          * @access      public
481          * @param       string  the table name
482          * @param       array   the insert keys
483          * @param       array   the insert values
484          * @return      string
485          */
486         function _insert($table, $keys, $values)
487         {       
488                 return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
489         }
490         
491         // --------------------------------------------------------------------
492
493         /**
494          * Update statement
495          *
496          * Generates a platform-specific update string from the supplied data
497          *
498          * @access      public
499          * @param       string  the table name
500          * @param       array   the update data
501          * @param       array   the where clause
502          * @param       array   the orderby clause
503          * @param       array   the limit clause
504          * @return      string
505          */
506         function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
507         {
508                 foreach($values as $key => $val)
509                 {
510                         $valstr[] = $key." = ".$val;
511                 }
512                 
513                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
514                 
515                 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
516         
517                 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
518
519                 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
520
521                 $sql .= $orderby.$limit;
522                 
523                 return $sql;
524         }
525
526         // --------------------------------------------------------------------
527
528         /**
529          * Truncate statement
530          *
531          * Generates a platform-specific truncate string from the supplied data
532          * If the database does not support the truncate() command
533          * This function maps to "DELETE FROM table"
534          *
535          * @access      public
536          * @param       string  the table name
537          * @return      string
538          */     
539         function _truncate($table)
540         {
541                 return "TRUNCATE ".$table;
542         }
543         
544         // --------------------------------------------------------------------
545
546         /**
547          * Delete statement
548          *
549          * Generates a platform-specific delete string from the supplied data
550          *
551          * @access      public
552          * @param       string  the table name
553          * @param       array   the where clause
554          * @param       string  the limit clause
555          * @return      string
556          */     
557         function _delete($table, $where = array(), $like = array(), $limit = FALSE)
558         {
559                 $conditions = '';
560
561                 if (count($where) > 0 OR count($like) > 0)
562                 {
563                         $conditions = "\nWHERE ";
564                         $conditions .= implode("\n", $this->ar_where);
565
566                         if (count($where) > 0 && count($like) > 0)
567                         {
568                                 $conditions .= " AND ";
569                         }
570                         $conditions .= implode("\n", $like);
571                 }
572
573                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
574         
575                 return "DELETE FROM ".$table.$conditions.$limit;
576         }
577
578         // --------------------------------------------------------------------
579
580         /**
581          * Limit string
582          *
583          * Generates a platform-specific LIMIT clause
584          *
585          * @access      public
586          * @param       string  the sql query string
587          * @param       integer the number of rows to limit the query to
588          * @param       integer the offset value
589          * @return      string
590          */
591         function _limit($sql, $limit, $offset)
592         {       
593                 if ($offset == 0)
594                 {
595                         $offset = '';
596                 }
597                 else
598                 {
599                         $offset .= ", ";
600                 }
601                 
602                 return $sql."LIMIT ".$offset.$limit;
603         }
604
605         // --------------------------------------------------------------------
606
607         /**
608          * Close DB Connection
609          *
610          * @access      public
611          * @param       resource
612          * @return      void
613          */
614         function _close($conn_id)
615         {
616                 @mysql_close($conn_id);
617         }
618         
619 }
620
621
622 /* End of file mysql_driver.php */
623 /* Location: ./system/database/drivers/mysql/mysql_driver.php */