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