blob: b89ebbf8df9f3d4938f32e8354e81ce88b148ec0 [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 }
158
adminfd2750b2006-10-06 17:29:12 +0000159 // --------------------------------------------------------------------
160
161 /**
162 * Load the Utilities Class
163 *
164 * @access public
165 * @return string
166 */
167 function load_utilities()
168 {
169 $obj =& get_instance();
170
171 require_once(BASEPATH.'database/DB_utility'.EXT);
172 require_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_utility'.EXT);
173 $class = 'CI_DB_'.$this->dbdriver.'_utility';
174 $obj->dbutil = new $class();
175 }
admin7b613c72006-09-24 18:05:17 +0000176
177 // --------------------------------------------------------------------
178
179 /**
admin9cd4e8e2006-09-25 23:26:25 +0000180 * The name of the platform in use (mysql, mssql, etc...)
181 *
182 * @access public
183 * @return string
184 */
185 function platform()
186 {
187 return $this->dbdriver;
188 }
189
190 // --------------------------------------------------------------------
191
192 /**
193 * Database Version Number. Returns a string containing the
194 * version of the database being used
195 *
196 * @access public
197 * @return string
198 */
199 function version()
200 {
201 if (FALSE === ($sql = $this->_version()))
202 {
admin6871d952006-10-04 00:36:18 +0000203 if ($this->db_debug)
204 {
admin9cd4e8e2006-09-25 23:26:25 +0000205 return $this->display_error('db_unsupported_function');
admin6871d952006-10-04 00:36:18 +0000206 }
207 return FALSE;
admin9cd4e8e2006-09-25 23:26:25 +0000208 }
209
admin6871d952006-10-04 00:36:18 +0000210 if ($this->dbdriver == 'oci8')
211 {
admin9cd4e8e2006-09-25 23:26:25 +0000212 return $sql;
213 }
214
215 $query = $this->query($sql);
216 $row = $query->row();
217 return $row->ver;
218 }
219
220 // --------------------------------------------------------------------
221
222 /**
admin7b613c72006-09-24 18:05:17 +0000223 * Execute the query
224 *
225 * Accepts an SQL string as input and returns a result object upon
226 * successful execution of a "read" type query. Returns boolean TRUE
227 * upon successful execution of a "write" type query. Returns boolean
228 * FALSE upon failure, and if the $db_debug variable is set to TRUE
229 * will raise an error.
230 *
231 * @access public
232 * @param string An SQL query string
233 * @param array An array of binding data
234 * @return mixed
235 */
admin6871d952006-10-04 00:36:18 +0000236 function query($sql, $binds = FALSE, $return_object = TRUE)
admindb8a3742006-10-04 07:43:35 +0000237 {
admin7b613c72006-09-24 18:05:17 +0000238 if ($sql == '')
239 {
admin6871d952006-10-04 00:36:18 +0000240 if ($this->db_debug)
241 {
admin7b613c72006-09-24 18:05:17 +0000242 log_message('error', 'Invalid query: '.$sql);
243 return $this->display_error('db_invalid_query');
admin6871d952006-10-04 00:36:18 +0000244 }
245 return FALSE;
admin7b613c72006-09-24 18:05:17 +0000246 }
247
admin0c405652006-10-04 18:37:57 +0000248 // Is query caching enabled? If the query is a "read type"
249 // we will load the caching class and return the previously
250 // cached query if it exists
admin6871d952006-10-04 00:36:18 +0000251 if ($this->cache_on == TRUE AND stristr($sql, 'SELECT'))
admin0c405652006-10-04 18:37:57 +0000252 {
253 if ($this->_cache_init())
admine8f6eb62006-10-02 06:46:16 +0000254 {
adminc2e3cd72006-10-05 04:22:30 +0000255 if (FALSE !== ($cache = $this->CACHE->read($sql)))
admin0c405652006-10-04 18:37:57 +0000256 {
257 return $cache;
258 }
admine8f6eb62006-10-02 06:46:16 +0000259 }
260 }
261
admin7b613c72006-09-24 18:05:17 +0000262 // Compile binds if needed
263 if ($binds !== FALSE)
264 {
265 $sql = $this->compile_binds($sql, $binds);
266 }
267
admin6871d952006-10-04 00:36:18 +0000268 // Save the query for debugging
269 $this->queries[] = $sql;
admin7b613c72006-09-24 18:05:17 +0000270
271 // Start the Query Timer
admin6871d952006-10-04 00:36:18 +0000272 $time_start = list($sm, $ss) = explode(' ', microtime());
273
admin7b613c72006-09-24 18:05:17 +0000274 // Run the Query
admin6871d952006-10-04 00:36:18 +0000275 if (FALSE === ($this->result_id = $this->simple_query($sql)))
276 {
277 // This will trigger a rollback if transactions are being used
278 $this->_trans_failure = TRUE;
279
280 if ($this->db_debug)
281 {
adminbb1d4392006-09-24 20:14:38 +0000282 log_message('error', 'Query error: '.$this->_error_message());
admin7b613c72006-09-24 18:05:17 +0000283 return $this->display_error(
284 array(
adminbb1d4392006-09-24 20:14:38 +0000285 'Error Number: '.$this->_error_number(),
286 $this->_error_message(),
admin7b613c72006-09-24 18:05:17 +0000287 $sql
288 )
289 );
admin6871d952006-10-04 00:36:18 +0000290 }
291
292 return FALSE;
293 }
294
admin7b613c72006-09-24 18:05:17 +0000295 // Stop and aggregate the query time results
296 $time_end = list($em, $es) = explode(' ', microtime());
297 $this->benchmark += ($em + $es) - ($sm + $ss);
298
299 // Increment the query counter
admin6871d952006-10-04 00:36:18 +0000300 $this->query_count++;
301
admin7b613c72006-09-24 18:05:17 +0000302 // Was the query a "write" type?
303 // If so we'll simply return true
304 if ($this->is_write_type($sql) === TRUE)
admindb8a3742006-10-04 07:43:35 +0000305 {
306 // If caching is enabled we'll auto-cleanup any
307 // existing files related to this particular URI
admina658e312006-10-06 01:29:36 +0000308 if ($this->cache_on == TRUE AND $this->cache_autodel == TRUE AND $this->_cache_init())
admindb8a3742006-10-04 07:43:35 +0000309 {
adminc2e3cd72006-10-05 04:22:30 +0000310 $this->CACHE->delete();
admindb8a3742006-10-04 07:43:35 +0000311 }
312
admin7b613c72006-09-24 18:05:17 +0000313 return TRUE;
314 }
315
316 // Return TRUE if we don't need to create a result object
317 // Currently only the Oracle driver uses this when stored
318 // procedures are used
319 if ($return_object !== TRUE)
320 {
321 return TRUE;
322 }
admindb8a3742006-10-04 07:43:35 +0000323
324 // Load and instantiate the result driver
admindb8a3742006-10-04 07:43:35 +0000325
adminc2e3cd72006-10-05 04:22:30 +0000326 $driver = $this->load_rdriver();
327 $RES = new $driver();
admin6871d952006-10-04 00:36:18 +0000328 $RES->conn_id = $this->conn_id;
admin6871d952006-10-04 00:36:18 +0000329 $RES->result_id = $this->result_id;
330
331 if ($this->dbdriver == 'oci8')
332 {
adminc2e3cd72006-10-05 04:22:30 +0000333 $RES->stmt_id = $this->stmt_id;
334 $RES->curs_id = NULL;
335 $RES->limit_used = $this->limit_used;
admin6871d952006-10-04 00:36:18 +0000336 }
admindb8a3742006-10-04 07:43:35 +0000337
338 // Is query caching enabled? If so, we'll serialize the
adminc2e3cd72006-10-05 04:22:30 +0000339 // result object and save it to a cache file.
admin0c405652006-10-04 18:37:57 +0000340 if ($this->cache_on == TRUE AND $this->_cache_init())
adminc2e3cd72006-10-05 04:22:30 +0000341 {
342 // We'll create a new instance of the result object
343 // only without the platform specific driver since
344 // we can't use it with cached data (the query result
345 // resource ID won't be any good once we've cached the
346 // result object, so we'll have to compile the data
347 // and save it)
348 $CR = new CI_DB_result();
349 $CR->num_rows = $RES->num_rows();
350 $CR->result_object = $RES->result_object();
351 $CR->result_array = $RES->result_array();
admina658e312006-10-06 01:29:36 +0000352
353 // Reset these since cached objects can not utilize resource IDs.
354 $CR->conn_id = NULL;
355 $CR->result_id = NULL;
adminc2e3cd72006-10-05 04:22:30 +0000356
357 $this->CACHE->write($sql, $CR);
admindb8a3742006-10-04 07:43:35 +0000358 }
359
admin7b613c72006-09-24 18:05:17 +0000360 return $RES;
361 }
admindb8a3742006-10-04 07:43:35 +0000362
363 // --------------------------------------------------------------------
364
365 /**
366 * Load the result drivers
367 *
368 * @access public
369 * @return string the name of the result class
370 */
371 function load_rdriver()
372 {
373 $driver = 'CI_DB_'.$this->dbdriver.'_result';
374
375 if ( ! class_exists($driver))
376 {
377 include_once(BASEPATH.'database/DB_result'.EXT);
378 include_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result'.EXT);
379 }
380
381 return $driver;
382 }
admin7b613c72006-09-24 18:05:17 +0000383
384 // --------------------------------------------------------------------
385
386 /**
387 * Simple Query
388 * This is a simiplified version of the query() function. Internally
389 * we only use it when running transaction commands since they do
390 * not require all the features of the main query() function.
391 *
392 * @access public
393 * @param string the sql query
394 * @return mixed
395 */
396 function simple_query($sql)
397 {
398 if ( ! $this->conn_id)
399 {
400 $this->initialize();
401 }
402
403 return $this->_execute($sql, $this->conn_id);
404 }
405
406 // --------------------------------------------------------------------
407
408 /**
409 * Disable Transactions
410 * This permits transactions to be disabled at run-time.
411 *
412 * @access public
413 * @return void
414 */
415 function trans_off()
416 {
417 $this->trans_enabled = FALSE;
418 }
419
420 // --------------------------------------------------------------------
421
422 /**
423 * Start Transaction
424 *
425 * @access public
426 * @return void
427 */
428 function trans_start($test_mode = FALSE)
429 {
430 if ( ! $this->trans_enabled)
431 {
432 return FALSE;
433 }
434
435 // When transactions are nested we only begin/commit/rollback the outermost ones
436 if ($this->_trans_depth > 0)
437 {
438 $this->_trans_depth += 1;
439 return;
440 }
441
442 $this->trans_begin($test_mode);
443 }
444
445 // --------------------------------------------------------------------
446
447 /**
448 * Complete Transaction
449 *
450 * @access public
451 * @return bool
452 */
453 function trans_complete()
454 {
455 if ( ! $this->trans_enabled)
456 {
457 return FALSE;
458 }
459
460 // When transactions are nested we only begin/commit/rollback the outermost ones
461 if ($this->_trans_depth > 1)
462 {
463 $this->_trans_depth -= 1;
464 return TRUE;
465 }
466
467 // The query() function will set this flag to TRUE in the event that a query failed
468 if ($this->_trans_failure === TRUE)
469 {
470 $this->trans_rollback();
471
472 if ($this->db_debug)
473 {
474 return $this->display_error('db_transaction_failure');
475 }
476 return FALSE;
477 }
478
479 $this->trans_commit();
480 return TRUE;
481 }
482
483 // --------------------------------------------------------------------
484
485 /**
486 * Lets you retrieve the transaction flag to determine if it has failed
487 *
488 * @access public
489 * @return bool
490 */
491 function trans_status()
492 {
493 return $this->_trans_failure;
494 }
495
496 // --------------------------------------------------------------------
497
498 /**
499 * Compile Bindings
500 *
501 * @access public
502 * @param string the sql statement
503 * @param array an array of bind data
504 * @return string
505 */
506 function compile_binds($sql, $binds)
507 {
508 if (FALSE === strpos($sql, $this->bind_marker))
509 {
510 return $sql;
511 }
512
513 if ( ! is_array($binds))
514 {
515 $binds = array($binds);
516 }
517
518 foreach ($binds as $val)
519 {
520 $val = $this->escape($val);
521
522 // Just in case the replacement string contains the bind
523 // character we'll temporarily replace it with a marker
524 $val = str_replace($this->bind_marker, '{%bind_marker%}', $val);
525 $sql = preg_replace("#".preg_quote($this->bind_marker, '#')."#", str_replace('$', '\$', $val), $sql, 1);
526 }
527
528 return str_replace('{%bind_marker%}', $this->bind_marker, $sql);
529 }
530
531 // --------------------------------------------------------------------
532
533 /**
534 * Determines if a query is a "write" type.
535 *
536 * @access public
537 * @param string An SQL query string
538 * @return boolean
539 */
540 function is_write_type($sql)
541 {
542 if ( ! preg_match('/^\s*"?(INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|LOAD DATA|COPY|ALTER|GRANT|REVOKE|LOCK|UNLOCK)\s+/i', $sql))
543 {
544 return FALSE;
545 }
546 return TRUE;
547 }
548
549 // --------------------------------------------------------------------
550
551 /**
552 * Calculate the aggregate query elapsed time
553 *
554 * @access public
555 * @param intiger The number of decimal places
556 * @return integer
557 */
558 function elapsed_time($decimals = 6)
559 {
560 return number_format($this->benchmark, $decimals);
561 }
562
563 // --------------------------------------------------------------------
564
565 /**
566 * Returns the total number of queries
567 *
568 * @access public
569 * @return integer
570 */
571 function total_queries()
572 {
573 return $this->query_count;
574 }
575
576 // --------------------------------------------------------------------
577
578 /**
579 * Returns the last query that was executed
580 *
581 * @access public
582 * @return void
583 */
584 function last_query()
585 {
586 return end($this->queries);
587 }
588
589 // --------------------------------------------------------------------
590
591 /**
592 * "Smart" Escape String
593 *
594 * Escapes data based on type
595 * Sets boolean and null types
596 *
597 * @access public
598 * @param string
599 * @return integer
600 */
601 function escape($str)
602 {
603 switch (gettype($str))
604 {
605 case 'string' : $str = "'".$this->escape_str($str)."'";
606 break;
607 case 'boolean' : $str = ($str === FALSE) ? 0 : 1;
608 break;
609 default : $str = ($str === NULL) ? 'NULL' : $str;
610 break;
611 }
612
613 return $str;
adminbb1d4392006-09-24 20:14:38 +0000614 }
615
admin9cd4e8e2006-09-25 23:26:25 +0000616
617
618 // --------------------------------------------------------------------
619
620 /**
621 * Primary
622 *
623 * Retrieves the primary key. It assumes that the row in the first
624 * position is the primary key
625 *
626 * @access public
627 * @param string the table name
628 * @return string
629 */
630 function primary($table = '')
631 {
632 $fields = $this->field_names($table);
633
634 if ( ! is_array($fields))
635 {
636 return FALSE;
637 }
638
639 return current($fields);
640 }
641
642 // --------------------------------------------------------------------
643
admin3dd978f2006-09-30 19:24:45 +0000644 /**
645 * Returns an array of table names
646 *
647 * @access public
648 * @return array
649 */
650 function list_tables()
651 {
652 // Is there a cached result?
admine8f6eb62006-10-02 06:46:16 +0000653 if (isset($this->data_cache['table_names']))
admin3dd978f2006-09-30 19:24:45 +0000654 {
admine8f6eb62006-10-02 06:46:16 +0000655 return $this->data_cache['table_names'];
admin3dd978f2006-09-30 19:24:45 +0000656 }
657
658 if (FALSE === ($sql = $this->_list_tables()))
659 {
admin6871d952006-10-04 00:36:18 +0000660 if ($this->db_debug)
661 {
admin3dd978f2006-09-30 19:24:45 +0000662 return $this->display_error('db_unsupported_function');
admin6871d952006-10-04 00:36:18 +0000663 }
664 return FALSE;
admin3dd978f2006-09-30 19:24:45 +0000665 }
666
667 $retval = array();
668 $query = $this->query($sql);
669
670 if ($query->num_rows() > 0)
671 {
672 foreach($query->result_array() as $row)
673 {
674 if (isset($row['TABLE_NAME']))
675 {
676 $retval[] = $row['TABLE_NAME'];
677 }
678 else
679 {
680 $retval[] = array_shift($row);
681 }
682 }
683 }
684
admine8f6eb62006-10-02 06:46:16 +0000685 return $this->data_cache['table_names'] =& $retval;
admin3dd978f2006-09-30 19:24:45 +0000686 }
687
688 // --------------------------------------------------------------------
689
690 /**
691 * Determine if a particular table exists
692 * @access public
693 * @return boolean
694 */
695 function table_exists($table_name)
696 {
697 return ( ! in_array($this->dbprefix.$table_name, $this->list_tables())) ? FALSE : TRUE;
698 }
699
700 // --------------------------------------------------------------------
701
admin9cd4e8e2006-09-25 23:26:25 +0000702 /**
703 * Fetch MySQL Field Names
704 *
705 * @access public
706 * @param string the table name
707 * @return array
708 */
admin6871d952006-10-04 00:36:18 +0000709 function list_fields($table = '')
710 {
admin3ed8c512006-09-29 23:26:28 +0000711 // Is there a cached result?
admine8f6eb62006-10-02 06:46:16 +0000712 if (isset($this->data_cache['field_names'][$table]))
admin3ed8c512006-09-29 23:26:28 +0000713 {
admine8f6eb62006-10-02 06:46:16 +0000714 return $this->data_cache['field_names'][$table];
admin3ed8c512006-09-29 23:26:28 +0000715 }
admin6871d952006-10-04 00:36:18 +0000716
717 if ($table == '')
718 {
admin9cd4e8e2006-09-25 23:26:25 +0000719 if ($this->db_debug)
720 {
721 return $this->display_error('db_field_param_missing');
722 }
723 return FALSE;
admin6871d952006-10-04 00:36:18 +0000724 }
725
admin9cd4e8e2006-09-25 23:26:25 +0000726 if (FALSE === ($sql = $this->_list_columns($this->dbprefix.$table)))
727 {
admin6871d952006-10-04 00:36:18 +0000728 if ($this->db_debug)
729 {
admin9cd4e8e2006-09-25 23:26:25 +0000730 return $this->display_error('db_unsupported_function');
admin6871d952006-10-04 00:36:18 +0000731 }
732 return FALSE;
admin9cd4e8e2006-09-25 23:26:25 +0000733 }
admin6871d952006-10-04 00:36:18 +0000734
735 $query = $this->query($sql);
736
737 $retval = array();
admin9cd4e8e2006-09-25 23:26:25 +0000738 foreach($query->result_array() as $row)
739 {
740 if (isset($row['COLUMN_NAME']))
741 {
742 $retval[] = $row['COLUMN_NAME'];
743 }
744 else
745 {
746 $retval[] = current($row);
admin6871d952006-10-04 00:36:18 +0000747 }
admin9cd4e8e2006-09-25 23:26:25 +0000748 }
admin6871d952006-10-04 00:36:18 +0000749
admine8f6eb62006-10-02 06:46:16 +0000750 return $this->data_cache['field_names'][$table] =& $retval;
admin6871d952006-10-04 00:36:18 +0000751 }
adminb2a9cec2006-10-01 03:38:04 +0000752
753 // --------------------------------------------------------------------
754
755 /**
756 * Determine if a particular field exists
757 * @access public
758 * @param string
759 * @param string
760 * @return boolean
761 */
762 function field_exists($field_name, $table_name)
763 {
764 return ( ! in_array($field_name, $this->list_fields($table_name))) ? FALSE : TRUE;
765 }
admin6871d952006-10-04 00:36:18 +0000766
admin3dd978f2006-09-30 19:24:45 +0000767 // --------------------------------------------------------------------
768
769 /**
770 * DEPRECATED - use list_fields()
771 */
admin6871d952006-10-04 00:36:18 +0000772 function field_names($table = '')
773 {
774 return $this->list_fields($table);
775 }
admin9cd4e8e2006-09-25 23:26:25 +0000776
777 // --------------------------------------------------------------------
778
779 /**
780 * Returns an object with field data
781 *
782 * @access public
783 * @param string the table name
784 * @return object
785 */
786 function field_data($table = '')
787 {
admin6871d952006-10-04 00:36:18 +0000788 if ($table == '')
789 {
admin9cd4e8e2006-09-25 23:26:25 +0000790 if ($this->db_debug)
791 {
792 return $this->display_error('db_field_param_missing');
793 }
794 return FALSE;
admin6871d952006-10-04 00:36:18 +0000795 }
796
admin9cd4e8e2006-09-25 23:26:25 +0000797 $query = $this->query($this->_field_data($this->dbprefix.$table));
798 return $query->field_data();
799 }
800
adminbb1d4392006-09-24 20:14:38 +0000801 // --------------------------------------------------------------------
802
803 /**
804 * Generate an insert string
805 *
806 * @access public
807 * @param string the table upon which the query will be performed
808 * @param array an associative array data of key/values
809 * @return string
810 */
811 function insert_string($table, $data)
812 {
admin6871d952006-10-04 00:36:18 +0000813 $fields = array();
adminbb1d4392006-09-24 20:14:38 +0000814 $values = array();
815
816 foreach($data as $key => $val)
817 {
818 $fields[] = $key;
819 $values[] = $this->escape($val);
820 }
821
822 return $this->_insert($this->dbprefix.$table, $fields, $values);
823 }
824
825 // --------------------------------------------------------------------
826
827 /**
828 * Generate an update string
829 *
830 * @access public
831 * @param string the table upon which the query will be performed
832 * @param array an associative array data of key/values
833 * @param mixed the "where" statement
834 * @return string
835 */
836 function update_string($table, $data, $where)
837 {
838 if ($where == '')
839 return false;
840
841 $fields = array();
842 foreach($data as $key => $val)
843 {
844 $fields[$key] = $this->escape($val);
845 }
846
847 if ( ! is_array($where))
848 {
849 $dest = array($where);
850 }
851 else
852 {
853 $dest = array();
854 foreach ($where as $key => $val)
855 {
856 $prefix = (count($dest) == 0) ? '' : ' AND ';
857
858 if ($val != '')
859 {
860 if ( ! $this->_has_operator($key))
861 {
862 $key .= ' =';
863 }
864
865 $val = ' '.$this->escape($val);
866 }
867
868 $dest[] = $prefix.$key.$val;
869 }
870 }
871
872 return $this->_update($this->dbprefix.$table, $fields, $dest);
admin6871d952006-10-04 00:36:18 +0000873 }
admin7b613c72006-09-24 18:05:17 +0000874
875 // --------------------------------------------------------------------
876
877 /**
878 * Enables a native PHP function to be run, using a platform agnostic wrapper.
879 *
880 * @access public
881 * @param string the function name
882 * @param mixed any parameters needed by the function
883 * @return mixed
884 */
885 function call_function($function)
886 {
887 $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_';
888
889 if (FALSE === strpos($driver, $function))
890 {
891 $function = $driver.$function;
892 }
893
894 if ( ! function_exists($function))
895 {
896 if ($this->db_debug)
897 {
898 return $this->display_error('db_unsupported_function');
899 }
900 return FALSE;
901 }
902 else
903 {
adminee54c112006-09-28 17:13:38 +0000904 $args = (func_num_args() > 1) ? array_splice(func_get_args(), 1) : null;
905
admin7b613c72006-09-24 18:05:17 +0000906 return call_user_func_array($function, $args);
907 }
908 }
adminc5f7fa32006-10-06 02:10:23 +0000909
910 // --------------------------------------------------------------------
911
912 /**
913 * Set Cache Directory Path
914 *
915 * @access public
916 * @param string the path to the cache directory
917 * @return void
918 */
919 function cache_set_path($path = '')
920 {
921 $this->cachedir = $path;
922 }
923
admine8f6eb62006-10-02 06:46:16 +0000924 // --------------------------------------------------------------------
925
926 /**
927 * Enable Query Caching
928 *
929 * @access public
930 * @return void
931 */
932 function cache_on()
933 {
adminc2e3cd72006-10-05 04:22:30 +0000934 return $this->cache_on = TRUE;
admine8f6eb62006-10-02 06:46:16 +0000935 }
936
937 // --------------------------------------------------------------------
938
939 /**
940 * Disable Query Caching
941 *
942 * @access public
943 * @return void
944 */
945 function cache_off()
946 {
adminc2e3cd72006-10-05 04:22:30 +0000947 return $this->cache_on = 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 */
adminc5f7fa32006-10-06 02:10:23 +0000959 function cache_delete()
adminfa708172006-10-04 18:42:42 +0000960 {
adminc5f7fa32006-10-06 02:10:23 +0000961 if ( ! $this->_cache_init())
962 {
963 return FALSE;
964 }
965 return $this->CACHE->delete();
966 }
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
1015 *
1016 * @access public
1017 * @return void
1018 */
admin6871d952006-10-04 00:36:18 +00001019 function close()
1020 {
1021 if (is_resource($this->conn_id))
1022 {
1023 $this->_close($this->conn_id);
admin7b613c72006-09-24 18:05:17 +00001024 }
1025 $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
1032 *
1033 * @access public
1034 * @param string the error message
1035 * @param string any "swap" values
1036 * @param boolean whether to localize the message
1037 * @return string sends the application/errror_db.php template
1038 */
admin6871d952006-10-04 00:36:18 +00001039 function display_error($error = '', $swap = '', $native = FALSE)
1040 {
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
admin6871d952006-10-04 00:36:18 +00001064 }
admin7b613c72006-09-24 18:05:17 +00001065
1066}
1067
1068?>