blob: 49ac8ab245633d2d12ebe8027f582ed2dad84bae [file] [log] [blame]
admin7b613c72006-09-24 18:05:17 +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.
admine334c472006-10-21 19:44:22 +000010 * @license http://www.codeignitor.com/user_guide/license.html
admin7b613c72006-09-24 18:05:17 +000011 * @link http://www.codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
admine334c472006-10-21 19:44:22 +000015
admin7b613c72006-09-24 18:05:17 +000016// ------------------------------------------------------------------------
17
18/**
19 * Database Driver Class
admine334c472006-10-21 19:44:22 +000020 *
admin7b613c72006-09-24 18:05:17 +000021 * This is the platform-independent base DB implementation class.
22 * This class will not be called directly. Rather, the adapter
23 * class for the specific database will extend and instantiate it.
24 *
25 * @package CodeIgniter
26 * @subpackage Drivers
27 * @category Database
28 * @author Rick Ellis
29 * @link http://www.codeigniter.com/user_guide/database/
30 */
31class CI_DB_driver {
32
33 var $username;
34 var $password;
35 var $hostname;
36 var $database;
37 var $dbdriver = 'mysql';
38 var $dbprefix = '';
39 var $port = '';
40 var $pconnect = FALSE;
41 var $conn_id = FALSE;
42 var $result_id = FALSE;
43 var $db_debug = FALSE;
44 var $benchmark = 0;
45 var $query_count = 0;
46 var $bind_marker = '?';
47 var $queries = array();
admine8f6eb62006-10-02 06:46:16 +000048 var $data_cache = array();
admin7b613c72006-09-24 18:05:17 +000049 var $trans_enabled = TRUE;
50 var $_trans_depth = 0;
51 var $_trans_failure = FALSE; // Used with transactions to determine if a rollback should occur
admin6871d952006-10-04 00:36:18 +000052 var $cache_on = FALSE;
53 var $cachedir = '';
adminc5f7fa32006-10-06 02:10:23 +000054 var $cache_autodel = FALSE;
adminc2e3cd72006-10-05 04:22:30 +000055 var $CACHE; // The cache class object
admin7b613c72006-09-24 18:05:17 +000056
admin6871d952006-10-04 00:36:18 +000057
58 // These are use with Oracle
59 var $stmt_id;
60 var $curs_id;
61 var $limit_used;
admin7b613c72006-09-24 18:05:17 +000062
admine8f6eb62006-10-02 06:46:16 +000063
admin7b613c72006-09-24 18:05:17 +000064
65 /**
66 * Constructor. Accepts one parameter containing the database
admine334c472006-10-21 19:44:22 +000067 * connection settings.
admin7b613c72006-09-24 18:05:17 +000068 *
admine334c472006-10-21 19:44:22 +000069 * Database settings can be passed as discreet
70 * parameters or as a data source name in the first
admin7b613c72006-09-24 18:05:17 +000071 * parameter. DSNs must have this prototype:
72 * $dsn = 'driver://username:password@hostname/database';
73 *
74 * @param mixed. Can be an array or a DSN string
75 */
76 function CI_DB_driver($params)
77 {
78 $this->initialize($params);
79 log_message('debug', 'Database Driver Class Initialized');
80 }
81
82 // --------------------------------------------------------------------
83
84 /**
85 * Initialize Database Settings
86 *
87 * @access private Called by the constructor
88 * @param mixed
89 * @return void
90 */
91 function initialize($params = '')
admin6871d952006-10-04 00:36:18 +000092 {
admin7b613c72006-09-24 18:05:17 +000093 if (is_array($params))
94 {
admin6871d952006-10-04 00:36:18 +000095 $defaults = array(
admine334c472006-10-21 19:44:22 +000096 'hostname' => '',
97 'username' => '',
98 'password' => '',
99 'database' => '',
admin25701d72006-10-24 22:34:33 +0000100 'conn_id' => FALSE,
admine334c472006-10-21 19:44:22 +0000101 'dbdriver' => 'mysql',
102 'dbprefix' => '',
103 'port' => '',
104 'pconnect' => FALSE,
105 'db_debug' => FALSE,
106 'cachedir' => '',
admin6871d952006-10-04 00:36:18 +0000107 'cache_on' => FALSE
108 );
109
110 foreach ($defaults as $key => $val)
admin7b613c72006-09-24 18:05:17 +0000111 {
112 $this->$key = ( ! isset($params[$key])) ? $val : $params[$key];
113 }
114 }
115 elseif (strpos($params, '://'))
116 {
117 if (FALSE === ($dsn = @parse_url($params)))
118 {
119 log_message('error', 'Invalid DB Connection String');
120
121 if ($this->db_debug)
122 {
123 return $this->display_error('db_invalid_connection_str');
124 }
125 return FALSE;
126 }
127
128 $this->hostname = ( ! isset($dsn['host'])) ? '' : rawurldecode($dsn['host']);
129 $this->username = ( ! isset($dsn['user'])) ? '' : rawurldecode($dsn['user']);
130 $this->password = ( ! isset($dsn['pass'])) ? '' : rawurldecode($dsn['pass']);
131 $this->database = ( ! isset($dsn['path'])) ? '' : rawurldecode(substr($dsn['path'], 1));
132 }
admin6871d952006-10-04 00:36:18 +0000133
admin25701d72006-10-24 22:34:33 +0000134 // If an existing DB connection resource is supplied
135 // there is no need to connect and select the database
136 if (is_resource($this->conn_id))
137 {
138 return TRUE;
139 }
140
admin6871d952006-10-04 00:36:18 +0000141 // Connect to the database
142 $this->conn_id = ($this->pconnect == FALSE) ? $this->db_connect() : $this->db_pconnect();
admin25701d72006-10-24 22:34:33 +0000143
144 // No connection? Throw an error
admin6871d952006-10-04 00:36:18 +0000145 if ( ! $this->conn_id)
admine334c472006-10-21 19:44:22 +0000146 {
admin7b613c72006-09-24 18:05:17 +0000147 log_message('error', 'Unable to connect to the database');
148
admin6871d952006-10-04 00:36:18 +0000149 if ($this->db_debug)
150 {
admin7b613c72006-09-24 18:05:17 +0000151 $this->display_error('db_unable_to_connect');
admin6871d952006-10-04 00:36:18 +0000152 }
admin25701d72006-10-24 22:34:33 +0000153 return FALSE;
admin6871d952006-10-04 00:36:18 +0000154 }
admin25701d72006-10-24 22:34:33 +0000155
156 // Select the database
admin59612e92006-10-28 18:50:23 +0000157 if ($this->database != '')
admin7b613c72006-09-24 18:05:17 +0000158 {
admin59612e92006-10-28 18:50:23 +0000159 if ( ! $this->db_select())
admin7b613c72006-09-24 18:05:17 +0000160 {
admin59612e92006-10-28 18:50:23 +0000161 log_message('error', 'Unable to select database: '.$this->database);
162
163 if ($this->db_debug)
164 {
165 $this->display_error('db_unable_to_select', $this->database);
166 }
167 return FALSE;
admin25701d72006-10-24 22:34:33 +0000168 }
admin59612e92006-10-28 18:50:23 +0000169 }
admin25701d72006-10-24 22:34:33 +0000170
171 return TRUE;
admin7b613c72006-09-24 18:05:17 +0000172 }
admin88a8ad12006-10-07 03:16:32 +0000173
admin7b613c72006-09-24 18:05:17 +0000174 // --------------------------------------------------------------------
175
176 /**
admin9cd4e8e2006-09-25 23:26:25 +0000177 * The name of the platform in use (mysql, mssql, etc...)
178 *
179 * @access public
admine334c472006-10-21 19:44:22 +0000180 * @return string
admin9cd4e8e2006-09-25 23:26:25 +0000181 */
182 function platform()
183 {
184 return $this->dbdriver;
185 }
186
187 // --------------------------------------------------------------------
188
189 /**
admine334c472006-10-21 19:44:22 +0000190 * Database Version Number. Returns a string containing the
admin9cd4e8e2006-09-25 23:26:25 +0000191 * version of the database being used
192 *
193 * @access public
194 * @return string
195 */
196 function version()
197 {
198 if (FALSE === ($sql = $this->_version()))
199 {
admin6871d952006-10-04 00:36:18 +0000200 if ($this->db_debug)
201 {
admin9cd4e8e2006-09-25 23:26:25 +0000202 return $this->display_error('db_unsupported_function');
admin6871d952006-10-04 00:36:18 +0000203 }
204 return FALSE;
admin9cd4e8e2006-09-25 23:26:25 +0000205 }
206
admin6871d952006-10-04 00:36:18 +0000207 if ($this->dbdriver == 'oci8')
208 {
admin9cd4e8e2006-09-25 23:26:25 +0000209 return $sql;
210 }
211
212 $query = $this->query($sql);
213 $row = $query->row();
214 return $row->ver;
215 }
216
217 // --------------------------------------------------------------------
218
219 /**
admin7b613c72006-09-24 18:05:17 +0000220 * Execute the query
221 *
admine334c472006-10-21 19:44:22 +0000222 * Accepts an SQL string as input and returns a result object upon
223 * successful execution of a "read" type query. Returns boolean TRUE
224 * upon successful execution of a "write" type query. Returns boolean
225 * FALSE upon failure, and if the $db_debug variable is set to TRUE
admin7b613c72006-09-24 18:05:17 +0000226 * will raise an error.
admine334c472006-10-21 19:44:22 +0000227 *
admin7b613c72006-09-24 18:05:17 +0000228 * @access public
229 * @param string An SQL query string
230 * @param array An array of binding data
admine334c472006-10-21 19:44:22 +0000231 * @return mixed
admin7b613c72006-09-24 18:05:17 +0000232 */
admin6871d952006-10-04 00:36:18 +0000233 function query($sql, $binds = FALSE, $return_object = TRUE)
admindb8a3742006-10-04 07:43:35 +0000234 {
admin7b613c72006-09-24 18:05:17 +0000235 if ($sql == '')
236 {
admin6871d952006-10-04 00:36:18 +0000237 if ($this->db_debug)
238 {
admin7b613c72006-09-24 18:05:17 +0000239 log_message('error', 'Invalid query: '.$sql);
240 return $this->display_error('db_invalid_query');
admin6871d952006-10-04 00:36:18 +0000241 }
242 return FALSE;
admin7b613c72006-09-24 18:05:17 +0000243 }
244
admine334c472006-10-21 19:44:22 +0000245 // Is query caching enabled? If the query is a "read type"
246 // we will load the caching class and return the previously
admin0c405652006-10-04 18:37:57 +0000247 // cached query if it exists
admin6871d952006-10-04 00:36:18 +0000248 if ($this->cache_on == TRUE AND stristr($sql, 'SELECT'))
admin0c405652006-10-04 18:37:57 +0000249 {
250 if ($this->_cache_init())
admine8f6eb62006-10-02 06:46:16 +0000251 {
admin36e64422006-10-22 01:30:50 +0000252 $this->load_rdriver();
adminc2e3cd72006-10-05 04:22:30 +0000253 if (FALSE !== ($cache = $this->CACHE->read($sql)))
admin0c405652006-10-04 18:37:57 +0000254 {
255 return $cache;
256 }
admine8f6eb62006-10-02 06:46:16 +0000257 }
258 }
259
admin7b613c72006-09-24 18:05:17 +0000260 // Compile binds if needed
261 if ($binds !== FALSE)
262 {
263 $sql = $this->compile_binds($sql, $binds);
264 }
265
admin6871d952006-10-04 00:36:18 +0000266 // Save the query for debugging
267 $this->queries[] = $sql;
admin7b613c72006-09-24 18:05:17 +0000268
269 // Start the Query Timer
admin6871d952006-10-04 00:36:18 +0000270 $time_start = list($sm, $ss) = explode(' ', microtime());
admine334c472006-10-21 19:44:22 +0000271
admin7b613c72006-09-24 18:05:17 +0000272 // Run the Query
admin6871d952006-10-04 00:36:18 +0000273 if (FALSE === ($this->result_id = $this->simple_query($sql)))
admine334c472006-10-21 19:44:22 +0000274 {
admin6871d952006-10-04 00:36:18 +0000275 // This will trigger a rollback if transactions are being used
276 $this->_trans_failure = TRUE;
277
278 if ($this->db_debug)
279 {
adminbb1d4392006-09-24 20:14:38 +0000280 log_message('error', 'Query error: '.$this->_error_message());
admin7b613c72006-09-24 18:05:17 +0000281 return $this->display_error(
282 array(
admine334c472006-10-21 19:44:22 +0000283 'Error Number: '.$this->_error_number(),
adminbb1d4392006-09-24 20:14:38 +0000284 $this->_error_message(),
admin7b613c72006-09-24 18:05:17 +0000285 $sql
286 )
287 );
admin6871d952006-10-04 00:36:18 +0000288 }
admine334c472006-10-21 19:44:22 +0000289
admin6871d952006-10-04 00:36:18 +0000290 return FALSE;
291 }
292
admin7b613c72006-09-24 18:05:17 +0000293 // Stop and aggregate the query time results
294 $time_end = list($em, $es) = explode(' ', microtime());
295 $this->benchmark += ($em + $es) - ($sm + $ss);
296
297 // Increment the query counter
admin6871d952006-10-04 00:36:18 +0000298 $this->query_count++;
299
admin7b613c72006-09-24 18:05:17 +0000300 // Was the query a "write" type?
301 // If so we'll simply return true
302 if ($this->is_write_type($sql) === TRUE)
admindb8a3742006-10-04 07:43:35 +0000303 {
304 // If caching is enabled we'll auto-cleanup any
305 // existing files related to this particular URI
admina658e312006-10-06 01:29:36 +0000306 if ($this->cache_on == TRUE AND $this->cache_autodel == TRUE AND $this->_cache_init())
admindb8a3742006-10-04 07:43:35 +0000307 {
adminc2e3cd72006-10-05 04:22:30 +0000308 $this->CACHE->delete();
admindb8a3742006-10-04 07:43:35 +0000309 }
310
admin7b613c72006-09-24 18:05:17 +0000311 return TRUE;
312 }
313
admine334c472006-10-21 19:44:22 +0000314 // Return TRUE if we don't need to create a result object
admin7b613c72006-09-24 18:05:17 +0000315 // Currently only the Oracle driver uses this when stored
316 // procedures are used
317 if ($return_object !== TRUE)
318 {
319 return TRUE;
320 }
admindb8a3742006-10-04 07:43:35 +0000321
322 // Load and instantiate the result driver
admindb8a3742006-10-04 07:43:35 +0000323
adminc2e3cd72006-10-05 04:22:30 +0000324 $driver = $this->load_rdriver();
325 $RES = new $driver();
admin6871d952006-10-04 00:36:18 +0000326 $RES->conn_id = $this->conn_id;
admin6871d952006-10-04 00:36:18 +0000327 $RES->result_id = $this->result_id;
328
329 if ($this->dbdriver == 'oci8')
330 {
adminc2e3cd72006-10-05 04:22:30 +0000331 $RES->stmt_id = $this->stmt_id;
332 $RES->curs_id = NULL;
333 $RES->limit_used = $this->limit_used;
admin6871d952006-10-04 00:36:18 +0000334 }
admindb8a3742006-10-04 07:43:35 +0000335
admine334c472006-10-21 19:44:22 +0000336 // Is query caching enabled? If so, we'll serialize the
adminc2e3cd72006-10-05 04:22:30 +0000337 // result object and save it to a cache file.
admin0c405652006-10-04 18:37:57 +0000338 if ($this->cache_on == TRUE AND $this->_cache_init())
adminc2e3cd72006-10-05 04:22:30 +0000339 {
340 // We'll create a new instance of the result object
341 // only without the platform specific driver since
342 // we can't use it with cached data (the query result
343 // resource ID won't be any good once we've cached the
344 // result object, so we'll have to compile the data
345 // and save it)
346 $CR = new CI_DB_result();
347 $CR->num_rows = $RES->num_rows();
348 $CR->result_object = $RES->result_object();
349 $CR->result_array = $RES->result_array();
admina658e312006-10-06 01:29:36 +0000350
351 // Reset these since cached objects can not utilize resource IDs.
352 $CR->conn_id = NULL;
353 $CR->result_id = NULL;
adminc2e3cd72006-10-05 04:22:30 +0000354
355 $this->CACHE->write($sql, $CR);
admindb8a3742006-10-04 07:43:35 +0000356 }
357
admin7b613c72006-09-24 18:05:17 +0000358 return $RES;
359 }
admindb8a3742006-10-04 07:43:35 +0000360
361 // --------------------------------------------------------------------
362
363 /**
364 * Load the result drivers
admine334c472006-10-21 19:44:22 +0000365 *
admindb8a3742006-10-04 07:43:35 +0000366 * @access public
admine334c472006-10-21 19:44:22 +0000367 * @return string the name of the result class
admindb8a3742006-10-04 07:43:35 +0000368 */
369 function load_rdriver()
370 {
371 $driver = 'CI_DB_'.$this->dbdriver.'_result';
372
373 if ( ! class_exists($driver))
374 {
375 include_once(BASEPATH.'database/DB_result'.EXT);
376 include_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result'.EXT);
377 }
378
379 return $driver;
380 }
admin7b613c72006-09-24 18:05:17 +0000381
382 // --------------------------------------------------------------------
383
384 /**
admine334c472006-10-21 19:44:22 +0000385 * Simple Query
adminfafe28b2006-10-21 19:08:17 +0000386 * This is a simplified version of the query() function. Internally
admin7b613c72006-09-24 18:05:17 +0000387 * we only use it when running transaction commands since they do
388 * not require all the features of the main query() function.
admine334c472006-10-21 19:44:22 +0000389 *
admin7b613c72006-09-24 18:05:17 +0000390 * @access public
391 * @param string the sql query
admine334c472006-10-21 19:44:22 +0000392 * @return mixed
admin7b613c72006-09-24 18:05:17 +0000393 */
394 function simple_query($sql)
395 {
396 if ( ! $this->conn_id)
397 {
398 $this->initialize();
399 }
400
admin40037182006-10-11 19:16:58 +0000401 return $this->_execute($sql);
admin7b613c72006-09-24 18:05:17 +0000402 }
403
404 // --------------------------------------------------------------------
405
406 /**
407 * Disable Transactions
408 * This permits transactions to be disabled at run-time.
admine334c472006-10-21 19:44:22 +0000409 *
admin7b613c72006-09-24 18:05:17 +0000410 * @access public
admine334c472006-10-21 19:44:22 +0000411 * @return void
admin7b613c72006-09-24 18:05:17 +0000412 */
413 function trans_off()
414 {
415 $this->trans_enabled = FALSE;
416 }
417
418 // --------------------------------------------------------------------
419
420 /**
421 * Start Transaction
admine334c472006-10-21 19:44:22 +0000422 *
admin7b613c72006-09-24 18:05:17 +0000423 * @access public
admine334c472006-10-21 19:44:22 +0000424 * @return void
admin7b613c72006-09-24 18:05:17 +0000425 */
426 function trans_start($test_mode = FALSE)
427 {
428 if ( ! $this->trans_enabled)
429 {
430 return FALSE;
431 }
432
433 // When transactions are nested we only begin/commit/rollback the outermost ones
434 if ($this->_trans_depth > 0)
435 {
436 $this->_trans_depth += 1;
437 return;
438 }
439
440 $this->trans_begin($test_mode);
441 }
442
443 // --------------------------------------------------------------------
444
445 /**
446 * Complete Transaction
admine334c472006-10-21 19:44:22 +0000447 *
admin7b613c72006-09-24 18:05:17 +0000448 * @access public
admine334c472006-10-21 19:44:22 +0000449 * @return bool
admin7b613c72006-09-24 18:05:17 +0000450 */
451 function trans_complete()
452 {
453 if ( ! $this->trans_enabled)
454 {
455 return FALSE;
456 }
457
458 // When transactions are nested we only begin/commit/rollback the outermost ones
459 if ($this->_trans_depth > 1)
460 {
461 $this->_trans_depth -= 1;
462 return TRUE;
463 }
464
465 // The query() function will set this flag to TRUE in the event that a query failed
466 if ($this->_trans_failure === TRUE)
467 {
468 $this->trans_rollback();
469
470 if ($this->db_debug)
471 {
472 return $this->display_error('db_transaction_failure');
473 }
474 return FALSE;
475 }
476
477 $this->trans_commit();
478 return TRUE;
479 }
480
481 // --------------------------------------------------------------------
482
483 /**
484 * Lets you retrieve the transaction flag to determine if it has failed
admine334c472006-10-21 19:44:22 +0000485 *
admin7b613c72006-09-24 18:05:17 +0000486 * @access public
admine334c472006-10-21 19:44:22 +0000487 * @return bool
admin7b613c72006-09-24 18:05:17 +0000488 */
489 function trans_status()
490 {
491 return $this->_trans_failure;
492 }
493
494 // --------------------------------------------------------------------
495
496 /**
497 * Compile Bindings
admine334c472006-10-21 19:44:22 +0000498 *
admin7b613c72006-09-24 18:05:17 +0000499 * @access public
500 * @param string the sql statement
501 * @param array an array of bind data
admine334c472006-10-21 19:44:22 +0000502 * @return string
admin7b613c72006-09-24 18:05:17 +0000503 */
504 function compile_binds($sql, $binds)
505 {
506 if (FALSE === strpos($sql, $this->bind_marker))
507 {
508 return $sql;
509 }
510
511 if ( ! is_array($binds))
512 {
513 $binds = array($binds);
514 }
515
516 foreach ($binds as $val)
517 {
518 $val = $this->escape($val);
519
520 // Just in case the replacement string contains the bind
521 // character we'll temporarily replace it with a marker
522 $val = str_replace($this->bind_marker, '{%bind_marker%}', $val);
523 $sql = preg_replace("#".preg_quote($this->bind_marker, '#')."#", str_replace('$', '\$', $val), $sql, 1);
524 }
525
526 return str_replace('{%bind_marker%}', $this->bind_marker, $sql);
527 }
528
529 // --------------------------------------------------------------------
530
531 /**
admine334c472006-10-21 19:44:22 +0000532 * Determines if a query is a "write" type.
533 *
admin7b613c72006-09-24 18:05:17 +0000534 * @access public
535 * @param string An SQL query string
admine334c472006-10-21 19:44:22 +0000536 * @return boolean
admin7b613c72006-09-24 18:05:17 +0000537 */
538 function is_write_type($sql)
539 {
admine334c472006-10-21 19:44:22 +0000540 if ( ! preg_match('/^\s*"?(INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|LOAD DATA|COPY|ALTER|GRANT|REVOKE|LOCK|UNLOCK)\s+/i', $sql))
admin7b613c72006-09-24 18:05:17 +0000541 {
542 return FALSE;
543 }
544 return TRUE;
545 }
546
547 // --------------------------------------------------------------------
548
549 /**
admine334c472006-10-21 19:44:22 +0000550 * Calculate the aggregate query elapsed time
551 *
admin7b613c72006-09-24 18:05:17 +0000552 * @access public
adminfafe28b2006-10-21 19:08:17 +0000553 * @param integer The number of decimal places
admine334c472006-10-21 19:44:22 +0000554 * @return integer
admin7b613c72006-09-24 18:05:17 +0000555 */
556 function elapsed_time($decimals = 6)
557 {
558 return number_format($this->benchmark, $decimals);
559 }
560
561 // --------------------------------------------------------------------
562
563 /**
564 * Returns the total number of queries
admine334c472006-10-21 19:44:22 +0000565 *
admin7b613c72006-09-24 18:05:17 +0000566 * @access public
admine334c472006-10-21 19:44:22 +0000567 * @return integer
admin7b613c72006-09-24 18:05:17 +0000568 */
569 function total_queries()
570 {
571 return $this->query_count;
572 }
573
574 // --------------------------------------------------------------------
575
576 /**
577 * Returns the last query that was executed
admine334c472006-10-21 19:44:22 +0000578 *
admin7b613c72006-09-24 18:05:17 +0000579 * @access public
admine334c472006-10-21 19:44:22 +0000580 * @return void
admin7b613c72006-09-24 18:05:17 +0000581 */
582 function last_query()
583 {
584 return end($this->queries);
585 }
586
587 // --------------------------------------------------------------------
588
589 /**
590 * "Smart" Escape String
591 *
592 * Escapes data based on type
593 * Sets boolean and null types
admine334c472006-10-21 19:44:22 +0000594 *
admin7b613c72006-09-24 18:05:17 +0000595 * @access public
596 * @param string
admine334c472006-10-21 19:44:22 +0000597 * @return integer
admin7b613c72006-09-24 18:05:17 +0000598 */
599 function escape($str)
600 {
601 switch (gettype($str))
602 {
603 case 'string' : $str = "'".$this->escape_str($str)."'";
604 break;
605 case 'boolean' : $str = ($str === FALSE) ? 0 : 1;
606 break;
607 default : $str = ($str === NULL) ? 'NULL' : $str;
608 break;
609 }
610
611 return $str;
adminbb1d4392006-09-24 20:14:38 +0000612 }
613
admin9cd4e8e2006-09-25 23:26:25 +0000614 // --------------------------------------------------------------------
615
616 /**
617 * Primary
618 *
619 * Retrieves the primary key. It assumes that the row in the first
620 * position is the primary key
admine334c472006-10-21 19:44:22 +0000621 *
admin9cd4e8e2006-09-25 23:26:25 +0000622 * @access public
623 * @param string the table name
admine334c472006-10-21 19:44:22 +0000624 * @return string
admin9cd4e8e2006-09-25 23:26:25 +0000625 */
626 function primary($table = '')
627 {
admin606f99c2006-10-11 23:48:41 +0000628 $fields = $this->list_fields($table);
admin9cd4e8e2006-09-25 23:26:25 +0000629
630 if ( ! is_array($fields))
631 {
632 return FALSE;
633 }
634
635 return current($fields);
636 }
637
638 // --------------------------------------------------------------------
639
admin3dd978f2006-09-30 19:24:45 +0000640 /**
641 * Returns an array of table names
admine334c472006-10-21 19:44:22 +0000642 *
admin3dd978f2006-09-30 19:24:45 +0000643 * @access public
admine334c472006-10-21 19:44:22 +0000644 * @return array
admin3dd978f2006-09-30 19:24:45 +0000645 */
646 function list_tables()
647 {
648 // Is there a cached result?
admine8f6eb62006-10-02 06:46:16 +0000649 if (isset($this->data_cache['table_names']))
admin3dd978f2006-09-30 19:24:45 +0000650 {
admine8f6eb62006-10-02 06:46:16 +0000651 return $this->data_cache['table_names'];
admin3dd978f2006-09-30 19:24:45 +0000652 }
653
654 if (FALSE === ($sql = $this->_list_tables()))
655 {
admin6871d952006-10-04 00:36:18 +0000656 if ($this->db_debug)
657 {
admin3dd978f2006-09-30 19:24:45 +0000658 return $this->display_error('db_unsupported_function');
admin6871d952006-10-04 00:36:18 +0000659 }
660 return FALSE;
admin3dd978f2006-09-30 19:24:45 +0000661 }
662
663 $retval = array();
664 $query = $this->query($sql);
665
666 if ($query->num_rows() > 0)
667 {
668 foreach($query->result_array() as $row)
669 {
670 if (isset($row['TABLE_NAME']))
671 {
672 $retval[] = $row['TABLE_NAME'];
673 }
674 else
675 {
676 $retval[] = array_shift($row);
677 }
678 }
679 }
680
admin7099a582006-10-10 17:47:59 +0000681 $this->data_cache['table_names'] = $retval;
682 return $this->data_cache['table_names'];
admin3dd978f2006-09-30 19:24:45 +0000683 }
684
685 // --------------------------------------------------------------------
686
687 /**
688 * Determine if a particular table exists
689 * @access public
690 * @return boolean
691 */
692 function table_exists($table_name)
693 {
694 return ( ! in_array($this->dbprefix.$table_name, $this->list_tables())) ? FALSE : TRUE;
695 }
696
697 // --------------------------------------------------------------------
698
admin9cd4e8e2006-09-25 23:26:25 +0000699 /**
700 * Fetch MySQL Field Names
701 *
702 * @access public
703 * @param string the table name
admine334c472006-10-21 19:44:22 +0000704 * @return array
admin9cd4e8e2006-09-25 23:26:25 +0000705 */
admin6871d952006-10-04 00:36:18 +0000706 function list_fields($table = '')
707 {
admin3ed8c512006-09-29 23:26:28 +0000708 // Is there a cached result?
admine8f6eb62006-10-02 06:46:16 +0000709 if (isset($this->data_cache['field_names'][$table]))
admin3ed8c512006-09-29 23:26:28 +0000710 {
admine8f6eb62006-10-02 06:46:16 +0000711 return $this->data_cache['field_names'][$table];
admin3ed8c512006-09-29 23:26:28 +0000712 }
admin6871d952006-10-04 00:36:18 +0000713
714 if ($table == '')
715 {
admin9cd4e8e2006-09-25 23:26:25 +0000716 if ($this->db_debug)
717 {
718 return $this->display_error('db_field_param_missing');
719 }
720 return FALSE;
admin6871d952006-10-04 00:36:18 +0000721 }
722
admin9cd4e8e2006-09-25 23:26:25 +0000723 if (FALSE === ($sql = $this->_list_columns($this->dbprefix.$table)))
724 {
admin6871d952006-10-04 00:36:18 +0000725 if ($this->db_debug)
726 {
admin9cd4e8e2006-09-25 23:26:25 +0000727 return $this->display_error('db_unsupported_function');
admin6871d952006-10-04 00:36:18 +0000728 }
729 return FALSE;
admin9cd4e8e2006-09-25 23:26:25 +0000730 }
admin6871d952006-10-04 00:36:18 +0000731
732 $query = $this->query($sql);
733
734 $retval = array();
admin9cd4e8e2006-09-25 23:26:25 +0000735 foreach($query->result_array() as $row)
736 {
737 if (isset($row['COLUMN_NAME']))
738 {
739 $retval[] = $row['COLUMN_NAME'];
740 }
741 else
742 {
743 $retval[] = current($row);
admin6871d952006-10-04 00:36:18 +0000744 }
admin9cd4e8e2006-09-25 23:26:25 +0000745 }
admin6871d952006-10-04 00:36:18 +0000746
admin7099a582006-10-10 17:47:59 +0000747 $this->data_cache['field_names'][$table] = $retval;
748 return $this->data_cache['field_names'][$table];
admin6871d952006-10-04 00:36:18 +0000749 }
adminb2a9cec2006-10-01 03:38:04 +0000750
751 // --------------------------------------------------------------------
752
753 /**
754 * Determine if a particular field exists
755 * @access public
756 * @param string
757 * @param string
758 * @return boolean
759 */
760 function field_exists($field_name, $table_name)
761 {
762 return ( ! in_array($field_name, $this->list_fields($table_name))) ? FALSE : TRUE;
763 }
admin6871d952006-10-04 00:36:18 +0000764
admin3dd978f2006-09-30 19:24:45 +0000765 // --------------------------------------------------------------------
766
767 /**
768 * DEPRECATED - use list_fields()
769 */
admine334c472006-10-21 19:44:22 +0000770 function field_names($table = '')
admin6871d952006-10-04 00:36:18 +0000771 {
772 return $this->list_fields($table);
773 }
admin9cd4e8e2006-09-25 23:26:25 +0000774
775 // --------------------------------------------------------------------
776
777 /**
778 * Returns an object with field data
admine334c472006-10-21 19:44:22 +0000779 *
admin9cd4e8e2006-09-25 23:26:25 +0000780 * @access public
781 * @param string the table name
admine334c472006-10-21 19:44:22 +0000782 * @return object
admin9cd4e8e2006-09-25 23:26:25 +0000783 */
784 function field_data($table = '')
785 {
admin6871d952006-10-04 00:36:18 +0000786 if ($table == '')
787 {
admin9cd4e8e2006-09-25 23:26:25 +0000788 if ($this->db_debug)
789 {
790 return $this->display_error('db_field_param_missing');
791 }
792 return FALSE;
admin6871d952006-10-04 00:36:18 +0000793 }
794
admin9cd4e8e2006-09-25 23:26:25 +0000795 $query = $this->query($this->_field_data($this->dbprefix.$table));
796 return $query->field_data();
797 }
798
adminbb1d4392006-09-24 20:14:38 +0000799 // --------------------------------------------------------------------
800
801 /**
802 * Generate an insert string
admine334c472006-10-21 19:44:22 +0000803 *
adminbb1d4392006-09-24 20:14:38 +0000804 * @access public
805 * @param string the table upon which the query will be performed
806 * @param array an associative array data of key/values
admine334c472006-10-21 19:44:22 +0000807 * @return string
adminbb1d4392006-09-24 20:14:38 +0000808 */
809 function insert_string($table, $data)
810 {
admine334c472006-10-21 19:44:22 +0000811 $fields = array();
adminbb1d4392006-09-24 20:14:38 +0000812 $values = array();
813
admine334c472006-10-21 19:44:22 +0000814 foreach($data as $key => $val)
adminbb1d4392006-09-24 20:14:38 +0000815 {
816 $fields[] = $key;
817 $values[] = $this->escape($val);
818 }
819
820 return $this->_insert($this->dbprefix.$table, $fields, $values);
821 }
822
823 // --------------------------------------------------------------------
824
825 /**
826 * Generate an update string
admine334c472006-10-21 19:44:22 +0000827 *
adminbb1d4392006-09-24 20:14:38 +0000828 * @access public
829 * @param string the table upon which the query will be performed
830 * @param array an associative array data of key/values
831 * @param mixed the "where" statement
admine334c472006-10-21 19:44:22 +0000832 * @return string
adminbb1d4392006-09-24 20:14:38 +0000833 */
834 function update_string($table, $data, $where)
835 {
836 if ($where == '')
837 return false;
838
839 $fields = array();
admine334c472006-10-21 19:44:22 +0000840 foreach($data as $key => $val)
adminbb1d4392006-09-24 20:14:38 +0000841 {
842 $fields[$key] = $this->escape($val);
843 }
844
845 if ( ! is_array($where))
846 {
847 $dest = array($where);
848 }
849 else
850 {
851 $dest = array();
852 foreach ($where as $key => $val)
853 {
854 $prefix = (count($dest) == 0) ? '' : ' AND ';
855
856 if ($val != '')
857 {
858 if ( ! $this->_has_operator($key))
859 {
860 $key .= ' =';
861 }
862
863 $val = ' '.$this->escape($val);
864 }
865
866 $dest[] = $prefix.$key.$val;
867 }
868 }
869
870 return $this->_update($this->dbprefix.$table, $fields, $dest);
admin6871d952006-10-04 00:36:18 +0000871 }
admin7b613c72006-09-24 18:05:17 +0000872
873 // --------------------------------------------------------------------
874
875 /**
876 * Enables a native PHP function to be run, using a platform agnostic wrapper.
admine334c472006-10-21 19:44:22 +0000877 *
admin7b613c72006-09-24 18:05:17 +0000878 * @access public
879 * @param string the function name
880 * @param mixed any parameters needed by the function
admine334c472006-10-21 19:44:22 +0000881 * @return mixed
admin7b613c72006-09-24 18:05:17 +0000882 */
883 function call_function($function)
884 {
885 $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_';
886
887 if (FALSE === strpos($driver, $function))
888 {
889 $function = $driver.$function;
890 }
891
892 if ( ! function_exists($function))
admine334c472006-10-21 19:44:22 +0000893 {
admin7b613c72006-09-24 18:05:17 +0000894 if ($this->db_debug)
895 {
896 return $this->display_error('db_unsupported_function');
897 }
898 return FALSE;
899 }
900 else
901 {
adminee54c112006-09-28 17:13:38 +0000902 $args = (func_num_args() > 1) ? array_splice(func_get_args(), 1) : null;
903
admine334c472006-10-21 19:44:22 +0000904 return call_user_func_array($function, $args);
admin7b613c72006-09-24 18:05:17 +0000905 }
906 }
adminc5f7fa32006-10-06 02:10:23 +0000907
908 // --------------------------------------------------------------------
909
910 /**
911 * Set Cache Directory Path
912 *
913 * @access public
914 * @param string the path to the cache directory
915 * @return void
916 */
917 function cache_set_path($path = '')
918 {
919 $this->cachedir = $path;
920 }
921
admine8f6eb62006-10-02 06:46:16 +0000922 // --------------------------------------------------------------------
923
924 /**
925 * Enable Query Caching
926 *
927 * @access public
928 * @return void
929 */
930 function cache_on()
931 {
admin7099a582006-10-10 17:47:59 +0000932 $this->cache_on = TRUE;
933 return TRUE;
admine8f6eb62006-10-02 06:46:16 +0000934 }
935
936 // --------------------------------------------------------------------
937
938 /**
939 * Disable Query Caching
940 *
941 * @access public
942 * @return void
943 */
944 function cache_off()
945 {
admin7099a582006-10-10 17:47:59 +0000946 $this->cache_on = FALSE;
947 return FALSE;
admine8f6eb62006-10-02 06:46:16 +0000948 }
adminfa708172006-10-04 18:42:42 +0000949
adminc5f7fa32006-10-06 02:10:23 +0000950
adminfa708172006-10-04 18:42:42 +0000951 // --------------------------------------------------------------------
952
953 /**
adminc5f7fa32006-10-06 02:10:23 +0000954 * Delete the cache files associated with a particular URI
adminfa708172006-10-04 18:42:42 +0000955 *
956 * @access public
adminfa708172006-10-04 18:42:42 +0000957 * @return void
958 */
admin1b0ab462006-10-10 23:30:21 +0000959 function cache_delete($segment_one = '', $segment_two = '')
adminfa708172006-10-04 18:42:42 +0000960 {
adminc5f7fa32006-10-06 02:10:23 +0000961 if ( ! $this->_cache_init())
962 {
963 return FALSE;
964 }
admin1b0ab462006-10-10 23:30:21 +0000965 return $this->CACHE->delete($segment_one, $segment_two);
adminc5f7fa32006-10-06 02:10:23 +0000966 }
967
968 // --------------------------------------------------------------------
969
970 /**
971 * Delete All cache files
972 *
973 * @access public
974 * @return void
975 */
976 function cache_delete_all()
977 {
978 if ( ! $this->_cache_init())
979 {
980 return FALSE;
981 }
982
983 return $this->CACHE->delete_all();
adminfa708172006-10-04 18:42:42 +0000984 }
admin0c405652006-10-04 18:37:57 +0000985
admin6871d952006-10-04 00:36:18 +0000986 // --------------------------------------------------------------------
987
988 /**
admin0c405652006-10-04 18:37:57 +0000989 * Initialize the Cache Class
admin6871d952006-10-04 00:36:18 +0000990 *
admin0c405652006-10-04 18:37:57 +0000991 * @access private
992 * @return void
993 */
994 function _cache_init()
admin6871d952006-10-04 00:36:18 +0000995 {
adminc2e3cd72006-10-05 04:22:30 +0000996 if (is_object($this->CACHE) AND class_exists('CI_DB_Cache'))
admindb8a3742006-10-04 07:43:35 +0000997 {
admin0c405652006-10-04 18:37:57 +0000998 return TRUE;
admindb8a3742006-10-04 07:43:35 +0000999 }
1000
adminfa708172006-10-04 18:42:42 +00001001 if ( ! @include_once(BASEPATH.'database/DB_cache'.EXT))
admin6871d952006-10-04 00:36:18 +00001002 {
adminfa708172006-10-04 18:42:42 +00001003 return $this->cache_off();
admin6871d952006-10-04 00:36:18 +00001004 }
1005
adminc2e3cd72006-10-05 04:22:30 +00001006 $this->CACHE = new CI_DB_Cache;
admin6871d952006-10-04 00:36:18 +00001007 return TRUE;
1008 }
1009
admindb8a3742006-10-04 07:43:35 +00001010
1011 // --------------------------------------------------------------------
1012
1013 /**
admin7b613c72006-09-24 18:05:17 +00001014 * Close DB Connection
admine334c472006-10-21 19:44:22 +00001015 *
admin7b613c72006-09-24 18:05:17 +00001016 * @access public
admine334c472006-10-21 19:44:22 +00001017 * @return void
admin7b613c72006-09-24 18:05:17 +00001018 */
admin6871d952006-10-04 00:36:18 +00001019 function close()
1020 {
1021 if (is_resource($this->conn_id))
1022 {
1023 $this->_close($this->conn_id);
admine334c472006-10-21 19:44:22 +00001024 }
admin7b613c72006-09-24 18:05:17 +00001025 $this->conn_id = FALSE;
admin6871d952006-10-04 00:36:18 +00001026 }
admin7b613c72006-09-24 18:05:17 +00001027
1028 // --------------------------------------------------------------------
1029
1030 /**
1031 * Display an error message
admine334c472006-10-21 19:44:22 +00001032 *
admin7b613c72006-09-24 18:05:17 +00001033 * @access public
1034 * @param string the error message
1035 * @param string any "swap" values
1036 * @param boolean whether to localize the message
admine334c472006-10-21 19:44:22 +00001037 * @return string sends the application/error_db.php template
admin7b613c72006-09-24 18:05:17 +00001038 */
admine334c472006-10-21 19:44:22 +00001039 function display_error($error = '', $swap = '', $native = FALSE)
admin6871d952006-10-04 00:36:18 +00001040 {
admin7b613c72006-09-24 18:05:17 +00001041 $LANG = new CI_Language();
1042 $LANG->load('db');
1043
1044 $heading = 'MySQL Error';
1045
1046 if ($native == TRUE)
1047 {
1048 $message = $error;
1049 }
1050 else
1051 {
1052 $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error;
1053 }
1054
1055 if ( ! class_exists('CI_Exceptions'))
1056 {
1057 include_once(BASEPATH.'libraries/Exceptions'.EXT);
1058 }
1059
1060 $error = new CI_Exceptions();
1061 echo $error->show_error('An Error Was Encountered', $message, 'error_db');
1062 exit;
1063
admine334c472006-10-21 19:44:22 +00001064 }
admin7b613c72006-09-24 18:05:17 +00001065
1066}
1067
1068?>