2 /*------------------------------------------------------------
3 * CarbonPHP framework (C) Tom Bell
4 * http://tombell.org.uk
5 *------------------------------------------------------------*/
7 if (!defined('CARBON_PATH'))
9 exit('Direct script access is not allowed.');
12 class Carbon_Database_driver
18 public $dbdriver = 'mysql';
19 public $dbprefix = '';
20 public $autoinit = true;
21 public $swap_pre = '';
23 public $pconnect = false;
24 public $conn_id = false;
25 public $result_id = false;
26 public $db_debug = false;
27 public $benchmark = 0;
28 public $query_count = 0;
29 public $bind_marker = '?';
30 public $save_queries = true;
31 public $queries = array();
32 public $query_times = array();
33 public $data_cache = array();
34 public $trans_enabled = true;
35 public $_trans_depth = 0;
36 public $_trans_status = true;
37 public $cache_on = false;
38 public $cachedir = '';
39 public $cache_autodel = false;
46 public function __construct($params)
48 if (is_array($params))
50 foreach ($params as $key => $value)
56 log_message('debug', 'Database_driver.php - Carbon_Database_driver class initialised');
59 public function initialise($create_db = false)
61 if (is_resource($this->conn_id
))
66 $this->conn_id
= ($this->pconnect
== false) ?
$this->database_connect() : $this->database_pconnect();
70 log_message('error', 'Database_driver.php - Unable to connect to the database');
74 $this->display_error('database_unable_to_connect');
80 if ($this->database
!= '')
82 if (!$this->database_select())
84 if ($create_db == true)
86 $carbon =& get_instance();
87 $carbon->load
->dbutil();
89 if (!$carbon->dbutil
->create_database($this->database
))
91 log_message('error', 'Database_driver.php - Unable to create the database: ' . $this->database
);
95 $this->display_error('database_unable_to_create', $this->database
);
102 if ($this->database_select())
104 if (!$this->database_set_charset($this->char_set
, $this->dbcollat
))
106 log_message('error', 'Database_driver.php - Unable to set the database connection charset: ' . $this->char_set
);
110 $this->display_error('database_unable_to_set_charset', $this->char_set
);
121 log_message('error', 'Database_driver.php - Unable to select the database: ' . $this->database
);
125 $this->display_error('database_unable_to_select', $this->database
);
131 if (!$this->database_set_charset($this->char_set
, $this->dbcollat
))
133 log_message('error', 'Database_driver.php - Unable to set the database connection charset: ' . $this->char_set
);
137 $this->display_error('database_unable_to_set_charset', $this->char_set
);
147 public function platform()
149 return $this->dbdriver
;
152 public function version()
154 $sql = $this->database_version();
160 return $this->display_error('database_unsupported_function');
166 if ($this->dbdriver
== 'oci8')
171 $query = $this->query($sql);
172 return $row->row('ver');
175 public function query($sql, $binds = false, $return_object = true)
179 log_message('error', 'Database_driver.php - Invalid query: ' . $sql);
183 return $this->display_error('database_invalid_query');
189 if (($this->dbprefix
!= '' && $this->swap_pre
!= '') && ($this->dbprefix
!= $this->swap_pre
))
191 $sql = preg_replace("/(\W)" . $this->swap_pre
. "(\S+?)/", "\\1" . $this->dbprefix
. "\\2", $sql);
194 if ($this->cache_on
== true && stristr($sql, 'SELECT'))
196 if ($this->database_cache_init())
198 $this->load_result_driver();
199 $cache = $this->cache
->read($sql);
201 if ($cache !== false)
208 if ($binds !== false)
210 $sql = $this->compile_binds($sql, $binds);
213 if ($this->save_queries
== true)
215 $this->queries
[] = $sql;
218 $time_start = list($sm, $ss) = explode(' ', microtime());
219 $this->result_id
= $this->simple_query($sql);
221 if ($this->result_id
=== false)
223 $this->_trans_status
= false;
225 log_message('error', 'Database_driver.php - Query error: ' . $this->database_error_message());
229 return $this->display_error(array('Error number: ' . $this->database_error_number(), $this->database_error_message(), $sql));
235 $time_end = list($em, $es) = explode(' ', microtime());
236 $this->benchmark +
= ($em +
$es) - ($sm +
$ss);
238 if ($this->save_queries
== true)
240 $this->query_times
[] = ($em +
$es) - ($sm +
$ss);
243 $this->query_count++
;
245 if ($this->is_write_type($sql) === true)
247 if ($this->cache_on
== true && $this->cache_autodel
== true && $this->database_cache_init())
249 $this->cache
->delete();
255 if ($return_object !== true)
260 $driver = $this->load_result_driver();
262 $result = new $driver();
264 $result->conn_id
= $this->conn_id
;
265 $result->result_id
= $this->result_id
;
266 $result->num_rows
= $result->num_rows();
268 if ($this->dbdriver
== 'oci8')
270 $result->stmt_id
= $this->stmt_id
;
271 $result->curs_id
= $this->curs_id
;
272 $result->limit_used
= $this->limit_used
;
275 if ($this->cache_on
== true && $this->database_cache_init())
277 $cache_result = new Carbon_Database_result();
279 $cache_result->num_rows
= $result->num_rows();
280 $cache_result->result_object
= $result->result_object();
281 $cache_result->result_array
= $result->result_array();
283 $cache_result->conn_id
= null;
284 $cache_result->result_id
= null;
286 $this->cache
->write($sql, $cache_result);
292 public function load_result_driver()
294 $driver = 'Carbon_Database_' . $this->dbdriver
. '_result';
296 if (!class_exists($driver))
298 include_once(CARBON_PATH
. 'database/Database_result' . FILE_EXT
);
299 include_once(CARBON_PATH
. 'database/drivers/' . $this->dbdriver
. '/' . $this->dbdriver
. '_result' . FILE_EXT
);
305 public function simple_query($sql)
312 return $this->database_execute($sql);
315 public function trans_off()
317 $this->trans_enabled
= false;
320 public function trans_start($test_mode = false)
322 if (!$this->trans_enabled
)
327 if ($this->_trans_depth
> 0)
329 $this->_trans_depth +
= 1;
333 $this->trans_begin($test_mode);
336 public function trans_complete()
338 if (!$this->trans_enabled
)
343 if ($this->_trans_depth
> 1)
345 $this->_trans_depth
-= 1;
349 if ($this->_trans_status
=== false)
351 $this->trans_rollback();
355 return $this->display_error('database_transaction_failure');
361 $this->trans_commit();
365 public function trans_status()
367 return $this->_trans_status
;
370 public function compile_binds($sql, $binds)
372 if (strpos($sql, $this->bind_marker
) === false)
377 if (!is_array($binds))
379 $binds = array($binds);
382 $segments = explode($this->bind_marker
, $sql);
384 if (count($binds) >= count($segments))
386 $binds = array_slice($binds, 0, count($segments) - 1);
389 $result = $segments[0];
392 foreach ($binds as $bind)
394 $result .= $this->escape($bind);
395 $result .= $segments[++
$i];
401 public function is_write_type($sql)
403 if (!preg_match('/^\s*"?(INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|LOAD DATA|COPY|ALTER|GRANT|REVOKE|LOCK|UNLOCK)\s+/i', $sql))
411 public function elapsed_time($precision = 6)
413 return number_format($this->benchmark
, $precision);
416 public function total_queries()
418 return $this->query_count
;
421 public function last_query()
423 return end($this->queries
);
426 public function protect_identifiers($item, $first_word_only = false)
428 return $this->database_protect_identifiers($item, $first_word_only);
431 public function escape($string)
434 if (is_numeric ($string))
438 else if (is_string ($string))
440 return "'" . $this->escape_string ($string) . "'";
442 else if (is_bool ($string))
444 return ($string === false) ?
0 : 1;
452 public function primary($table = '')
454 $fields = $this->list_fields($table);
456 if (!is_array($fields))
461 return current($fields);
464 public function list_tables($constrain_by_prefix = false)
466 if (isset($this->data_cache
['table_names']))
468 return $this->data_cache
['table_names'];
471 $sql = $this->database_list_tables($constrain_by_prefix);
477 return $this->display_error('database_unsupported_function');
484 $query = $this->query($sql);
486 if ($query->num_rows() > 0)
488 foreach ($query->result_array() as $row)
490 if (isset($row['TABLE_NAME']))
492 $retval[] = $row['TABLE_NAME'];
496 $retval[] = array_shift($row);
501 $this->data_cache
['table_names'] = $retval;
503 return $this->data_cache
['table_names'];
506 public function table_exist($table_name)
508 return (!in_array($this->prep_tablename($table_name), $this->list_tables())) ?
false : true;
511 public function list_fields($table = '')
513 if (isset($this->data_cache
['field_names'][$table]))
515 return $this->data_cache
['field_names'][$table];
522 return $this->display_error('database_field_param_missing');
528 $sql = $this->database_list_columns($this->dbprefix
. $table);
534 return $this->display_error('database_unsupported_function');
540 $query = $this->query($sql);
544 foreach ($query->result_array() as $row)
546 if (isset($row['COLUMN_NAME']))
548 $retval[] = $row['COLUMN_NAME'];
552 $retval[] = current($row);
556 $this->data_cache
['field_names'][$table] = $retval;
558 return $this->data_cache
['field_names'][$table];
561 public function field_exists($field_names, $table_name)
563 return (!in_array($field_names, $this->list_fields($table_name))) ?
false : true;
566 public function field_names($table = '')
568 return $this->list_fields($table);
571 public function field_data($table = '')
577 return $this->display_error('database_field_param_missing');
583 $query = $this->query($this->database_field_data($this->dbprefix
. $table));
585 return $query->field_data();
588 public function insert_string($table, $data)
593 foreach ($data as $key => $val)
596 $values[] = $this->escape($val);
599 return $this->database_insert($this->dbprefix
. $table, $fields, $values);
602 public function update_string($table, $data, $where)
611 foreach ($data as $key => $val)
613 $fields[$key] = $this->escape($val);
616 if (!is_array($where))
618 $dest = array($where);
624 foreach ($where as $key => $val)
626 $prefix = (count($dest) == 0) ?
'' : ' AND ';
630 if (!$this->database_has_operator($key))
635 $val = ' ' . $this->escape($val);
638 $dest[] = $prefix . $key . $val;
642 return $this->database_update($this->dbprefix
. $table, $fields, $dest);
645 public function prep_tablename($table = '')
647 if ($this->dbprefix
!= '')
649 if (substr($table, 0, strlen($this->dbprefix
)) != $this->dbprefix
)
651 $table = $this->dbprefix
. $table;
658 public function call_function($function)
660 $driver = ($this->dbdriver
== 'postgre') ?
'pg_' : $this->dbdriver
. '_';
662 if (strpos($driver, $function) === false)
664 $function = $driver . $function;
667 if (!function_exists($function))
671 return $this->display_error('database_unsupported_function');
678 $args = (func_num_args() > 1) ?
array_splice(func_get_args(), 1) : null;
680 return call_user_func_array($function, $args);
684 public function cache_set_path($path = '')
686 $this->cachedir
= $path;
689 public function cache_on()
691 $this->cache_on
= true;
696 public function cache_off()
698 $this->cache_on
= false;
703 public function cache_delete($segment_one = '', $segment_two = '')
705 if (!$this->_cache_init())
710 return $this->cache
->delete($segment_one, $segment_two);
713 public function cache_delete_all()
715 if (!$this->_cache_init())
720 return $this->cache
->delete_all();
723 public function database_cache_init()
725 if (is_object($this->cache
) && class_exists('Carbon_Database_Cache'))
730 if (!@include
(CARBON_PATH
. 'database/Database_cache' . FILE_EXT
))
732 return $this->cache_off();
735 $this->cache
= new Carbon_Database_Cache
;
740 public function close()
742 if (is_resource($this->conn_id
))
744 $this->database_close($this->conn_id
);
747 $this->conn_id
= false;
750 public function display_error($error = '', $swap = '', $native = false)
752 $lang = load_class('Language');
753 $lang->load('database');
761 $message = (!is_array($error)) ?
array(str_replace('%s', $swap, $lang->line($error))) : $error;
764 $error = load_class('Exception');
765 echo $error->display_error('An error has been encountered', $message, 'error_database');