blob: a5237c832d341e07f66b42fb59f2a5021266cbb1 [file] [log] [blame]
adminb0dd10f2006-08-25 17:25:49 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * Code Igniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author Rick Ellis
9 * @copyright Copyright (c) 2006, pMachine, Inc.
10 * @license http://www.codeignitor.com/user_guide/license.html
11 * @link http://www.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 Rick Ellis
29 * @link http://www.codeigniter.com/user_guide/libraries/database/
30 */
31class CI_DB_mysqli extends CI_DB {
32
33 /**
34 * Whether to use the MySQL "delete hack" which allows the number
35 * of affected rows to be shown. Uses a preg_replace when enabled,
36 * adding a bit more processing to all queries.
37 */
38 var $delete_hack = TRUE;
39
40 // --------------------------------------------------------------------
41
42 /**
43 * Non-persistent database connection
44 *
45 * @access private called by the base class
46 * @return resource
47 */
48 function db_connect()
49 {
50 return mysqli_connect($this->hostname, $this->username, $this->password);
51 }
52
53 // --------------------------------------------------------------------
54
55 /**
56 * Persistent database connection
57 *
58 * @access private called by the base class
59 * @return resource
60 */
61 function db_pconnect()
62 {
63 return $this->db_connect();
64 }
65
66 // --------------------------------------------------------------------
67
68 /**
69 * Select the database
70 *
71 * @access private called by the base class
72 * @return resource
73 */
74 function db_select()
75 {
76 return @mysqli_select_db($this->conn_id, $this->database);
77 }
78
79 // --------------------------------------------------------------------
80
81 /**
82 * Execute the query
83 *
84 * @access private called by the base class
85 * @param string an SQL query
86 * @return resource
87 */
admine885d782006-09-23 20:25:05 +000088 function _execute($sql)
adminb0dd10f2006-08-25 17:25:49 +000089 {
90 $sql = $this->_prep_query($sql);
admin1082bdd2006-08-27 19:32:02 +000091 $result = @mysqli_query($this->conn_id, $sql);
admin1082bdd2006-08-27 19:32:02 +000092 return $result;
adminb0dd10f2006-08-25 17:25:49 +000093 }
94
95 // --------------------------------------------------------------------
96
97 /**
98 * Prep the query
99 *
100 * If needed, each database adapter can prep the query string
101 *
102 * @access private called by execute()
103 * @param string an SQL query
104 * @return string
105 */
adminb071bb52006-08-26 19:28:37 +0000106 function _prep_query($sql)
adminb0dd10f2006-08-25 17:25:49 +0000107 {
108 // "DELETE FROM TABLE" returns 0 affected rows This hack modifies
109 // the query so that it returns the number of affected rows
110 if ($this->delete_hack === TRUE)
111 {
112 if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
113 {
114 $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
115 }
116 }
117
118 return $sql;
119 }
admine885d782006-09-23 20:25:05 +0000120
121
122 // --------------------------------------------------------------------
123
124 /**
125 * Begin Transaction
126 *
127 * @access public
128 * @return bool
129 */
130 function trans_begin()
131 {
132 if ( ! $this->trans_enabled)
133 {
134 return TRUE;
135 }
136
137 // When transactions are nested we only begin/commit/rollback the outermost ones
138 if ($this->_trans_depth > 0)
139 {
140 return TRUE;
141 }
142
143 $this->simple_query('SET AUTOCOMMIT=0');
144 $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
145 return TRUE;
146 }
147
148 // --------------------------------------------------------------------
149
150 /**
151 * Commit Transaction
152 *
153 * @access public
154 * @return bool
155 */
156 function trans_commit()
157 {
158 if ( ! $this->trans_enabled)
159 {
160 return TRUE;
161 }
162
163 // When transactions are nested we only begin/commit/rollback the outermost ones
164 if ($this->_trans_depth > 0)
165 {
166 return TRUE;
167 }
168
169 $this->simple_query('COMMIT');
170 $this->simple_query('SET AUTOCOMMIT=1');
171 return TRUE;
172 }
173
174 // --------------------------------------------------------------------
175
176 /**
177 * Rollback Transaction
178 *
179 * @access public
180 * @return bool
181 */
182 function trans_rollback()
183 {
184 if ( ! $this->trans_enabled)
185 {
186 return TRUE;
187 }
188
189 // When transactions are nested we only begin/commit/rollback the outermost ones
190 if ($this->_trans_depth > 0)
191 {
192 return TRUE;
193 }
194
195 $this->simple_query('ROLLBACK');
196 $this->simple_query('SET AUTOCOMMIT=1');
197 return TRUE;
198 }
199
adminb0dd10f2006-08-25 17:25:49 +0000200 // --------------------------------------------------------------------
201
202 /**
203 * Escape String
204 *
205 * @access public
206 * @param string
207 * @return string
208 */
209 function escape_str($str)
210 {
adminb0dd10f2006-08-25 17:25:49 +0000211 return mysqli_real_escape_string($this->conn_id, $str);
212 }
213
214 // --------------------------------------------------------------------
215
216 /**
217 * Close DB Connection
218 *
219 * @access public
220 * @param resource
221 * @return void
222 */
223 function destroy($conn_id)
224 {
225 mysqli_close($conn_id);
226 }
227
228 // --------------------------------------------------------------------
229
230 /**
231 * Affected Rows
232 *
233 * @access public
234 * @return integer
235 */
236 function affected_rows()
237 {
238 return @mysqli_affected_rows($this->conn_id);
239 }
240
241 // --------------------------------------------------------------------
242
243 /**
244 * Insert ID
245 *
246 * @access public
247 * @return integer
248 */
249 function insert_id()
250 {
251 return @mysqli_insert_id($this->conn_id);
252 }
253
254 // --------------------------------------------------------------------
255
256 /**
257 * "Count All" query
258 *
259 * Generates a platform-specific query string that counts all records in
260 * the specified database
261 *
262 * @access public
263 * @param string
264 * @return string
265 */
266 function count_all($table = '')
267 {
268 if ($table == '')
269 return '0';
270
271 $query = $this->query("SELECT COUNT(*) AS numrows FROM `".$this->dbprefix.$table."`");
272
273 if ($query->num_rows() == 0)
274 return '0';
275
276 $row = $query->row();
277 return $row->numrows;
278 }
279
280 // --------------------------------------------------------------------
281
282 /**
283 * The error message string
284 *
285 * @access public
286 * @return string
287 */
288 function error_message()
289 {
290 return mysqli_error($this->conn_id);
291 }
292
293 // --------------------------------------------------------------------
294
295 /**
296 * The error message number
297 *
298 * @access public
299 * @return integer
300 */
301 function error_number()
302 {
303 return mysqli_errno($this->conn_id);
304 }
305
306 // --------------------------------------------------------------------
307
308 /**
309 * Escape Table Name
310 *
311 * This function adds backticks if the table name has a period
312 * in it. Some DBs will get cranky unless periods are escaped
313 *
314 * @access public
315 * @param string the table name
316 * @return string
317 */
318 function escape_table($table)
319 {
320 if (stristr($table, '.'))
321 {
322 $table = preg_replace("/\./", "`.`", $table);
323 }
324
325 return $table;
326 }
327
328 // --------------------------------------------------------------------
329
330 /**
331 * Field data query
332 *
333 * Generates a platform-specific query so that the column data can be retrieved
334 *
335 * @access public
336 * @param string the table name
337 * @return object
338 */
339 function _field_data($table)
340 {
341 $sql = "SELECT * FROM ".$this->escape_table($table)." LIMIT 1";
342 $query = $this->query($sql);
343 return $query->field_data();
344 }
345
346 // --------------------------------------------------------------------
347
348 /**
349 * Insert statement
350 *
351 * Generates a platform-specific insert string from the supplied data
352 *
353 * @access public
354 * @param string the table name
355 * @param array the insert keys
356 * @param array the insert values
357 * @return string
358 */
359 function _insert($table, $keys, $values)
360 {
361 return "INSERT INTO ".$this->escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
362 }
363
364 // --------------------------------------------------------------------
365
366 /**
367 * Update statement
368 *
369 * Generates a platform-specific update string from the supplied data
370 *
371 * @access public
372 * @param string the table name
373 * @param array the update data
374 * @param array the where clause
375 * @return string
376 */
377 function _update($table, $values, $where)
378 {
379 foreach($values as $key => $val)
380 {
381 $valstr[] = $key." = ".$val;
382 }
383
384 return "UPDATE ".$this->escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where);
385 }
386
387 // --------------------------------------------------------------------
388
389 /**
390 * Delete statement
391 *
392 * Generates a platform-specific delete string from the supplied data
393 *
394 * @access public
395 * @param string the table name
396 * @param array the where clause
397 * @return string
398 */
399 function _delete($table, $where)
400 {
401 return "DELETE FROM ".$this->escape_table($table)." WHERE ".implode(" ", $where);
402 }
403
404 // --------------------------------------------------------------------
405
406 /**
407 * Version number query string
408 *
409 * @access public
410 * @return string
411 */
412 function _version()
413 {
414 return "SELECT version() AS ver";
415 }
416
417 // --------------------------------------------------------------------
418
419 /**
420 * Show table query
421 *
422 * Generates a platform-specific query string so that the table names can be fetched
423 *
424 * @access public
425 * @return string
426 */
427 function _show_tables()
428 {
429 return "SHOW TABLES FROM `".$this->database."`";
430 }
431
432 // --------------------------------------------------------------------
433
434 /**
435 * Show columnn query
436 *
437 * Generates a platform-specific query string so that the column names can be fetched
438 *
439 * @access public
440 * @param string the table name
441 * @return string
442 */
443 function _show_columns($table = '')
444 {
445 return "SHOW COLUMNS FROM ".$this->escape_table($table);
446 }
447
448 // --------------------------------------------------------------------
449
450 /**
451 * Limit string
452 *
453 * Generates a platform-specific LIMIT clause
454 *
455 * @access public
456 * @param string the sql query string
457 * @param integer the number of rows to limit the query to
458 * @param integer the offset value
459 * @return string
460 */
461 function _limit($sql, $limit, $offset)
462 {
463 $sql .= "LIMIT ".$limit;
464
465 if ($offset > 0)
466 {
467 $sql .= " OFFSET ".$offset;
468 }
469
470 return $sql;
471 }
472
473}
474
475
476
477/**
478 * MySQLi Result Class
479 *
480 * This class extends the parent result class: CI_DB_result
481 *
482 * @category Database
483 * @author Rick Ellis
484 * @link http://www.codeigniter.com/user_guide/libraries/database/
485 */
486class CI_DB_mysqli_result extends CI_DB_result {
487
488 /**
489 * Number of rows in the result set
490 *
491 * @access public
492 * @return integer
493 */
494 function num_rows()
495 {
496 return @mysqli_num_rows($this->result_id);
497 }
498
499 // --------------------------------------------------------------------
500
501 /**
502 * Number of fields in the result set
503 *
504 * @access public
505 * @return integer
506 */
507 function num_fields()
508 {
509 return @mysqli_num_fields($this->result_id);
510 }
511
512 // --------------------------------------------------------------------
513
514 /**
515 * Field data
516 *
517 * Generates an array of objects containing field meta-data
518 *
519 * @access public
520 * @return array
521 */
522 function field_data()
523 {
524 $retval = array();
525 while ($field = mysqli_fetch_field($this->result_id))
526 {
admine348efb2006-09-20 21:13:26 +0000527 $F = new stdClass();
adminb0dd10f2006-08-25 17:25:49 +0000528 $F->name = $field->name;
529 $F->type = $field->type;
530 $F->default = $field->def;
531 $F->max_length = $field->max_length;
adminb68745e2006-09-17 18:13:34 +0000532 $F->primary_key = ($field->flags & MYSQLI_PRI_KEY_FLAG) ? 1 : 0;
adminb0dd10f2006-08-25 17:25:49 +0000533
534 $retval[] = $F;
535 }
536
537 return $retval;
538 }
539
540 // --------------------------------------------------------------------
541
542 /**
543 * Result - associative array
544 *
545 * Returns the result set as an array
546 *
547 * @access private
548 * @return array
549 */
550 function _fetch_assoc()
551 {
552 return mysqli_fetch_assoc($this->result_id);
553 }
554
555 // --------------------------------------------------------------------
556
557 /**
558 * Result - object
559 *
560 * Returns the result set as an object
561 *
562 * @access private
563 * @return object
564 */
565 function _fetch_object()
566 {
567 return mysqli_fetch_object($this->result_id);
568 }
569
570}
571
572?>