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