Setting tag www-register-wizard-4.3-5
[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 - 2009, 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         // clause and character used for LIKE escape sequences - not used in MySQL
39         var $_like_escape_str = '';
40         var $_like_escape_chr = '';
41
42         /**
43          * Whether to use the MySQL "delete hack" which allows the number
44          * of affected rows to be shown. Uses a preg_replace when enabled,
45          * adding a bit more processing to all queries.
46          */     
47         var $delete_hack = TRUE;
48         
49         /**
50          * The syntax to count rows is slightly different across different
51          * database engines, so this string appears in each driver and is
52          * used for the count_all() and count_all_results() functions.
53          */
54         var $_count_string = 'SELECT COUNT(*) AS ';
55         var $_random_keyword = ' RAND()'; // database specific random keyword
56
57         /**
58          * Non-persistent database connection
59          *
60          * @access      private called by the base class
61          * @return      resource
62          */     
63         function db_connect()
64         {
65                 if ($this->port != '')
66                 {
67                         $this->hostname .= ':'.$this->port;
68                 }
69                 
70                 return @mysql_connect($this->hostname, $this->username, $this->password, TRUE);
71         }
72         
73         // --------------------------------------------------------------------
74
75         /**
76          * Persistent database connection
77          *
78          * @access      private called by the base class
79          * @return      resource
80          */     
81         function db_pconnect()
82         {
83                 if ($this->port != '')
84                 {
85                         $this->hostname .= ':'.$this->port;
86                 }
87
88                 return @mysql_pconnect($this->hostname, $this->username, $this->password);
89         }
90         
91         // --------------------------------------------------------------------
92
93         /**
94          * Reconnect
95          *
96          * Keep / reestablish the db connection if no queries have been
97          * sent for a length of time exceeding the server's idle timeout
98          *
99          * @access      public
100          * @return      void
101          */
102         function reconnect()
103         {
104                 if (mysql_ping($this->conn_id) === FALSE)
105                 {
106                         $this->conn_id = FALSE;
107                 }
108         }
109
110         // --------------------------------------------------------------------
111         
112         /**
113          * Select the database
114          *
115          * @access      private called by the base class
116          * @return      resource
117          */     
118         function db_select()
119         {
120                 return @mysql_select_db($this->database, $this->conn_id);
121         }
122
123         // --------------------------------------------------------------------
124
125         /**
126          * Set client character set
127          *
128          * @access      public
129          * @param       string
130          * @param       string
131          * @return      resource
132          */
133         function db_set_charset($charset, $collation)
134         {
135                 return @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id);
136         }
137
138         // --------------------------------------------------------------------
139         
140         /**
141          * Version number query string
142          *
143          * @access      public
144          * @return      string
145          */
146         function _version()
147         {
148                 return "SELECT version() AS ver";
149         }
150
151         // --------------------------------------------------------------------
152
153         /**
154          * Execute the query
155          *
156          * @access      private called by the base class
157          * @param       string  an SQL query
158          * @return      resource
159          */     
160         function _execute($sql)
161         {
162                 $sql = $this->_prep_query($sql);
163                 return @mysql_query($sql, $this->conn_id);
164         }
165         
166         // --------------------------------------------------------------------
167
168         /**
169          * Prep the query
170          *
171          * If needed, each database adapter can prep the query string
172          *
173          * @access      private called by execute()
174          * @param       string  an SQL query
175          * @return      string
176          */     
177         function _prep_query($sql)
178         {
179                 // "DELETE FROM TABLE" returns 0 affected rows This hack modifies
180                 // the query so that it returns the number of affected rows
181                 if ($this->delete_hack === TRUE)
182                 {
183                         if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
184                         {
185                                 $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
186                         }
187                 }
188                 
189                 return $sql;
190         }
191
192         // --------------------------------------------------------------------
193
194         /**
195          * Begin Transaction
196          *
197          * @access      public
198          * @return      bool            
199          */     
200         function trans_begin($test_mode = FALSE)
201         {
202                 if ( ! $this->trans_enabled)
203                 {
204                         return TRUE;
205                 }
206                 
207                 // When transactions are nested we only begin/commit/rollback the outermost ones
208                 if ($this->_trans_depth > 0)
209                 {
210                         return TRUE;
211                 }
212
213                 // Reset the transaction failure flag.
214                 // If the $test_mode flag is set to TRUE transactions will be rolled back
215                 // even if the queries produce a successful result.
216                 $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
217                 
218                 $this->simple_query('SET AUTOCOMMIT=0');
219                 $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
220                 return TRUE;
221         }
222
223         // --------------------------------------------------------------------
224
225         /**
226          * Commit Transaction
227          *
228          * @access      public
229          * @return      bool            
230          */     
231         function trans_commit()
232         {
233                 if ( ! $this->trans_enabled)
234                 {
235                         return TRUE;
236                 }
237
238                 // When transactions are nested we only begin/commit/rollback the outermost ones
239                 if ($this->_trans_depth > 0)
240                 {
241                         return TRUE;
242                 }
243
244                 $this->simple_query('COMMIT');
245                 $this->simple_query('SET AUTOCOMMIT=1');
246                 return TRUE;
247         }
248
249         // --------------------------------------------------------------------
250
251         /**
252          * Rollback Transaction
253          *
254          * @access      public
255          * @return      bool            
256          */     
257         function trans_rollback()
258         {
259                 if ( ! $this->trans_enabled)
260                 {
261                         return TRUE;
262                 }
263
264                 // When transactions are nested we only begin/commit/rollback the outermost ones
265                 if ($this->_trans_depth > 0)
266                 {
267                         return TRUE;
268                 }
269
270                 $this->simple_query('ROLLBACK');
271                 $this->simple_query('SET AUTOCOMMIT=1');
272                 return TRUE;
273         }
274         
275         // --------------------------------------------------------------------
276
277         /**
278          * Escape String
279          *
280          * @access      public
281          * @param       string
282          * @param       bool    whether or not the string will be used in a LIKE condition
283          * @return      string
284          */
285         function escape_str($str, $like = FALSE)        
286         {       
287                 if (is_array($str))
288                 {
289                         foreach($str as $key => $val)
290                         {
291                                 $str[$key] = $this->escape_str($val, $like);
292                         }
293                 
294                         return $str;
295                 }
296
297                 if (function_exists('mysql_real_escape_string') AND is_resource($this->conn_id))
298                 {
299                         $str = mysql_real_escape_string($str, $this->conn_id);
300                 }
301                 elseif (function_exists('mysql_escape_string'))
302                 {
303                         $str = mysql_escape_string($str);
304                 }
305                 else
306                 {
307                         $str = addslashes($str);
308                 }
309                 
310                 // escape LIKE condition wildcards
311                 if ($like === TRUE)
312                 {
313                         $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
314                 }
315                 
316                 return $str;
317         }
318                 
319         // --------------------------------------------------------------------
320
321         /**
322          * Affected Rows
323          *
324          * @access      public
325          * @return      integer
326          */
327         function affected_rows()
328         {
329                 return @mysql_affected_rows($this->conn_id);
330         }
331         
332         // --------------------------------------------------------------------
333
334         /**
335          * Insert ID
336          *
337          * @access      public
338          * @return      integer
339          */
340         function insert_id()
341         {
342                 return @mysql_insert_id($this->conn_id);
343         }
344
345         // --------------------------------------------------------------------
346
347         /**
348          * "Count All" query
349          *
350          * Generates a platform-specific query string that counts all records in
351          * the specified database
352          *
353          * @access      public
354          * @param       string
355          * @return      string
356          */
357         function count_all($table = '')
358         {
359                 if ($table == '')
360                 {
361                         return 0;
362                 }
363         
364                 $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
365
366                 if ($query->num_rows() == 0)
367                 {
368                         return 0;
369                 }
370
371                 $row = $query->row();
372                 return (int) $row->numrows;
373         }
374
375         // --------------------------------------------------------------------
376
377         /**
378          * List table query
379          *
380          * Generates a platform-specific query string so that the table names can be fetched
381          *
382          * @access      private
383          * @param       boolean
384          * @return      string
385          */
386         function _list_tables($prefix_limit = FALSE)
387         {
388                 $sql = "SHOW TABLES FROM ".$this->_escape_char.$this->database.$this->_escape_char;     
389
390                 if ($prefix_limit !== FALSE AND $this->dbprefix != '')
391                 {
392                         $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'";
393                 }
394
395                 return $sql;
396         }
397         
398         // --------------------------------------------------------------------
399
400         /**
401          * Show column query
402          *
403          * Generates a platform-specific query string so that the column names can be fetched
404          *
405          * @access      public
406          * @param       string  the table name
407          * @return      string
408          */
409         function _list_columns($table = '')
410         {
411                 return "SHOW COLUMNS FROM ".$table;
412         }
413
414         // --------------------------------------------------------------------
415
416         /**
417          * Field data query
418          *
419          * Generates a platform-specific query so that the column data can be retrieved
420          *
421          * @access      public
422          * @param       string  the table name
423          * @return      object
424          */
425         function _field_data($table)
426         {
427                 return "SELECT * FROM ".$table." LIMIT 1";
428         }
429
430         // --------------------------------------------------------------------
431
432         /**
433          * The error message string
434          *
435          * @access      private
436          * @return      string
437          */
438         function _error_message()
439         {
440                 return mysql_error($this->conn_id);
441         }
442         
443         // --------------------------------------------------------------------
444
445         /**
446          * The error message number
447          *
448          * @access      private
449          * @return      integer
450          */
451         function _error_number()
452         {
453                 return mysql_errno($this->conn_id);
454         }
455
456         // --------------------------------------------------------------------
457
458         /**
459          * Escape the SQL Identifiers
460          *
461          * This function escapes column and table names
462          *
463          * @access      private
464          * @param       string
465          * @return      string
466          */
467         function _escape_identifiers($item)
468         {
469                 if ($this->_escape_char == '')
470                 {
471                         return $item;
472                 }
473
474                 foreach ($this->_reserved_identifiers as $id)
475                 {
476                         if (strpos($item, '.'.$id) !== FALSE)
477                         {
478                                 $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);  
479                                 
480                                 // remove duplicates if the user already included the escape
481                                 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
482                         }               
483                 }
484                 
485                 if (strpos($item, '.') !== FALSE)
486                 {
487                         $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;                    
488                 }
489                 else
490                 {
491                         $str = $this->_escape_char.$item.$this->_escape_char;
492                 }
493         
494                 // remove duplicates if the user already included the escape
495                 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
496         }
497                         
498         // --------------------------------------------------------------------
499
500         /**
501          * From Tables
502          *
503          * This function implicitly groups FROM tables so there is no confusion
504          * about operator precedence in harmony with SQL standards
505          *
506          * @access      public
507          * @param       type
508          * @return      type
509          */
510         function _from_tables($tables)
511         {
512                 if ( ! is_array($tables))
513                 {
514                         $tables = array($tables);
515                 }
516                 
517                 return '('.implode(', ', $tables).')';
518         }
519
520         // --------------------------------------------------------------------
521         
522         /**
523          * Insert statement
524          *
525          * Generates a platform-specific insert string from the supplied data
526          *
527          * @access      public
528          * @param       string  the table name
529          * @param       array   the insert keys
530          * @param       array   the insert values
531          * @return      string
532          */
533         function _insert($table, $keys, $values)
534         {       
535                 return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
536         }
537         
538         // --------------------------------------------------------------------
539
540         /**
541          * Update statement
542          *
543          * Generates a platform-specific update string from the supplied data
544          *
545          * @access      public
546          * @param       string  the table name
547          * @param       array   the update data
548          * @param       array   the where clause
549          * @param       array   the orderby clause
550          * @param       array   the limit clause
551          * @return      string
552          */
553         function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
554         {
555                 foreach($values as $key => $val)
556                 {
557                         $valstr[] = $key." = ".$val;
558                 }
559                 
560                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
561                 
562                 $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
563         
564                 $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
565
566                 $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
567
568                 $sql .= $orderby.$limit;
569                 
570                 return $sql;
571         }
572
573         // --------------------------------------------------------------------
574
575         /**
576          * Truncate statement
577          *
578          * Generates a platform-specific truncate string from the supplied data
579          * If the database does not support the truncate() command
580          * This function maps to "DELETE FROM table"
581          *
582          * @access      public
583          * @param       string  the table name
584          * @return      string
585          */     
586         function _truncate($table)
587         {
588                 return "TRUNCATE ".$table;
589         }
590         
591         // --------------------------------------------------------------------
592
593         /**
594          * Delete statement
595          *
596          * Generates a platform-specific delete string from the supplied data
597          *
598          * @access      public
599          * @param       string  the table name
600          * @param       array   the where clause
601          * @param       string  the limit clause
602          * @return      string
603          */     
604         function _delete($table, $where = array(), $like = array(), $limit = FALSE)
605         {
606                 $conditions = '';
607
608                 if (count($where) > 0 OR count($like) > 0)
609                 {
610                         $conditions = "\nWHERE ";
611                         $conditions .= implode("\n", $this->ar_where);
612
613                         if (count($where) > 0 && count($like) > 0)
614                         {
615                                 $conditions .= " AND ";
616                         }
617                         $conditions .= implode("\n", $like);
618                 }
619
620                 $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
621         
622                 return "DELETE FROM ".$table.$conditions.$limit;
623         }
624
625         // --------------------------------------------------------------------
626
627         /**
628          * Limit string
629          *
630          * Generates a platform-specific LIMIT clause
631          *
632          * @access      public
633          * @param       string  the sql query string
634          * @param       integer the number of rows to limit the query to
635          * @param       integer the offset value
636          * @return      string
637          */
638         function _limit($sql, $limit, $offset)
639         {       
640                 if ($offset == 0)
641                 {
642                         $offset = '';
643                 }
644                 else
645                 {
646                         $offset .= ", ";
647                 }
648                 
649                 return $sql."LIMIT ".$offset.$limit;
650         }
651
652         // --------------------------------------------------------------------
653
654         /**
655          * Close DB Connection
656          *
657          * @access      public
658          * @param       resource
659          * @return      void
660          */
661         function _close($conn_id)
662         {
663                 @mysql_close($conn_id);
664         }
665         
666 }
667
668
669 /* End of file mysql_driver.php */
670 /* Location: ./system/database/drivers/mysql/mysql_driver.php */