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