blob: a24bd20d8514fa4acd740859d8cf58adfaf4726d [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.
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 * Database Driver Class
20 *
21 * 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
67 * connection settings.
68 *
69 * Database settings can be passed as discreet
70 * parameters or as a data source name in the first
71 * 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(
96 'hostname' => '',
97 'username' => '',
98 'password' => '',
99 'database' => '',
100 'dbdriver' => 'mysql',
101 'dbprefix' => '',
102 'port' => '',
103 'pconnect' => FALSE,
104 'db_debug' => FALSE,
105 'cachedir' => '',
106 'cache_on' => FALSE
107 );
108
109 foreach ($defaults as $key => $val)
admin7b613c72006-09-24 18:05:17 +0000110 {
111 $this->$key = ( ! isset($params[$key])) ? $val : $params[$key];
112 }
113 }
114 elseif (strpos($params, '://'))
115 {
116 if (FALSE === ($dsn = @parse_url($params)))
117 {
118 log_message('error', 'Invalid DB Connection String');
119
120 if ($this->db_debug)
121 {
122 return $this->display_error('db_invalid_connection_str');
123 }
124 return FALSE;
125 }
126
127 $this->hostname = ( ! isset($dsn['host'])) ? '' : rawurldecode($dsn['host']);
128 $this->username = ( ! isset($dsn['user'])) ? '' : rawurldecode($dsn['user']);
129 $this->password = ( ! isset($dsn['pass'])) ? '' : rawurldecode($dsn['pass']);
130 $this->database = ( ! isset($dsn['path'])) ? '' : rawurldecode(substr($dsn['path'], 1));
131 }
admin6871d952006-10-04 00:36:18 +0000132
133 // Connect to the database
134 $this->conn_id = ($this->pconnect == FALSE) ? $this->db_connect() : $this->db_pconnect();
135
136 if ( ! $this->conn_id)
137 {
admin7b613c72006-09-24 18:05:17 +0000138 log_message('error', 'Unable to connect to the database');
139
admin6871d952006-10-04 00:36:18 +0000140 if ($this->db_debug)
141 {
admin7b613c72006-09-24 18:05:17 +0000142 $this->display_error('db_unable_to_connect');
admin6871d952006-10-04 00:36:18 +0000143 }
144 }
admin7b613c72006-09-24 18:05:17 +0000145 else
146 {
147 if ( ! $this->db_select())
148 {
149 log_message('error', 'Unable to select database: '.$this->database);
150
151 if ($this->db_debug)
152 {
153 $this->display_error('db_unable_to_select', $this->database);
154 }
155 }
admin6871d952006-10-04 00:36:18 +0000156 }
admin7b613c72006-09-24 18:05:17 +0000157 }
admin88a8ad12006-10-07 03:16:32 +0000158
admin7b613c72006-09-24 18:05:17 +0000159 // --------------------------------------------------------------------
160
161 /**
admin9cd4e8e2006-09-25 23:26:25 +0000162 * The name of the platform in use (mysql, mssql, etc...)
163 *
164 * @access public
165 * @return string
166 */
167 function platform()
168 {
169 return $this->dbdriver;
170 }
171
172 // --------------------------------------------------------------------
173
174 /**
175 * Database Version Number. Returns a string containing the
176 * version of the database being used
177 *
178 * @access public
179 * @return string
180 */
181 function version()
182 {
183 if (FALSE === ($sql = $this->_version()))
184 {
admin6871d952006-10-04 00:36:18 +0000185 if ($this->db_debug)
186 {
admin9cd4e8e2006-09-25 23:26:25 +0000187 return $this->display_error('db_unsupported_function');
admin6871d952006-10-04 00:36:18 +0000188 }
189 return FALSE;
admin9cd4e8e2006-09-25 23:26:25 +0000190 }
191
admin6871d952006-10-04 00:36:18 +0000192 if ($this->dbdriver == 'oci8')
193 {
admin9cd4e8e2006-09-25 23:26:25 +0000194 return $sql;
195 }
196
197 $query = $this->query($sql);
198 $row = $query->row();
199 return $row->ver;
200 }
201
202 // --------------------------------------------------------------------
203
204 /**
admin7b613c72006-09-24 18:05:17 +0000205 * Execute the query
206 *
207 * Accepts an SQL string as input and returns a result object upon
208 * successful execution of a "read" type query. Returns boolean TRUE
209 * upon successful execution of a "write" type query. Returns boolean
210 * FALSE upon failure, and if the $db_debug variable is set to TRUE
211 * will raise an error.
212 *
213 * @access public
214 * @param string An SQL query string
215 * @param array An array of binding data
216 * @return mixed
217 */
admin6871d952006-10-04 00:36:18 +0000218 function query($sql, $binds = FALSE, $return_object = TRUE)
admindb8a3742006-10-04 07:43:35 +0000219 {
admin7b613c72006-09-24 18:05:17 +0000220 if ($sql == '')
221 {
admin6871d952006-10-04 00:36:18 +0000222 if ($this->db_debug)
223 {
admin7b613c72006-09-24 18:05:17 +0000224 log_message('error', 'Invalid query: '.$sql);
225 return $this->display_error('db_invalid_query');
admin6871d952006-10-04 00:36:18 +0000226 }
227 return FALSE;
admin7b613c72006-09-24 18:05:17 +0000228 }
229
admin0c405652006-10-04 18:37:57 +0000230 // Is query caching enabled? If the query is a "read type"
231 // we will load the caching class and return the previously
232 // cached query if it exists
admin6871d952006-10-04 00:36:18 +0000233 if ($this->cache_on == TRUE AND stristr($sql, 'SELECT'))
admin0c405652006-10-04 18:37:57 +0000234 {
235 if ($this->_cache_init())
admine8f6eb62006-10-02 06:46:16 +0000236 {
adminc2e3cd72006-10-05 04:22:30 +0000237 if (FALSE !== ($cache = $this->CACHE->read($sql)))
admin0c405652006-10-04 18:37:57 +0000238 {
admin9fcc28a2006-10-21 17:49:47 +0000239 $this->load_rdriver();
admin0c405652006-10-04 18:37:57 +0000240 return $cache;
241 }
admine8f6eb62006-10-02 06:46:16 +0000242 }
243 }
244
admin7b613c72006-09-24 18:05:17 +0000245 // Compile binds if needed
246 if ($binds !== FALSE)
247 {
248 $sql = $this->compile_binds($sql, $binds);
249 }
250
admin6871d952006-10-04 00:36:18 +0000251 // Save the query for debugging
252 $this->queries[] = $sql;
admin7b613c72006-09-24 18:05:17 +0000253
254 // Start the Query Timer
admin6871d952006-10-04 00:36:18 +0000255 $time_start = list($sm, $ss) = explode(' ', microtime());
256
admin7b613c72006-09-24 18:05:17 +0000257 // Run the Query
admin6871d952006-10-04 00:36:18 +0000258 if (FALSE === ($this->result_id = $this->simple_query($sql)))
259 {
260 // This will trigger a rollback if transactions are being used
261 $this->_trans_failure = TRUE;
262
263 if ($this->db_debug)
264 {
adminbb1d4392006-09-24 20:14:38 +0000265 log_message('error', 'Query error: '.$this->_error_message());
admin7b613c72006-09-24 18:05:17 +0000266 return $this->display_error(
267 array(
adminbb1d4392006-09-24 20:14:38 +0000268 'Error Number: '.$this->_error_number(),
269 $this->_error_message(),
admin7b613c72006-09-24 18:05:17 +0000270 $sql
271 )
272 );
admin6871d952006-10-04 00:36:18 +0000273 }
274
275 return FALSE;
276 }
277
admin7b613c72006-09-24 18:05:17 +0000278 // Stop and aggregate the query time results
279 $time_end = list($em, $es) = explode(' ', microtime());
280 $this->benchmark += ($em + $es) - ($sm + $ss);
281
282 // Increment the query counter
admin6871d952006-10-04 00:36:18 +0000283 $this->query_count++;
284
admin7b613c72006-09-24 18:05:17 +0000285 // Was the query a "write" type?
286 // If so we'll simply return true
287 if ($this->is_write_type($sql) === TRUE)
admindb8a3742006-10-04 07:43:35 +0000288 {
289 // If caching is enabled we'll auto-cleanup any
290 // existing files related to this particular URI
admina658e312006-10-06 01:29:36 +0000291 if ($this->cache_on == TRUE AND $this->cache_autodel == TRUE AND $this->_cache_init())
admindb8a3742006-10-04 07:43:35 +0000292 {
adminc2e3cd72006-10-05 04:22:30 +0000293 $this->CACHE->delete();
admindb8a3742006-10-04 07:43:35 +0000294 }
295
admin7b613c72006-09-24 18:05:17 +0000296 return TRUE;
297 }
298
299 // Return TRUE if we don't need to create a result object
300 // Currently only the Oracle driver uses this when stored
301 // procedures are used
302 if ($return_object !== TRUE)
303 {
304 return TRUE;
305 }
admindb8a3742006-10-04 07:43:35 +0000306
307 // Load and instantiate the result driver
admindb8a3742006-10-04 07:43:35 +0000308
adminc2e3cd72006-10-05 04:22:30 +0000309 $driver = $this->load_rdriver();
310 $RES = new $driver();
admin6871d952006-10-04 00:36:18 +0000311 $RES->conn_id = $this->conn_id;
admin6871d952006-10-04 00:36:18 +0000312 $RES->result_id = $this->result_id;
313
314 if ($this->dbdriver == 'oci8')
315 {
adminc2e3cd72006-10-05 04:22:30 +0000316 $RES->stmt_id = $this->stmt_id;
317 $RES->curs_id = NULL;
318 $RES->limit_used = $this->limit_used;
admin6871d952006-10-04 00:36:18 +0000319 }
admindb8a3742006-10-04 07:43:35 +0000320
321 // Is query caching enabled? If so, we'll serialize the
adminc2e3cd72006-10-05 04:22:30 +0000322 // result object and save it to a cache file.
admin0c405652006-10-04 18:37:57 +0000323 if ($this->cache_on == TRUE AND $this->_cache_init())
adminc2e3cd72006-10-05 04:22:30 +0000324 {
325 // We'll create a new instance of the result object
326 // only without the platform specific driver since
327 // we can't use it with cached data (the query result
328 // resource ID won't be any good once we've cached the
329 // result object, so we'll have to compile the data
330 // and save it)
331 $CR = new CI_DB_result();
332 $CR->num_rows = $RES->num_rows();
333 $CR->result_object = $RES->result_object();
334 $CR->result_array = $RES->result_array();
admina658e312006-10-06 01:29:36 +0000335
336 // Reset these since cached objects can not utilize resource IDs.
337 $CR->conn_id = NULL;
338 $CR->result_id = NULL;
adminc2e3cd72006-10-05 04:22:30 +0000339
340 $this->CACHE->write($sql, $CR);
admindb8a3742006-10-04 07:43:35 +0000341 }
342
admin7b613c72006-09-24 18:05:17 +0000343 return $RES;
344 }
admindb8a3742006-10-04 07:43:35 +0000345
346 // --------------------------------------------------------------------
347
348 /**
349 * Load the result drivers
350 *
351 * @access public
352 * @return string the name of the result class
353 */
354 function load_rdriver()
355 {
356 $driver = 'CI_DB_'.$this->dbdriver.'_result';
357
358 if ( ! class_exists($driver))
359 {
360 include_once(BASEPATH.'database/DB_result'.EXT);
361 include_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result'.EXT);
362 }
363
364 return $driver;
365 }
admin7b613c72006-09-24 18:05:17 +0000366
367 // --------------------------------------------------------------------
368
369 /**
370 * Simple Query
371 * This is a simiplified version of the query() function. Internally
372 * we only use it when running transaction commands since they do
373 * not require all the features of the main query() function.
374 *
375 * @access public
376 * @param string the sql query
377 * @return mixed
378 */
379 function simple_query($sql)
380 {
381 if ( ! $this->conn_id)
382 {
383 $this->initialize();
384 }
385
admin40037182006-10-11 19:16:58 +0000386 return $this->_execute($sql);
admin7b613c72006-09-24 18:05:17 +0000387 }
388
389 // --------------------------------------------------------------------
390
391 /**
392 * Disable Transactions
393 * This permits transactions to be disabled at run-time.
394 *
395 * @access public
396 * @return void
397 */
398 function trans_off()
399 {
400 $this->trans_enabled = FALSE;
401 }
402
403 // --------------------------------------------------------------------
404
405 /**
406 * Start Transaction
407 *
408 * @access public
409 * @return void
410 */
411 function trans_start($test_mode = FALSE)
412 {
413 if ( ! $this->trans_enabled)
414 {
415 return FALSE;
416 }
417
418 // When transactions are nested we only begin/commit/rollback the outermost ones
419 if ($this->_trans_depth > 0)
420 {
421 $this->_trans_depth += 1;
422 return;
423 }
424
425 $this->trans_begin($test_mode);
426 }
427
428 // --------------------------------------------------------------------
429
430 /**
431 * Complete Transaction
432 *
433 * @access public
434 * @return bool
435 */
436 function trans_complete()
437 {
438 if ( ! $this->trans_enabled)
439 {
440 return FALSE;
441 }
442
443 // When transactions are nested we only begin/commit/rollback the outermost ones
444 if ($this->_trans_depth > 1)
445 {
446 $this->_trans_depth -= 1;
447 return TRUE;
448 }
449
450 // The query() function will set this flag to TRUE in the event that a query failed
451 if ($this->_trans_failure === TRUE)
452 {
453 $this->trans_rollback();
454
455 if ($this->db_debug)
456 {
457 return $this->display_error('db_transaction_failure');
458 }
459 return FALSE;
460 }
461
462 $this->trans_commit();
463 return TRUE;
464 }
465
466 // --------------------------------------------------------------------
467
468 /**
469 * Lets you retrieve the transaction flag to determine if it has failed
470 *
471 * @access public
472 * @return bool
473 */
474 function trans_status()
475 {
476 return $this->_trans_failure;
477 }
478
479 // --------------------------------------------------------------------
480
481 /**
482 * Compile Bindings
483 *
484 * @access public
485 * @param string the sql statement
486 * @param array an array of bind data
487 * @return string
488 */
489 function compile_binds($sql, $binds)
490 {
491 if (FALSE === strpos($sql, $this->bind_marker))
492 {
493 return $sql;
494 }
495
496 if ( ! is_array($binds))
497 {
498 $binds = array($binds);
499 }
500
501 foreach ($binds as $val)
502 {
503 $val = $this->escape($val);
504
505 // Just in case the replacement string contains the bind
506 // character we'll temporarily replace it with a marker
507 $val = str_replace($this->bind_marker, '{%bind_marker%}', $val);
508 $sql = preg_replace("#".preg_quote($this->bind_marker, '#')."#", str_replace('$', '\$', $val), $sql, 1);
509 }
510
511 return str_replace('{%bind_marker%}', $this->bind_marker, $sql);
512 }
513
514 // --------------------------------------------------------------------
515
516 /**
517 * Determines if a query is a "write" type.
518 *
519 * @access public
520 * @param string An SQL query string
521 * @return boolean
522 */
523 function is_write_type($sql)
524 {
525 if ( ! preg_match('/^\s*"?(INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|LOAD DATA|COPY|ALTER|GRANT|REVOKE|LOCK|UNLOCK)\s+/i', $sql))
526 {
527 return FALSE;
528 }
529 return TRUE;
530 }
531
532 // --------------------------------------------------------------------
533
534 /**
535 * Calculate the aggregate query elapsed time
536 *
537 * @access public
538 * @param intiger The number of decimal places
539 * @return integer
540 */
541 function elapsed_time($decimals = 6)
542 {
543 return number_format($this->benchmark, $decimals);
544 }
545
546 // --------------------------------------------------------------------
547
548 /**
549 * Returns the total number of queries
550 *
551 * @access public
552 * @return integer
553 */
554 function total_queries()
555 {
556 return $this->query_count;
557 }
558
559 // --------------------------------------------------------------------
560
561 /**
562 * Returns the last query that was executed
563 *
564 * @access public
565 * @return void
566 */
567 function last_query()
568 {
569 return end($this->queries);
570 }
571
572 // --------------------------------------------------------------------
573
574 /**
575 * "Smart" Escape String
576 *
577 * Escapes data based on type
578 * Sets boolean and null types
579 *
580 * @access public
581 * @param string
582 * @return integer
583 */
584 function escape($str)
585 {
586 switch (gettype($str))
587 {
588 case 'string' : $str = "'".$this->escape_str($str)."'";
589 break;
590 case 'boolean' : $str = ($str === FALSE) ? 0 : 1;
591 break;
592 default : $str = ($str === NULL) ? 'NULL' : $str;
593 break;
594 }
595
596 return $str;
adminbb1d4392006-09-24 20:14:38 +0000597 }
598
admin9cd4e8e2006-09-25 23:26:25 +0000599
600
601 // --------------------------------------------------------------------
602
603 /**
604 * Primary
605 *
606 * Retrieves the primary key. It assumes that the row in the first
607 * position is the primary key
608 *
609 * @access public
610 * @param string the table name
611 * @return string
612 */
613 function primary($table = '')
614 {
admin606f99c2006-10-11 23:48:41 +0000615 $fields = $this->list_fields($table);
admin9cd4e8e2006-09-25 23:26:25 +0000616
617 if ( ! is_array($fields))
618 {
619 return FALSE;
620 }
621
622 return current($fields);
623 }
624
625 // --------------------------------------------------------------------
626
admin3dd978f2006-09-30 19:24:45 +0000627 /**
628 * Returns an array of table names
629 *
630 * @access public
631 * @return array
632 */
633 function list_tables()
634 {
635 // Is there a cached result?
admine8f6eb62006-10-02 06:46:16 +0000636 if (isset($this->data_cache['table_names']))
admin3dd978f2006-09-30 19:24:45 +0000637 {
admine8f6eb62006-10-02 06:46:16 +0000638 return $this->data_cache['table_names'];
admin3dd978f2006-09-30 19:24:45 +0000639 }
640
641 if (FALSE === ($sql = $this->_list_tables()))
642 {
admin6871d952006-10-04 00:36:18 +0000643 if ($this->db_debug)
644 {
admin3dd978f2006-09-30 19:24:45 +0000645 return $this->display_error('db_unsupported_function');
admin6871d952006-10-04 00:36:18 +0000646 }
647 return FALSE;
admin3dd978f2006-09-30 19:24:45 +0000648 }
649
650 $retval = array();
651 $query = $this->query($sql);
652
653 if ($query->num_rows() > 0)
654 {
655 foreach($query->result_array() as $row)
656 {
657 if (isset($row['TABLE_NAME']))
658 {
659 $retval[] = $row['TABLE_NAME'];
660 }
661 else
662 {
663 $retval[] = array_shift($row);
664 }
665 }
666 }
667
admin7099a582006-10-10 17:47:59 +0000668 $this->data_cache['table_names'] = $retval;
669 return $this->data_cache['table_names'];
admin3dd978f2006-09-30 19:24:45 +0000670 }
671
672 // --------------------------------------------------------------------
673
674 /**
675 * Determine if a particular table exists
676 * @access public
677 * @return boolean
678 */
679 function table_exists($table_name)
680 {
681 return ( ! in_array($this->dbprefix.$table_name, $this->list_tables())) ? FALSE : TRUE;
682 }
683
684 // --------------------------------------------------------------------
685
admin9cd4e8e2006-09-25 23:26:25 +0000686 /**
687 * Fetch MySQL Field Names
688 *
689 * @access public
690 * @param string the table name
691 * @return array
692 */
admin6871d952006-10-04 00:36:18 +0000693 function list_fields($table = '')
694 {
admin3ed8c512006-09-29 23:26:28 +0000695 // Is there a cached result?
admine8f6eb62006-10-02 06:46:16 +0000696 if (isset($this->data_cache['field_names'][$table]))
admin3ed8c512006-09-29 23:26:28 +0000697 {
admine8f6eb62006-10-02 06:46:16 +0000698 return $this->data_cache['field_names'][$table];
admin3ed8c512006-09-29 23:26:28 +0000699 }
admin6871d952006-10-04 00:36:18 +0000700
701 if ($table == '')
702 {
admin9cd4e8e2006-09-25 23:26:25 +0000703 if ($this->db_debug)
704 {
705 return $this->display_error('db_field_param_missing');
706 }
707 return FALSE;
admin6871d952006-10-04 00:36:18 +0000708 }
709
admin9cd4e8e2006-09-25 23:26:25 +0000710 if (FALSE === ($sql = $this->_list_columns($this->dbprefix.$table)))
711 {
admin6871d952006-10-04 00:36:18 +0000712 if ($this->db_debug)
713 {
admin9cd4e8e2006-09-25 23:26:25 +0000714 return $this->display_error('db_unsupported_function');
admin6871d952006-10-04 00:36:18 +0000715 }
716 return FALSE;
admin9cd4e8e2006-09-25 23:26:25 +0000717 }
admin6871d952006-10-04 00:36:18 +0000718
719 $query = $this->query($sql);
720
721 $retval = array();
admin9cd4e8e2006-09-25 23:26:25 +0000722 foreach($query->result_array() as $row)
723 {
724 if (isset($row['COLUMN_NAME']))
725 {
726 $retval[] = $row['COLUMN_NAME'];
727 }
728 else
729 {
730 $retval[] = current($row);
admin6871d952006-10-04 00:36:18 +0000731 }
admin9cd4e8e2006-09-25 23:26:25 +0000732 }
admin6871d952006-10-04 00:36:18 +0000733
admin7099a582006-10-10 17:47:59 +0000734 $this->data_cache['field_names'][$table] = $retval;
735 return $this->data_cache['field_names'][$table];
admin6871d952006-10-04 00:36:18 +0000736 }
adminb2a9cec2006-10-01 03:38:04 +0000737
738 // --------------------------------------------------------------------
739
740 /**
741 * Determine if a particular field exists
742 * @access public
743 * @param string
744 * @param string
745 * @return boolean
746 */
747 function field_exists($field_name, $table_name)
748 {
749 return ( ! in_array($field_name, $this->list_fields($table_name))) ? FALSE : TRUE;
750 }
admin6871d952006-10-04 00:36:18 +0000751
admin3dd978f2006-09-30 19:24:45 +0000752 // --------------------------------------------------------------------
753
754 /**
755 * DEPRECATED - use list_fields()
756 */
admin6871d952006-10-04 00:36:18 +0000757 function field_names($table = '')
758 {
759 return $this->list_fields($table);
760 }
admin9cd4e8e2006-09-25 23:26:25 +0000761
762 // --------------------------------------------------------------------
763
764 /**
765 * Returns an object with field data
766 *
767 * @access public
768 * @param string the table name
769 * @return object
770 */
771 function field_data($table = '')
772 {
admin6871d952006-10-04 00:36:18 +0000773 if ($table == '')
774 {
admin9cd4e8e2006-09-25 23:26:25 +0000775 if ($this->db_debug)
776 {
777 return $this->display_error('db_field_param_missing');
778 }
779 return FALSE;
admin6871d952006-10-04 00:36:18 +0000780 }
781
admin9cd4e8e2006-09-25 23:26:25 +0000782 $query = $this->query($this->_field_data($this->dbprefix.$table));
783 return $query->field_data();
784 }
785
adminbb1d4392006-09-24 20:14:38 +0000786 // --------------------------------------------------------------------
787
788 /**
789 * Generate an insert string
790 *
791 * @access public
792 * @param string the table upon which the query will be performed
793 * @param array an associative array data of key/values
794 * @return string
795 */
796 function insert_string($table, $data)
797 {
admin6871d952006-10-04 00:36:18 +0000798 $fields = array();
adminbb1d4392006-09-24 20:14:38 +0000799 $values = array();
800
801 foreach($data as $key => $val)
802 {
803 $fields[] = $key;
804 $values[] = $this->escape($val);
805 }
806
807 return $this->_insert($this->dbprefix.$table, $fields, $values);
808 }
809
810 // --------------------------------------------------------------------
811
812 /**
813 * Generate an update string
814 *
815 * @access public
816 * @param string the table upon which the query will be performed
817 * @param array an associative array data of key/values
818 * @param mixed the "where" statement
819 * @return string
820 */
821 function update_string($table, $data, $where)
822 {
823 if ($where == '')
824 return false;
825
826 $fields = array();
827 foreach($data as $key => $val)
828 {
829 $fields[$key] = $this->escape($val);
830 }
831
832 if ( ! is_array($where))
833 {
834 $dest = array($where);
835 }
836 else
837 {
838 $dest = array();
839 foreach ($where as $key => $val)
840 {
841 $prefix = (count($dest) == 0) ? '' : ' AND ';
842
843 if ($val != '')
844 {
845 if ( ! $this->_has_operator($key))
846 {
847 $key .= ' =';
848 }
849
850 $val = ' '.$this->escape($val);
851 }
852
853 $dest[] = $prefix.$key.$val;
854 }
855 }
856
857 return $this->_update($this->dbprefix.$table, $fields, $dest);
admin6871d952006-10-04 00:36:18 +0000858 }
admin7b613c72006-09-24 18:05:17 +0000859
860 // --------------------------------------------------------------------
861
862 /**
863 * Enables a native PHP function to be run, using a platform agnostic wrapper.
864 *
865 * @access public
866 * @param string the function name
867 * @param mixed any parameters needed by the function
868 * @return mixed
869 */
870 function call_function($function)
871 {
872 $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_';
873
874 if (FALSE === strpos($driver, $function))
875 {
876 $function = $driver.$function;
877 }
878
879 if ( ! function_exists($function))
880 {
881 if ($this->db_debug)
882 {
883 return $this->display_error('db_unsupported_function');
884 }
885 return FALSE;
886 }
887 else
888 {
adminee54c112006-09-28 17:13:38 +0000889 $args = (func_num_args() > 1) ? array_splice(func_get_args(), 1) : null;
890
admin7b613c72006-09-24 18:05:17 +0000891 return call_user_func_array($function, $args);
892 }
893 }
adminc5f7fa32006-10-06 02:10:23 +0000894
895 // --------------------------------------------------------------------
896
897 /**
898 * Set Cache Directory Path
899 *
900 * @access public
901 * @param string the path to the cache directory
902 * @return void
903 */
904 function cache_set_path($path = '')
905 {
906 $this->cachedir = $path;
907 }
908
admine8f6eb62006-10-02 06:46:16 +0000909 // --------------------------------------------------------------------
910
911 /**
912 * Enable Query Caching
913 *
914 * @access public
915 * @return void
916 */
917 function cache_on()
918 {
admin7099a582006-10-10 17:47:59 +0000919 $this->cache_on = TRUE;
920 return TRUE;
admine8f6eb62006-10-02 06:46:16 +0000921 }
922
923 // --------------------------------------------------------------------
924
925 /**
926 * Disable Query Caching
927 *
928 * @access public
929 * @return void
930 */
931 function cache_off()
932 {
admin7099a582006-10-10 17:47:59 +0000933 $this->cache_on = FALSE;
934 return FALSE;
admine8f6eb62006-10-02 06:46:16 +0000935 }
adminfa708172006-10-04 18:42:42 +0000936
adminc5f7fa32006-10-06 02:10:23 +0000937
adminfa708172006-10-04 18:42:42 +0000938 // --------------------------------------------------------------------
939
940 /**
adminc5f7fa32006-10-06 02:10:23 +0000941 * Delete the cache files associated with a particular URI
adminfa708172006-10-04 18:42:42 +0000942 *
943 * @access public
adminfa708172006-10-04 18:42:42 +0000944 * @return void
945 */
admin1b0ab462006-10-10 23:30:21 +0000946 function cache_delete($segment_one = '', $segment_two = '')
adminfa708172006-10-04 18:42:42 +0000947 {
adminc5f7fa32006-10-06 02:10:23 +0000948 if ( ! $this->_cache_init())
949 {
950 return FALSE;
951 }
admin1b0ab462006-10-10 23:30:21 +0000952 return $this->CACHE->delete($segment_one, $segment_two);
adminc5f7fa32006-10-06 02:10:23 +0000953 }
954
955 // --------------------------------------------------------------------
956
957 /**
958 * Delete All cache files
959 *
960 * @access public
961 * @return void
962 */
963 function cache_delete_all()
964 {
965 if ( ! $this->_cache_init())
966 {
967 return FALSE;
968 }
969
970 return $this->CACHE->delete_all();
adminfa708172006-10-04 18:42:42 +0000971 }
admin0c405652006-10-04 18:37:57 +0000972
admin6871d952006-10-04 00:36:18 +0000973 // --------------------------------------------------------------------
974
975 /**
admin0c405652006-10-04 18:37:57 +0000976 * Initialize the Cache Class
admin6871d952006-10-04 00:36:18 +0000977 *
admin0c405652006-10-04 18:37:57 +0000978 * @access private
979 * @return void
980 */
981 function _cache_init()
admin6871d952006-10-04 00:36:18 +0000982 {
adminc2e3cd72006-10-05 04:22:30 +0000983 if (is_object($this->CACHE) AND class_exists('CI_DB_Cache'))
admindb8a3742006-10-04 07:43:35 +0000984 {
admin0c405652006-10-04 18:37:57 +0000985 return TRUE;
admindb8a3742006-10-04 07:43:35 +0000986 }
987
adminfa708172006-10-04 18:42:42 +0000988 if ( ! @include_once(BASEPATH.'database/DB_cache'.EXT))
admin6871d952006-10-04 00:36:18 +0000989 {
adminfa708172006-10-04 18:42:42 +0000990 return $this->cache_off();
admin6871d952006-10-04 00:36:18 +0000991 }
992
adminc2e3cd72006-10-05 04:22:30 +0000993 $this->CACHE = new CI_DB_Cache;
admin6871d952006-10-04 00:36:18 +0000994 return TRUE;
995 }
996
admindb8a3742006-10-04 07:43:35 +0000997
998 // --------------------------------------------------------------------
999
1000 /**
admin7b613c72006-09-24 18:05:17 +00001001 * Close DB Connection
1002 *
1003 * @access public
1004 * @return void
1005 */
admin6871d952006-10-04 00:36:18 +00001006 function close()
1007 {
1008 if (is_resource($this->conn_id))
1009 {
1010 $this->_close($this->conn_id);
admin7b613c72006-09-24 18:05:17 +00001011 }
1012 $this->conn_id = FALSE;
admin6871d952006-10-04 00:36:18 +00001013 }
admin7b613c72006-09-24 18:05:17 +00001014
1015 // --------------------------------------------------------------------
1016
1017 /**
1018 * Display an error message
1019 *
1020 * @access public
1021 * @param string the error message
1022 * @param string any "swap" values
1023 * @param boolean whether to localize the message
1024 * @return string sends the application/errror_db.php template
1025 */
admin6871d952006-10-04 00:36:18 +00001026 function display_error($error = '', $swap = '', $native = FALSE)
1027 {
admin7b613c72006-09-24 18:05:17 +00001028 $LANG = new CI_Language();
1029 $LANG->load('db');
1030
1031 $heading = 'MySQL Error';
1032
1033 if ($native == TRUE)
1034 {
1035 $message = $error;
1036 }
1037 else
1038 {
1039 $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error;
1040 }
1041
1042 if ( ! class_exists('CI_Exceptions'))
1043 {
1044 include_once(BASEPATH.'libraries/Exceptions'.EXT);
1045 }
1046
1047 $error = new CI_Exceptions();
1048 echo $error->show_error('An Error Was Encountered', $message, 'error_db');
1049 exit;
1050
admin6871d952006-10-04 00:36:18 +00001051 }
admin7b613c72006-09-24 18:05:17 +00001052
1053}
1054
1055?>