blob: 966fd3ad5c63a96cc5c4ac3cf65bb145cc603f8c [file] [log] [blame]
Derek Allardd2df9bc2007-04-15 17:41:17 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
Derek Allard3d879d52008-01-18 19:41:32 +00008 * @author ExpressionEngine Dev Team
Derek Allardd2df9bc2007-04-15 17:41:17 +00009 * @copyright Copyright (c) 2006, EllisLab, Inc.
Derek Jones7a9193a2008-01-21 18:39:20 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
Derek Allardd2df9bc2007-04-15 17:41:17 +000012 * @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
Derek Allard3d879d52008-01-18 19:41:32 +000028 * @author ExpressionEngine Dev Team
Derek Jones7a9193a2008-01-21 18:39:20 +000029 * @link http://codeigniter.com/user_guide/database/
Derek Allardd2df9bc2007-04-15 17:41:17 +000030 */
31class CI_DB_driver {
32
33 var $username;
34 var $password;
35 var $hostname;
36 var $database;
37 var $dbdriver = 'mysql';
38 var $dbprefix = '';
Derek Allard39b622d2008-01-16 21:10:09 +000039 var $autoinit = TRUE; // Whether to automatically initialize the DB
40 var $swap_pre = '';
Derek Allardd2df9bc2007-04-15 17:41:17 +000041 var $port = '';
42 var $pconnect = FALSE;
43 var $conn_id = FALSE;
44 var $result_id = FALSE;
45 var $db_debug = FALSE;
46 var $benchmark = 0;
47 var $query_count = 0;
48 var $bind_marker = '?';
Rick Ellis40990462007-07-17 21:40:44 +000049 var $save_queries = TRUE;
Derek Allardd2df9bc2007-04-15 17:41:17 +000050 var $queries = array();
Derek Jones56e9fa52008-01-23 17:26:37 +000051 var $query_times = array();
Derek Allardd2df9bc2007-04-15 17:41:17 +000052 var $data_cache = array();
53 var $trans_enabled = TRUE;
54 var $_trans_depth = 0;
Rick Ellis28239ad2007-06-11 04:26:39 +000055 var $_trans_status = TRUE; // Used with transactions to determine if a rollback should occur
Derek Allardd2df9bc2007-04-15 17:41:17 +000056 var $cache_on = FALSE;
57 var $cachedir = '';
58 var $cache_autodel = FALSE;
59 var $CACHE; // The cache class object
60
61
62 // These are use with Oracle
63 var $stmt_id;
64 var $curs_id;
65 var $limit_used;
66
67
68
69 /**
70 * Constructor. Accepts one parameter containing the database
71 * connection settings.
72 *
73 * Database settings can be passed as discreet
74 * parameters or as a data source name in the first
75 * parameter. DSNs must have this prototype:
76 * $dsn = 'driver://username:password@hostname/database';
77 *
78 * @param mixed. Can be an array or a DSN string
79 */
80 function CI_DB_driver($params)
81 {
Derek Allardd2df9bc2007-04-15 17:41:17 +000082 if (is_array($params))
83 {
Derek Allard39b622d2008-01-16 21:10:09 +000084 foreach ($params as $key => $val)
Derek Allardd2df9bc2007-04-15 17:41:17 +000085 {
Derek Allard39b622d2008-01-16 21:10:09 +000086 $this->$key = $val;
Derek Allardd2df9bc2007-04-15 17:41:17 +000087 }
88 }
89 elseif (strpos($params, '://'))
90 {
91 if (FALSE === ($dsn = @parse_url($params)))
92 {
93 log_message('error', 'Invalid DB Connection String');
94
95 if ($this->db_debug)
96 {
97 return $this->display_error('db_invalid_connection_str');
98 }
99 return FALSE;
100 }
101
102 $this->hostname = ( ! isset($dsn['host'])) ? '' : rawurldecode($dsn['host']);
103 $this->username = ( ! isset($dsn['user'])) ? '' : rawurldecode($dsn['user']);
104 $this->password = ( ! isset($dsn['pass'])) ? '' : rawurldecode($dsn['pass']);
105 $this->database = ( ! isset($dsn['path'])) ? '' : rawurldecode(substr($dsn['path'], 1));
106 }
Derek Allard39b622d2008-01-16 21:10:09 +0000107
108 log_message('debug', 'Database Driver Class Initialized');
109 }
110
111 // --------------------------------------------------------------------
112
113 /**
114 * Initialize Database Settings
115 *
116 * @access private Called by the constructor
117 * @param mixed
118 * @return void
119 */
120 function initialize($create_db = FALSE)
121 {
Derek Allardd2df9bc2007-04-15 17:41:17 +0000122 // If an existing DB connection resource is supplied
123 // there is no need to connect and select the database
124 if (is_resource($this->conn_id))
125 {
126 return TRUE;
127 }
128
129 // Connect to the database
130 $this->conn_id = ($this->pconnect == FALSE) ? $this->db_connect() : $this->db_pconnect();
131
132 // No connection? Throw an error
133 if ( ! $this->conn_id)
134 {
135 log_message('error', 'Unable to connect to the database');
136
137 if ($this->db_debug)
138 {
139 $this->display_error('db_unable_to_connect');
140 }
141 return FALSE;
142 }
143
144 // Select the database
145 if ($this->database != '')
146 {
147 if ( ! $this->db_select())
148 {
Derek Allard39b622d2008-01-16 21:10:09 +0000149 // Should we attempt to create the database?
150 if ($create_db == TRUE)
151 {
152 // Load the DB utility class
153 $CI =& get_instance();
154 $CI->load->dbutil();
155
156 // Create the DB
157 if ( ! $CI->dbutil->create_database($this->database))
158 {
159 log_message('error', 'Unable to create database: '.$this->database);
160
161 if ($this->db_debug)
162 {
163 $this->display_error('db_unable_to_create', $this->database);
164 }
165 return FALSE;
166 }
167 else
168 {
169 // In the event the DB was created we need to select it
170 if ($this->db_select())
171 {
172 if (! $this->db_set_charset($this->char_set, $this->dbcollat))
173 {
174 log_message('error', 'Unable to set database connection charset: '.$this->char_set);
175
176 if ($this->db_debug)
177 {
178 $this->display_error('db_unable_to_set_charset', $this->char_set);
179 }
180
181 return FALSE;
182 }
183
184 return TRUE;
185 }
186 }
187 }
188
Derek Allardd2df9bc2007-04-15 17:41:17 +0000189 log_message('error', 'Unable to select database: '.$this->database);
190
191 if ($this->db_debug)
192 {
193 $this->display_error('db_unable_to_select', $this->database);
194 }
195 return FALSE;
196 }
Derek Allard39b622d2008-01-16 21:10:09 +0000197
198 if (! $this->db_set_charset($this->char_set, $this->dbcollat))
199 {
200 log_message('error', 'Unable to set database connection charset: '.$this->char_set);
201
202 if ($this->db_debug)
203 {
204 $this->display_error('db_unable_to_set_charset', $this->char_set);
205 }
206
207 return FALSE;
208 }
Derek Allardd2df9bc2007-04-15 17:41:17 +0000209 }
210
211 return TRUE;
212 }
213
214 // --------------------------------------------------------------------
215
216 /**
217 * The name of the platform in use (mysql, mssql, etc...)
218 *
219 * @access public
220 * @return string
221 */
222 function platform()
223 {
224 return $this->dbdriver;
225 }
226
227 // --------------------------------------------------------------------
228
229 /**
230 * Database Version Number. Returns a string containing the
231 * version of the database being used
232 *
233 * @access public
234 * @return string
235 */
236 function version()
237 {
238 if (FALSE === ($sql = $this->_version()))
239 {
240 if ($this->db_debug)
241 {
242 return $this->display_error('db_unsupported_function');
243 }
244 return FALSE;
245 }
246
247 if ($this->dbdriver == 'oci8')
248 {
249 return $sql;
250 }
251
252 $query = $this->query($sql);
Derek Allard39b622d2008-01-16 21:10:09 +0000253 return $query->row('ver');
Derek Allardd2df9bc2007-04-15 17:41:17 +0000254 }
255
256 // --------------------------------------------------------------------
257
258 /**
259 * Execute the query
260 *
261 * Accepts an SQL string as input and returns a result object upon
262 * successful execution of a "read" type query. Returns boolean TRUE
263 * upon successful execution of a "write" type query. Returns boolean
264 * FALSE upon failure, and if the $db_debug variable is set to TRUE
265 * will raise an error.
266 *
267 * @access public
268 * @param string An SQL query string
269 * @param array An array of binding data
270 * @return mixed
271 */
272 function query($sql, $binds = FALSE, $return_object = TRUE)
273 {
274 if ($sql == '')
275 {
276 if ($this->db_debug)
277 {
278 log_message('error', 'Invalid query: '.$sql);
279 return $this->display_error('db_invalid_query');
280 }
281 return FALSE;
282 }
Derek Allard39b622d2008-01-16 21:10:09 +0000283
284 // Verify table prefix and replace if necessary
285 if ( ($this->dbprefix != '' AND $this->swap_pre != '') AND ($this->dbprefix != $this->swap_pre) )
286 {
287 $sql = preg_replace("/(\W)".$this->swap_pre."(\S+?)/", "\\1".$this->dbprefix."\\2", $sql);
288 }
Derek Allardd2df9bc2007-04-15 17:41:17 +0000289
290 // Is query caching enabled? If the query is a "read type"
291 // we will load the caching class and return the previously
292 // cached query if it exists
293 if ($this->cache_on == TRUE AND stristr($sql, 'SELECT'))
294 {
295 if ($this->_cache_init())
296 {
297 $this->load_rdriver();
298 if (FALSE !== ($cache = $this->CACHE->read($sql)))
299 {
300 return $cache;
301 }
302 }
303 }
304
305 // Compile binds if needed
306 if ($binds !== FALSE)
307 {
308 $sql = $this->compile_binds($sql, $binds);
309 }
310
311 // Save the query for debugging
Rick Ellis40990462007-07-17 21:40:44 +0000312 if ($this->save_queries == TRUE)
313 {
314 $this->queries[] = $sql;
315 }
Derek Allard39b622d2008-01-16 21:10:09 +0000316
Derek Allardd2df9bc2007-04-15 17:41:17 +0000317 // Start the Query Timer
318 $time_start = list($sm, $ss) = explode(' ', microtime());
319
320 // Run the Query
321 if (FALSE === ($this->result_id = $this->simple_query($sql)))
322 {
323 // This will trigger a rollback if transactions are being used
Rick Ellis28239ad2007-06-11 04:26:39 +0000324 $this->_trans_status = FALSE;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000325
326 if ($this->db_debug)
327 {
328 log_message('error', 'Query error: '.$this->_error_message());
329 return $this->display_error(
330 array(
331 'Error Number: '.$this->_error_number(),
332 $this->_error_message(),
333 $sql
334 )
335 );
336 }
337
Derek Allard39b622d2008-01-16 21:10:09 +0000338 return FALSE;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000339 }
340
341 // Stop and aggregate the query time results
342 $time_end = list($em, $es) = explode(' ', microtime());
343 $this->benchmark += ($em + $es) - ($sm + $ss);
344
Derek Jones56e9fa52008-01-23 17:26:37 +0000345 if ($this->save_queries == TRUE)
346 {
347 $this->query_times[] = ($em + $es) - ($sm + $ss);
348 }
349
Derek Allardd2df9bc2007-04-15 17:41:17 +0000350 // Increment the query counter
351 $this->query_count++;
352
353 // Was the query a "write" type?
354 // If so we'll simply return true
355 if ($this->is_write_type($sql) === TRUE)
356 {
357 // If caching is enabled we'll auto-cleanup any
358 // existing files related to this particular URI
359 if ($this->cache_on == TRUE AND $this->cache_autodel == TRUE AND $this->_cache_init())
360 {
361 $this->CACHE->delete();
362 }
363
364 return TRUE;
365 }
366
367 // Return TRUE if we don't need to create a result object
368 // Currently only the Oracle driver uses this when stored
369 // procedures are used
370 if ($return_object !== TRUE)
371 {
372 return TRUE;
373 }
374
375 // Load and instantiate the result driver
376
377 $driver = $this->load_rdriver();
378 $RES = new $driver();
379 $RES->conn_id = $this->conn_id;
380 $RES->result_id = $this->result_id;
Derek Allard39b622d2008-01-16 21:10:09 +0000381 $RES->num_rows = $RES->num_rows();
Derek Allard060052d2007-07-14 14:26:13 +0000382
Derek Allardd2df9bc2007-04-15 17:41:17 +0000383 if ($this->dbdriver == 'oci8')
384 {
385 $RES->stmt_id = $this->stmt_id;
386 $RES->curs_id = NULL;
387 $RES->limit_used = $this->limit_used;
388 }
Derek Allard39b622d2008-01-16 21:10:09 +0000389
Derek Allardd2df9bc2007-04-15 17:41:17 +0000390 // Is query caching enabled? If so, we'll serialize the
391 // result object and save it to a cache file.
392 if ($this->cache_on == TRUE AND $this->_cache_init())
393 {
394 // We'll create a new instance of the result object
395 // only without the platform specific driver since
396 // we can't use it with cached data (the query result
397 // resource ID won't be any good once we've cached the
398 // result object, so we'll have to compile the data
399 // and save it)
400 $CR = new CI_DB_result();
401 $CR->num_rows = $RES->num_rows();
402 $CR->result_object = $RES->result_object();
403 $CR->result_array = $RES->result_array();
404
405 // Reset these since cached objects can not utilize resource IDs.
406 $CR->conn_id = NULL;
407 $CR->result_id = NULL;
408
409 $this->CACHE->write($sql, $CR);
410 }
411
412 return $RES;
413 }
414
415 // --------------------------------------------------------------------
416
417 /**
418 * Load the result drivers
419 *
420 * @access public
421 * @return string the name of the result class
422 */
423 function load_rdriver()
424 {
425 $driver = 'CI_DB_'.$this->dbdriver.'_result';
426
427 if ( ! class_exists($driver))
428 {
429 include_once(BASEPATH.'database/DB_result'.EXT);
430 include_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result'.EXT);
431 }
432
433 return $driver;
434 }
435
436 // --------------------------------------------------------------------
437
438 /**
439 * Simple Query
440 * This is a simplified version of the query() function. Internally
441 * we only use it when running transaction commands since they do
442 * not require all the features of the main query() function.
443 *
444 * @access public
445 * @param string the sql query
446 * @return mixed
447 */
448 function simple_query($sql)
449 {
450 if ( ! $this->conn_id)
451 {
452 $this->initialize();
453 }
454
455 return $this->_execute($sql);
456 }
457
458 // --------------------------------------------------------------------
459
460 /**
461 * Disable Transactions
462 * This permits transactions to be disabled at run-time.
463 *
464 * @access public
465 * @return void
466 */
467 function trans_off()
468 {
469 $this->trans_enabled = FALSE;
470 }
471
472 // --------------------------------------------------------------------
473
474 /**
475 * Start Transaction
476 *
477 * @access public
478 * @return void
479 */
480 function trans_start($test_mode = FALSE)
481 {
482 if ( ! $this->trans_enabled)
483 {
484 return FALSE;
485 }
486
487 // When transactions are nested we only begin/commit/rollback the outermost ones
488 if ($this->_trans_depth > 0)
489 {
490 $this->_trans_depth += 1;
491 return;
492 }
493
494 $this->trans_begin($test_mode);
495 }
496
497 // --------------------------------------------------------------------
498
499 /**
500 * Complete Transaction
501 *
502 * @access public
503 * @return bool
504 */
505 function trans_complete()
506 {
507 if ( ! $this->trans_enabled)
508 {
509 return FALSE;
510 }
511
512 // When transactions are nested we only begin/commit/rollback the outermost ones
513 if ($this->_trans_depth > 1)
514 {
515 $this->_trans_depth -= 1;
516 return TRUE;
517 }
518
519 // The query() function will set this flag to TRUE in the event that a query failed
Rick Ellis28239ad2007-06-11 04:26:39 +0000520 if ($this->_trans_status === FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000521 {
522 $this->trans_rollback();
523
524 if ($this->db_debug)
525 {
526 return $this->display_error('db_transaction_failure');
527 }
528 return FALSE;
529 }
530
531 $this->trans_commit();
532 return TRUE;
533 }
534
535 // --------------------------------------------------------------------
536
537 /**
538 * Lets you retrieve the transaction flag to determine if it has failed
539 *
540 * @access public
541 * @return bool
542 */
543 function trans_status()
544 {
Rick Ellis28239ad2007-06-11 04:26:39 +0000545 return $this->_trans_status;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000546 }
547
548 // --------------------------------------------------------------------
549
550 /**
551 * Compile Bindings
552 *
553 * @access public
554 * @param string the sql statement
555 * @param array an array of bind data
556 * @return string
557 */
558 function compile_binds($sql, $binds)
559 {
560 if (FALSE === strpos($sql, $this->bind_marker))
561 {
562 return $sql;
563 }
564
565 if ( ! is_array($binds))
566 {
567 $binds = array($binds);
568 }
569
570 foreach ($binds as $val)
571 {
572 $val = $this->escape($val);
573
574 // Just in case the replacement string contains the bind
575 // character we'll temporarily replace it with a marker
576 $val = str_replace($this->bind_marker, '{%bind_marker%}', $val);
577 $sql = preg_replace("#".preg_quote($this->bind_marker, '#')."#", str_replace('$', '\$', $val), $sql, 1);
578 }
579
580 return str_replace('{%bind_marker%}', $this->bind_marker, $sql);
581 }
582
583 // --------------------------------------------------------------------
584
585 /**
586 * Determines if a query is a "write" type.
587 *
588 * @access public
589 * @param string An SQL query string
590 * @return boolean
591 */
592 function is_write_type($sql)
593 {
594 if ( ! preg_match('/^\s*"?(INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|LOAD DATA|COPY|ALTER|GRANT|REVOKE|LOCK|UNLOCK)\s+/i', $sql))
595 {
596 return FALSE;
597 }
598 return TRUE;
599 }
600
601 // --------------------------------------------------------------------
602
603 /**
604 * Calculate the aggregate query elapsed time
605 *
606 * @access public
607 * @param integer The number of decimal places
608 * @return integer
609 */
610 function elapsed_time($decimals = 6)
611 {
612 return number_format($this->benchmark, $decimals);
613 }
614
615 // --------------------------------------------------------------------
616
617 /**
618 * Returns the total number of queries
619 *
620 * @access public
621 * @return integer
622 */
623 function total_queries()
624 {
625 return $this->query_count;
626 }
627
628 // --------------------------------------------------------------------
629
630 /**
631 * Returns the last query that was executed
632 *
633 * @access public
634 * @return void
635 */
636 function last_query()
637 {
638 return end($this->queries);
639 }
640
641 // --------------------------------------------------------------------
642
643 /**
Derek Allard39b622d2008-01-16 21:10:09 +0000644 * Protect Identifiers
645 *
646 * This function adds backticks if appropriate based on db type
647 *
648 * @access private
649 * @param mixed the item to escape
650 * @param boolean only affect the first word
651 * @return mixed the item with backticks
652 */
653 function protect_identifiers($item, $first_word_only = FALSE)
654 {
Derek Allard1a704ce2008-01-27 15:03:06 +0000655 return $this->_protect_identifiers($item, $first_word_only);
Derek Allard39b622d2008-01-16 21:10:09 +0000656 }
657
658 // --------------------------------------------------------------------
659
660 /**
Derek Allardd2df9bc2007-04-15 17:41:17 +0000661 * "Smart" Escape String
662 *
663 * Escapes data based on type
664 * Sets boolean and null types
665 *
666 * @access public
667 * @param string
668 * @return integer
669 */
670 function escape($str)
671 {
672 switch (gettype($str))
673 {
674 case 'string' : $str = "'".$this->escape_str($str)."'";
675 break;
676 case 'boolean' : $str = ($str === FALSE) ? 0 : 1;
677 break;
678 default : $str = ($str === NULL) ? 'NULL' : $str;
679 break;
680 }
681
682 return $str;
683 }
684
685 // --------------------------------------------------------------------
686
687 /**
688 * Primary
689 *
690 * Retrieves the primary key. It assumes that the row in the first
691 * position is the primary key
692 *
693 * @access public
694 * @param string the table name
695 * @return string
696 */
697 function primary($table = '')
698 {
699 $fields = $this->list_fields($table);
700
701 if ( ! is_array($fields))
702 {
703 return FALSE;
704 }
705
706 return current($fields);
707 }
708
709 // --------------------------------------------------------------------
710
711 /**
712 * Returns an array of table names
713 *
714 * @access public
715 * @return array
716 */
Derek Allard39b622d2008-01-16 21:10:09 +0000717 function list_tables($constrain_by_prefix = FALSE)
Derek Allardd2df9bc2007-04-15 17:41:17 +0000718 {
719 // Is there a cached result?
720 if (isset($this->data_cache['table_names']))
721 {
722 return $this->data_cache['table_names'];
723 }
724
Derek Allard39b622d2008-01-16 21:10:09 +0000725 if (FALSE === ($sql = $this->_list_tables($constrain_by_prefix)))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000726 {
727 if ($this->db_debug)
728 {
729 return $this->display_error('db_unsupported_function');
730 }
731 return FALSE;
732 }
733
734 $retval = array();
735 $query = $this->query($sql);
736
737 if ($query->num_rows() > 0)
738 {
739 foreach($query->result_array() as $row)
740 {
741 if (isset($row['TABLE_NAME']))
742 {
743 $retval[] = $row['TABLE_NAME'];
744 }
745 else
746 {
747 $retval[] = array_shift($row);
748 }
749 }
750 }
751
752 $this->data_cache['table_names'] = $retval;
753 return $this->data_cache['table_names'];
754 }
755
756 // --------------------------------------------------------------------
757
758 /**
759 * Determine if a particular table exists
760 * @access public
761 * @return boolean
762 */
763 function table_exists($table_name)
764 {
Derek Allard39b622d2008-01-16 21:10:09 +0000765 return ( ! in_array($this->prep_tablename($table_name), $this->list_tables())) ? FALSE : TRUE;
Derek Allardd2df9bc2007-04-15 17:41:17 +0000766 }
767
768 // --------------------------------------------------------------------
769
770 /**
771 * Fetch MySQL Field Names
772 *
773 * @access public
774 * @param string the table name
775 * @return array
776 */
777 function list_fields($table = '')
778 {
779 // Is there a cached result?
780 if (isset($this->data_cache['field_names'][$table]))
781 {
782 return $this->data_cache['field_names'][$table];
783 }
784
785 if ($table == '')
786 {
787 if ($this->db_debug)
788 {
789 return $this->display_error('db_field_param_missing');
790 }
791 return FALSE;
792 }
793
Derek Allard39b622d2008-01-16 21:10:09 +0000794 if (FALSE === ($sql = $this->_list_columns($this->prep_tablename($table))))
Derek Allardd2df9bc2007-04-15 17:41:17 +0000795 {
796 if ($this->db_debug)
797 {
798 return $this->display_error('db_unsupported_function');
799 }
800 return FALSE;
801 }
802
803 $query = $this->query($sql);
804
805 $retval = array();
806 foreach($query->result_array() as $row)
807 {
808 if (isset($row['COLUMN_NAME']))
809 {
810 $retval[] = $row['COLUMN_NAME'];
811 }
812 else
813 {
814 $retval[] = current($row);
815 }
816 }
817
818 $this->data_cache['field_names'][$table] = $retval;
819 return $this->data_cache['field_names'][$table];
820 }
821
822 // --------------------------------------------------------------------
823
824 /**
825 * Determine if a particular field exists
826 * @access public
827 * @param string
828 * @param string
829 * @return boolean
830 */
831 function field_exists($field_name, $table_name)
832 {
833 return ( ! in_array($field_name, $this->list_fields($table_name))) ? FALSE : TRUE;
834 }
835
836 // --------------------------------------------------------------------
837
838 /**
839 * DEPRECATED - use list_fields()
840 */
841 function field_names($table = '')
842 {
843 return $this->list_fields($table);
844 }
845
846 // --------------------------------------------------------------------
847
848 /**
849 * Returns an object with field data
850 *
851 * @access public
852 * @param string the table name
853 * @return object
854 */
855 function field_data($table = '')
856 {
857 if ($table == '')
858 {
859 if ($this->db_debug)
860 {
861 return $this->display_error('db_field_param_missing');
862 }
863 return FALSE;
864 }
865
Derek Allard39b622d2008-01-16 21:10:09 +0000866 $query = $this->query($this->_field_data($this->prep_tablename($table)));
Derek Allardd2df9bc2007-04-15 17:41:17 +0000867 return $query->field_data();
868 }
869
870 // --------------------------------------------------------------------
871
872 /**
873 * Generate an insert string
874 *
875 * @access public
876 * @param string the table upon which the query will be performed
877 * @param array an associative array data of key/values
878 * @return string
879 */
880 function insert_string($table, $data)
881 {
882 $fields = array();
883 $values = array();
884
885 foreach($data as $key => $val)
886 {
887 $fields[] = $key;
888 $values[] = $this->escape($val);
889 }
Derek Allard39b622d2008-01-16 21:10:09 +0000890
891
892 return $this->_insert($this->prep_tablename($table), $fields, $values);
893 }
Derek Allardd2df9bc2007-04-15 17:41:17 +0000894
895 // --------------------------------------------------------------------
896
897 /**
898 * Generate an update string
899 *
900 * @access public
901 * @param string the table upon which the query will be performed
902 * @param array an associative array data of key/values
903 * @param mixed the "where" statement
904 * @return string
905 */
906 function update_string($table, $data, $where)
907 {
908 if ($where == '')
909 return false;
910
911 $fields = array();
912 foreach($data as $key => $val)
913 {
914 $fields[$key] = $this->escape($val);
915 }
916
917 if ( ! is_array($where))
918 {
919 $dest = array($where);
920 }
921 else
922 {
923 $dest = array();
924 foreach ($where as $key => $val)
925 {
926 $prefix = (count($dest) == 0) ? '' : ' AND ';
927
Derek Allard39b622d2008-01-16 21:10:09 +0000928 if ($val !== '')
Derek Allardd2df9bc2007-04-15 17:41:17 +0000929 {
930 if ( ! $this->_has_operator($key))
931 {
932 $key .= ' =';
933 }
934
935 $val = ' '.$this->escape($val);
936 }
937
938 $dest[] = $prefix.$key.$val;
939 }
940 }
941
Derek Allard39b622d2008-01-16 21:10:09 +0000942 return $this->_update($this->prep_tablename($table), $fields, $dest);
Derek Allardd2df9bc2007-04-15 17:41:17 +0000943 }
944
945 // --------------------------------------------------------------------
946
947 /**
Derek Allard39b622d2008-01-16 21:10:09 +0000948 * Prep the table name - simply adds the table prefix if needed
949 *
950 * @access public
951 * @param string the table name
952 * @return string
953 */
954 function prep_tablename($table = '')
955 {
956 // Do we need to add the table prefix?
957 if ($this->dbprefix != '')
958 {
959 if (substr($table, 0, strlen($this->dbprefix)) != $this->dbprefix)
960 {
961 $table = $this->dbprefix.$table;
962 }
963 }
964
965 return $table;
966 }
967
968 // --------------------------------------------------------------------
969
970 /**
Derek Allardd2df9bc2007-04-15 17:41:17 +0000971 * Enables a native PHP function to be run, using a platform agnostic wrapper.
972 *
973 * @access public
974 * @param string the function name
975 * @param mixed any parameters needed by the function
976 * @return mixed
977 */
978 function call_function($function)
979 {
980 $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_';
981
982 if (FALSE === strpos($driver, $function))
983 {
984 $function = $driver.$function;
985 }
986
987 if ( ! function_exists($function))
988 {
989 if ($this->db_debug)
990 {
991 return $this->display_error('db_unsupported_function');
992 }
993 return FALSE;
994 }
995 else
996 {
997 $args = (func_num_args() > 1) ? array_splice(func_get_args(), 1) : null;
998
999 return call_user_func_array($function, $args);
1000 }
1001 }
1002
1003 // --------------------------------------------------------------------
1004
1005 /**
1006 * Set Cache Directory Path
1007 *
1008 * @access public
1009 * @param string the path to the cache directory
1010 * @return void
1011 */
1012 function cache_set_path($path = '')
1013 {
1014 $this->cachedir = $path;
1015 }
1016
1017 // --------------------------------------------------------------------
1018
1019 /**
1020 * Enable Query Caching
1021 *
1022 * @access public
1023 * @return void
1024 */
1025 function cache_on()
1026 {
1027 $this->cache_on = TRUE;
1028 return TRUE;
1029 }
1030
1031 // --------------------------------------------------------------------
1032
1033 /**
1034 * Disable Query Caching
1035 *
1036 * @access public
1037 * @return void
1038 */
1039 function cache_off()
1040 {
1041 $this->cache_on = FALSE;
1042 return FALSE;
1043 }
1044
1045
1046 // --------------------------------------------------------------------
1047
1048 /**
1049 * Delete the cache files associated with a particular URI
1050 *
1051 * @access public
1052 * @return void
1053 */
1054 function cache_delete($segment_one = '', $segment_two = '')
1055 {
1056 if ( ! $this->_cache_init())
1057 {
1058 return FALSE;
1059 }
1060 return $this->CACHE->delete($segment_one, $segment_two);
1061 }
1062
1063 // --------------------------------------------------------------------
1064
1065 /**
1066 * Delete All cache files
1067 *
1068 * @access public
1069 * @return void
1070 */
1071 function cache_delete_all()
1072 {
1073 if ( ! $this->_cache_init())
1074 {
1075 return FALSE;
1076 }
1077
1078 return $this->CACHE->delete_all();
1079 }
1080
1081 // --------------------------------------------------------------------
1082
1083 /**
1084 * Initialize the Cache Class
1085 *
1086 * @access private
1087 * @return void
1088 */
1089 function _cache_init()
1090 {
1091 if (is_object($this->CACHE) AND class_exists('CI_DB_Cache'))
1092 {
1093 return TRUE;
1094 }
1095
1096 if ( ! @include(BASEPATH.'database/DB_cache'.EXT))
1097 {
1098 return $this->cache_off();
1099 }
1100
1101 $this->CACHE = new CI_DB_Cache;
1102 return TRUE;
1103 }
1104
Derek Allardd2df9bc2007-04-15 17:41:17 +00001105 // --------------------------------------------------------------------
1106
1107 /**
1108 * Close DB Connection
1109 *
1110 * @access public
1111 * @return void
1112 */
1113 function close()
1114 {
1115 if (is_resource($this->conn_id))
1116 {
1117 $this->_close($this->conn_id);
1118 }
1119 $this->conn_id = FALSE;
1120 }
1121
1122 // --------------------------------------------------------------------
1123
1124 /**
1125 * Display an error message
1126 *
1127 * @access public
1128 * @param string the error message
1129 * @param string any "swap" values
1130 * @param boolean whether to localize the message
1131 * @return string sends the application/error_db.php template
1132 */
1133 function display_error($error = '', $swap = '', $native = FALSE)
1134 {
Derek Allard39b622d2008-01-16 21:10:09 +00001135// $LANG = new CI_Lang();
Derek Allardd2df9bc2007-04-15 17:41:17 +00001136 $LANG = new CI_Language();
1137 $LANG->load('db');
1138
Derek Allard1a704ce2008-01-27 15:03:06 +00001139 $heading = 'Database Error';
Derek Allardd2df9bc2007-04-15 17:41:17 +00001140
1141 if ($native == TRUE)
1142 {
1143 $message = $error;
1144 }
1145 else
1146 {
1147 $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error;
1148 }
1149
1150 if ( ! class_exists('CI_Exceptions'))
1151 {
Derek Allard39b622d2008-01-16 21:10:09 +00001152// include(BASEPATH.'core/Exceptions'.EXT);
Derek Allardd2df9bc2007-04-15 17:41:17 +00001153 include(BASEPATH.'libraries/Exceptions'.EXT);
1154 }
1155
1156 $error = new CI_Exceptions();
1157 echo $error->show_error('An Error Was Encountered', $message, 'error_db');
1158 exit;
1159 }
1160
1161}
1162
admin7b613c72006-09-24 18:05:17 +00001163?>