1 <?php defined('SYSPATH') OR die('No direct access allowed.');
3 * Provides database access in a platform agnostic way, using simple query building blocks.
5 * $Id: Database.php 4342 2009-05-08 16:56:01Z jheathco $
9 * @copyright (c) 2007-2008 Kohana Team
10 * @license http://kohanaphp.com/license.html
15 public static $instances = array();
18 public static $benchmarks = array();
21 protected $config = array
24 'persistent' => FALSE,
26 'character_set' => 'utf8',
33 // Database driver object
37 // Un-compiled parts of the SQL query
38 protected $select = array();
39 protected $set = array();
40 protected $from = array();
41 protected $join = array();
42 protected $where = array();
43 protected $orderby = array();
44 protected $order = array();
45 protected $groupby = array();
46 protected $having = array();
47 protected $distinct = FALSE;
48 protected $limit = FALSE;
49 protected $offset = FALSE;
50 protected $last_query = '';
52 // Stack of queries for push/pop
53 protected $query_history = array();
56 * Returns a singleton instance of Database.
58 * @param mixed configuration array or DSN
59 * @return Database_Core
61 public static function & instance($name = 'default', $config = NULL)
63 if ( ! isset(Database::$instances[$name]))
65 // Create a new instance
66 Database::$instances[$name] = new Database($config === NULL ? $name : $config);
69 return Database::$instances[$name];
73 * Returns the name of a given database instance.
75 * @param Database instance of Database
78 public static function instance_name(Database $db)
80 return array_search($db, Database::$instances, TRUE);
84 * Sets up the database configuration, loads the Database_Driver.
86 * @throws Kohana_Database_Exception
88 public function __construct($config = array())
92 // Load the default group
93 $config = Kohana::config('database.default');
95 elseif (is_array($config) AND count($config) > 0)
97 if ( ! array_key_exists('connection', $config))
99 $config = array('connection' => $config);
102 elseif (is_string($config))
104 // The config is a DSN string
105 if (strpos($config, '://') !== FALSE)
107 $config = array('connection' => $config);
109 // The config is a group name
114 // Test the config group name
115 if (($config = Kohana::config('database.'.$config)) === NULL)
116 throw new Kohana_Database_Exception('database.undefined_group', $name);
120 // Merge the default config with the passed config
121 $this->config = array_merge($this->config, $config);
123 if (is_string($this->config['connection']))
125 // Make sure the connection is valid
126 if (strpos($this->config['connection'], '://') === FALSE)
127 throw new Kohana_Database_Exception('database.invalid_dsn', $this->config['connection']);
129 // Parse the DSN, creating an array to hold the connection parameters
141 // Get the protocol and arguments
142 list ($db['type'], $connection) = explode('://', $this->config['connection'], 2);
144 if (strpos($connection, '@') !== FALSE)
146 // Get the username and password
147 list ($db['pass'], $connection) = explode('@', $connection, 2);
148 // Check if a password is supplied
149 $logindata = explode(':', $db['pass'], 2);
150 $db['pass'] = (count($logindata) > 1) ? $logindata[1] : '';
151 $db['user'] = $logindata[0];
153 // Prepare for finding the database
154 $connection = explode('/', $connection);
156 // Find the database name
157 $db['database'] = array_pop($connection);
159 // Reset connection string
160 $connection = implode('/', $connection);
163 if (preg_match('/^unix\([^)]++\)/', $connection))
165 // This one is a little hairy: we explode based on the end of
166 // the socket, removing the 'unix(' from the connection string
167 list ($db['socket'], $connection) = explode(')', substr($connection, 5), 2);
169 elseif (strpos($connection, ':') !== FALSE)
171 // Fetch the host and port name
172 list ($db['host'], $db['port']) = explode(':', $connection, 2);
176 $db['host'] = $connection;
182 $connection = explode('/', $connection);
184 // Find database file name
185 $db['database'] = array_pop($connection);
187 // Find database directory name
188 $db['socket'] = implode('/', $connection).'/';
191 // Reset the connection array to the database config
192 $this->config['connection'] = $db;
195 $driver = 'Database_'.ucfirst($this->config['connection']['type']).'_Driver';
198 if ( ! Kohana::auto_load($driver))
199 throw new Kohana_Database_Exception('core.driver_not_found', $this->config['connection']['type'], get_class($this));
201 // Initialize the driver
202 $this->driver = new $driver($this->config);
204 // Validate the driver
205 if ( ! ($this->driver instanceof Database_Driver))
206 throw new Kohana_Database_Exception('core.driver_implements', $this->config['connection']['type'], get_class($this), 'Database_Driver');
208 Kohana::log('debug', 'Database Library initialized');
212 * Simple connect method to get the database queries up and running.
216 public function connect()
218 // A link can be a resource or an object
219 if ( ! is_resource($this->link) AND ! is_object($this->link))
221 $this->link = $this->driver->connect();
222 if ( ! is_resource($this->link) AND ! is_object($this->link))
223 throw new Kohana_Database_Exception('database.connection', $this->driver->show_error());
225 // Clear password after successful connect
226 $this->config['connection']['pass'] = NULL;
231 * Runs a query into the driver and returns the result.
233 * @param string SQL query to execute
234 * @return Database_Result
236 public function query($sql = '')
238 if ($sql == '') return FALSE;
241 $this->link or $this->connect();
243 // Start the benchmark
244 $start = microtime(TRUE);
246 if (func_num_args() > 1) //if we have more than one argument ($sql)
248 $argv = func_get_args();
249 $binds = (is_array(next($argv))) ? current($argv) : array_slice($argv, 1);
252 // Compile binds if needed
255 $sql = $this->compile_binds($sql, $binds);
259 $result = $this->driver->query($this->last_query = $sql);
261 // Stop the benchmark
262 $stop = microtime(TRUE);
264 if ($this->config['benchmark'] == TRUE)
266 // Benchmark the query
267 Database::$benchmarks[] = array('query' => $sql, 'time' => $stop - $start, 'rows' => count($result));
274 * Selects the column names for a database query.
276 * @param string string or array of column names to select
277 * @return Database_Core This Database object.
279 public function select($sql = '*')
281 if (func_num_args() > 1)
283 $sql = func_get_args();
285 elseif (is_string($sql))
287 $sql = explode(',', $sql);
294 foreach ($sql as $val)
296 if (($val = trim($val)) === '') continue;
298 if (strpos($val, '(') === FALSE AND $val !== '*')
300 if (preg_match('/^DISTINCT\s++(.+)$/i', $val, $matches))
302 // Only prepend with table prefix if table name is specified
303 $val = (strpos($matches[1], '.') !== FALSE) ? $this->config['table_prefix'].$matches[1] : $matches[1];
305 $this->distinct = TRUE;
309 $val = (strpos($val, '.') !== FALSE) ? $this->config['table_prefix'].$val : $val;
312 $val = $this->driver->escape_column($val);
315 $this->select[] = $val;
322 * Selects the from table(s) for a database query.
324 * @param string string or array of tables to select
325 * @return Database_Core This Database object.
327 public function from($sql)
329 if (func_num_args() > 1)
331 $sql = func_get_args();
333 elseif (is_string($sql))
335 $sql = explode(',', $sql);
342 foreach ($sql as $val)
346 if (($val = trim($val)) === '') continue;
348 // TODO: Temporary solution, this should be moved to database driver (AS is checked for twice)
349 if (stripos($val, ' AS ') !== FALSE)
351 $val = str_ireplace(' AS ', ' AS ', $val);
353 list($table, $alias) = explode(' AS ', $val);
355 // Attach prefix to both sides of the AS
356 $val = $this->config['table_prefix'].$table.' AS '.$this->config['table_prefix'].$alias;
360 $val = $this->config['table_prefix'].$val;
364 $this->from[] = $val;
371 * Generates the JOIN portion of the query.
373 * @param string table name
374 * @param string|array where key or array of key => value pairs
375 * @param string where value
376 * @param string type of join
377 * @return Database_Core This Database object.
379 public function join($table, $key, $value = NULL, $type = '')
385 $type = strtoupper(trim($type));
387 if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE))
398 $keys = is_array($key) ? $key : array($key => $value);
399 foreach ($keys as $key => $value)
401 $key = (strpos($key, '.') !== FALSE) ? $this->config['table_prefix'].$key : $key;
403 if (is_string($value))
405 // Only escape if it's a string
406 $value = $this->driver->escape_column($this->config['table_prefix'].$value);
409 $cond[] = $this->driver->where($key, $value, 'AND ', count($cond), FALSE);
412 if ( ! is_array($this->join))
414 $this->join = array();
417 if ( ! is_array($table))
419 $table = array($table);
422 foreach ($table as $t)
426 // TODO: Temporary solution, this should be moved to database driver (AS is checked for twice)
427 if (stripos($t, ' AS ') !== FALSE)
429 $t = str_ireplace(' AS ', ' AS ', $t);
431 list($table, $alias) = explode(' AS ', $t);
433 // Attach prefix to both sides of the AS
434 $t = $this->config['table_prefix'].$table.' AS '.$this->config['table_prefix'].$alias;
438 $t = $this->config['table_prefix'].$t;
442 $join['tables'][] = $this->driver->escape_column($t);
445 $join['conditions'] = '('.trim(implode(' ', $cond)).')';
446 $join['type'] = $type;
448 $this->join[] = $join;
455 * Selects the where(s) for a database query.
457 * @param string|array key name or array of key => value pairs
458 * @param string value to match with key
459 * @param boolean disable quoting of WHERE clause
460 * @return Database_Core This Database object.
462 public function where($key, $value = NULL, $quote = TRUE)
464 $quote = (func_num_args() < 2 AND ! is_array($key)) ? -1 : $quote;
467 $keys = array((string) $key => '');
469 elseif ( ! is_array($key))
471 $keys = array($key => $value);
478 foreach ($keys as $key => $value)
480 $key = (strpos($key, '.') !== FALSE) ? $this->config['table_prefix'].$key : $key;
481 $this->where[] = $this->driver->where($key, $value, 'AND ', count($this->where), $quote);
488 * Selects the or where(s) for a database query.
490 * @param string|array key name or array of key => value pairs
491 * @param string value to match with key
492 * @param boolean disable quoting of WHERE clause
493 * @return Database_Core This Database object.
495 public function orwhere($key, $value = NULL, $quote = TRUE)
497 $quote = (func_num_args() < 2 AND ! is_array($key)) ? -1 : $quote;
500 $keys = array((string) $key => '');
502 elseif ( ! is_array($key))
504 $keys = array($key => $value);
511 foreach ($keys as $key => $value)
513 $key = (strpos($key, '.') !== FALSE) ? $this->config['table_prefix'].$key : $key;
514 $this->where[] = $this->driver->where($key, $value, 'OR ', count($this->where), $quote);
521 * Selects the like(s) for a database query.
523 * @param string|array field name or array of field => match pairs
524 * @param string like value to match with field
525 * @param boolean automatically add starting and ending wildcards
526 * @return Database_Core This Database object.
528 public function like($field, $match = '', $auto = TRUE)
530 $fields = is_array($field) ? $field : array($field => $match);
532 foreach ($fields as $field => $match)
534 $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field;
535 $this->where[] = $this->driver->like($field, $match, $auto, 'AND ', count($this->where));
542 * Selects the or like(s) for a database query.
544 * @param string|array field name or array of field => match pairs
545 * @param string like value to match with field
546 * @param boolean automatically add starting and ending wildcards
547 * @return Database_Core This Database object.
549 public function orlike($field, $match = '', $auto = TRUE)
551 $fields = is_array($field) ? $field : array($field => $match);
553 foreach ($fields as $field => $match)
555 $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field;
556 $this->where[] = $this->driver->like($field, $match, $auto, 'OR ', count($this->where));
563 * Selects the not like(s) for a database query.
565 * @param string|array field name or array of field => match pairs
566 * @param string like value to match with field
567 * @param boolean automatically add starting and ending wildcards
568 * @return Database_Core This Database object.
570 public function notlike($field, $match = '', $auto = TRUE)
572 $fields = is_array($field) ? $field : array($field => $match);
574 foreach ($fields as $field => $match)
576 $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field;
577 $this->where[] = $this->driver->notlike($field, $match, $auto, 'AND ', count($this->where));
584 * Selects the or not like(s) for a database query.
586 * @param string|array field name or array of field => match pairs
587 * @param string like value to match with field
588 * @return Database_Core This Database object.
590 public function ornotlike($field, $match = '', $auto = TRUE)
592 $fields = is_array($field) ? $field : array($field => $match);
594 foreach ($fields as $field => $match)
596 $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field;
597 $this->where[] = $this->driver->notlike($field, $match, $auto, 'OR ', count($this->where));
604 * Selects the like(s) for a database query.
606 * @param string|array field name or array of field => match pairs
607 * @param string like value to match with field
608 * @return Database_Core This Database object.
610 public function regex($field, $match = '')
612 $fields = is_array($field) ? $field : array($field => $match);
614 foreach ($fields as $field => $match)
616 $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field;
617 $this->where[] = $this->driver->regex($field, $match, 'AND ', count($this->where));
624 * Selects the or like(s) for a database query.
626 * @param string|array field name or array of field => match pairs
627 * @param string like value to match with field
628 * @return Database_Core This Database object.
630 public function orregex($field, $match = '')
632 $fields = is_array($field) ? $field : array($field => $match);
634 foreach ($fields as $field => $match)
636 $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field;
637 $this->where[] = $this->driver->regex($field, $match, 'OR ', count($this->where));
644 * Selects the not regex(s) for a database query.
646 * @param string|array field name or array of field => match pairs
647 * @param string regex value to match with field
648 * @return Database_Core This Database object.
650 public function notregex($field, $match = '')
652 $fields = is_array($field) ? $field : array($field => $match);
654 foreach ($fields as $field => $match)
656 $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field;
657 $this->where[] = $this->driver->notregex($field, $match, 'AND ', count($this->where));
664 * Selects the or not regex(s) for a database query.
666 * @param string|array field name or array of field => match pairs
667 * @param string regex value to match with field
668 * @return Database_Core This Database object.
670 public function ornotregex($field, $match = '')
672 $fields = is_array($field) ? $field : array($field => $match);
674 foreach ($fields as $field => $match)
676 $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field;
677 $this->where[] = $this->driver->notregex($field, $match, 'OR ', count($this->where));
684 * Chooses the column to group by in a select query.
686 * @param string column name to group by
687 * @return Database_Core This Database object.
689 public function groupby($by)
691 if ( ! is_array($by))
693 $by = explode(',', (string) $by);
696 foreach ($by as $val)
702 // Add the table prefix if we are using table.column names
703 if(strpos($val, '.'))
705 $val = $this->config['table_prefix'].$val;
708 $this->groupby[] = $this->driver->escape_column($val);
716 * Selects the having(s) for a database query.
718 * @param string|array key name or array of key => value pairs
719 * @param string value to match with key
720 * @param boolean disable quoting of WHERE clause
721 * @return Database_Core This Database object.
723 public function having($key, $value = '', $quote = TRUE)
725 $this->having[] = $this->driver->where($key, $value, 'AND', count($this->having), TRUE);
730 * Selects the or having(s) for a database query.
732 * @param string|array key name or array of key => value pairs
733 * @param string value to match with key
734 * @param boolean disable quoting of WHERE clause
735 * @return Database_Core This Database object.
737 public function orhaving($key, $value = '', $quote = TRUE)
739 $this->having[] = $this->driver->where($key, $value, 'OR', count($this->having), TRUE);
744 * Chooses which column(s) to order the select query by.
746 * @param string|array column(s) to order on, can be an array, single column, or comma seperated list of columns
747 * @param string direction of the order
748 * @return Database_Core This Database object.
750 public function orderby($orderby, $direction = NULL)
752 if ( ! is_array($orderby))
754 $orderby = array($orderby => $direction);
757 foreach ($orderby as $column => $direction)
759 $direction = strtoupper(trim($direction));
761 // Add a direction if the provided one isn't valid
762 if ( ! in_array($direction, array('ASC', 'DESC', 'RAND()', 'RANDOM()', 'NULL')))
767 // Add the table prefix if a table.column was passed
768 if (strpos($column, '.'))
770 $column = $this->config['table_prefix'].$column;
773 $this->orderby[] = $this->driver->escape_column($column).' '.$direction;
780 * Selects the limit section of a query.
782 * @param integer number of rows to limit result to
783 * @param integer offset in result to start returning rows from
784 * @return Database_Core This Database object.
786 public function limit($limit, $offset = NULL)
788 $this->limit = (int) $limit;
790 if ($offset !== NULL OR ! is_int($this->offset))
792 $this->offset($offset);
799 * Sets the offset portion of a query.
801 * @param integer offset value
802 * @return Database_Core This Database object.
804 public function offset($value)
806 $this->offset = (int) $value;
812 * Allows key/value pairs to be set for inserting or updating.
814 * @param string|array key name or array of key => value pairs
815 * @param string value to match with key
816 * @return Database_Core This Database object.
818 public function set($key, $value = '')
820 if ( ! is_array($key))
822 $key = array($key => $value);
825 foreach ($key as $k => $v)
827 // Add a table prefix if the column includes the table.
829 $k = $this->config['table_prefix'].$k;
831 $this->set[$k] = $this->driver->escape($v);
838 * Compiles the select statement based on the other functions called and runs the query.
840 * @param string table name
841 * @param string limit clause
842 * @param string offset clause
843 * @return Database_Result
845 public function get($table = '', $limit = NULL, $offset = NULL)
852 if ( ! is_null($limit))
854 $this->limit($limit, $offset);
857 $sql = $this->driver->compile_select(get_object_vars($this));
859 $this->reset_select();
861 $result = $this->query($sql);
863 $this->last_query = $sql;
869 * Compiles the select statement based on the other functions called and runs the query.
871 * @param string table name
872 * @param array where clause
873 * @param string limit clause
874 * @param string offset clause
875 * @return Database_Core This Database object.
877 public function getwhere($table = '', $where = NULL, $limit = NULL, $offset = NULL)
884 if ( ! is_null($where))
886 $this->where($where);
889 if ( ! is_null($limit))
891 $this->limit($limit, $offset);
894 $sql = $this->driver->compile_select(get_object_vars($this));
896 $this->reset_select();
898 $result = $this->query($sql);
904 * Compiles the select statement based on the other functions called and returns the query string.
906 * @param string table name
907 * @param string limit clause
908 * @param string offset clause
909 * @return string sql string
911 public function compile($table = '', $limit = NULL, $offset = NULL)
918 if ( ! is_null($limit))
920 $this->limit($limit, $offset);
923 $sql = $this->driver->compile_select(get_object_vars($this));
925 $this->reset_select();
931 * Compiles an insert string and runs the query.
933 * @param string table name
934 * @param array array of key/value pairs to insert
935 * @return Database_Result Query result
937 public function insert($table = '', $set = NULL)
939 if ( ! is_null($set))
944 if ($this->set == NULL)
945 throw new Kohana_Database_Exception('database.must_use_set');
949 if ( ! isset($this->from[0]))
950 throw new Kohana_Database_Exception('database.must_use_table');
952 $table = $this->from[0];
955 // If caching is enabled, clear the cache before inserting
956 ($this->config['cache'] === TRUE) and $this->clear_cache();
958 $sql = $this->driver->insert($this->config['table_prefix'].$table, array_keys($this->set), array_values($this->set));
960 $this->reset_write();
962 return $this->query($sql);
966 * Adds an "IN" condition to the where clause
968 * @param string Name of the column being examined
969 * @param mixed An array or string to match against
970 * @param bool Generate a NOT IN clause instead
971 * @return Database_Core This Database object.
973 public function in($field, $values, $not = FALSE)
975 if (is_array($values))
977 $escaped_values = array();
978 foreach ($values as $v)
982 $escaped_values[] = $v;
986 $escaped_values[] = "'".$this->driver->escape_str($v)."'";
989 $values = implode(",", $escaped_values);
992 $where = $this->driver->escape_column(((strpos($field,'.') !== FALSE) ? $this->config['table_prefix'] : ''). $field).' '.($not === TRUE ? 'NOT ' : '').'IN ('.$values.')';
993 $this->where[] = $this->driver->where($where, '', 'AND ', count($this->where), -1);
999 * Adds a "NOT IN" condition to the where clause
1001 * @param string Name of the column being examined
1002 * @param mixed An array or string to match against
1003 * @return Database_Core This Database object.
1005 public function notin($field, $values)
1007 return $this->in($field, $values, TRUE);
1011 * Compiles a merge string and runs the query.
1013 * @param string table name
1014 * @param array array of key/value pairs to merge
1015 * @return Database_Result Query result
1017 public function merge($table = '', $set = NULL)
1019 if ( ! is_null($set))
1024 if ($this->set == NULL)
1025 throw new Kohana_Database_Exception('database.must_use_set');
1029 if ( ! isset($this->from[0]))
1030 throw new Kohana_Database_Exception('database.must_use_table');
1032 $table = $this->from[0];
1035 $sql = $this->driver->merge($this->config['table_prefix'].$table, array_keys($this->set), array_values($this->set));
1037 $this->reset_write();
1038 return $this->query($sql);
1042 * Compiles an update string and runs the query.
1044 * @param string table name
1045 * @param array associative array of update values
1046 * @param array where clause
1047 * @return Database_Result Query result
1049 public function update($table = '', $set = NULL, $where = NULL)
1051 if ( is_array($set))
1056 if ( ! is_null($where))
1058 $this->where($where);
1061 if ($this->set == FALSE)
1062 throw new Kohana_Database_Exception('database.must_use_set');
1066 if ( ! isset($this->from[0]))
1067 throw new Kohana_Database_Exception('database.must_use_table');
1069 $table = $this->from[0];
1072 $sql = $this->driver->update($this->config['table_prefix'].$table, $this->set, $this->where);
1074 $this->reset_write();
1075 return $this->query($sql);
1079 * Compiles a delete string and runs the query.
1081 * @param string table name
1082 * @param array where clause
1083 * @return Database_Result Query result
1085 public function delete($table = '', $where = NULL)
1089 if ( ! isset($this->from[0]))
1090 throw new Kohana_Database_Exception('database.must_use_table');
1092 $table = $this->from[0];
1096 $table = $this->config['table_prefix'].$table;
1099 if (! is_null($where))
1101 $this->where($where);
1104 if (count($this->where) < 1)
1105 throw new Kohana_Database_Exception('database.must_use_where');
1107 $sql = $this->driver->delete($table, $this->where);
1109 $this->reset_write();
1110 return $this->query($sql);
1114 * Returns the last query run.
1116 * @return string SQL
1118 public function last_query()
1120 return $this->last_query;
1124 * Count query records.
1126 * @param string table name
1127 * @param array where clause
1130 public function count_records($table = FALSE, $where = NULL)
1132 if (count($this->from) < 1)
1134 if ($table == FALSE)
1135 throw new Kohana_Database_Exception('database.must_use_table');
1137 $this->from($table);
1140 if ($where !== NULL)
1142 $this->where($where);
1145 $query = $this->select('COUNT(*) AS '.$this->escape_column('records_found'))->get()->result(TRUE);
1147 return (int) $query->current()->records_found;
1151 * Resets all private select variables.
1155 protected function reset_select()
1157 $this->select = array();
1158 $this->from = array();
1159 $this->join = array();
1160 $this->where = array();
1161 $this->orderby = array();
1162 $this->groupby = array();
1163 $this->having = array();
1164 $this->distinct = FALSE;
1165 $this->limit = FALSE;
1166 $this->offset = FALSE;
1170 * Resets all private insert and update variables.
1174 protected function reset_write()
1176 $this->set = array();
1177 $this->from = array();
1178 $this->where = array();
1182 * Lists all the tables in the current database.
1186 public function list_tables()
1188 $this->link or $this->connect();
1190 return $this->driver->list_tables();
1194 * See if a table exists in the database.
1196 * @param string table name
1197 * @param boolean True to attach table prefix
1200 public function table_exists($table_name, $prefix = TRUE)
1203 return in_array($this->config['table_prefix'].$table_name, $this->list_tables());
1205 return in_array($table_name, $this->list_tables());
1209 * Combine a SQL statement with the bind values. Used for safe queries.
1211 * @param string query to bind to the values
1212 * @param array array of values to bind to the query
1215 public function compile_binds($sql, $binds)
1217 foreach ((array) $binds as $val)
1219 // If the SQL contains no more bind marks ("?"), we're done.
1220 if (($next_bind_pos = strpos($sql, '?')) === FALSE)
1223 // Properly escape the bind value.
1224 $val = $this->driver->escape($val);
1226 // Temporarily replace possible bind marks ("?"), in the bind value itself, with a placeholder.
1227 $val = str_replace('?', '{%B%}', $val);
1229 // Replace the first bind mark ("?") with its corresponding value.
1230 $sql = substr($sql, 0, $next_bind_pos).$val.substr($sql, $next_bind_pos + 1);
1233 // Restore placeholders.
1234 return str_replace('{%B%}', '?', $sql);
1238 * Get the field data for a database table, along with the field's attributes.
1240 * @param string table name
1243 public function field_data($table = '')
1245 $this->link or $this->connect();
1247 return $this->driver->field_data($this->config['table_prefix'].$table);
1251 * Get the field data for a database table, along with the field's attributes.
1253 * @param string table name
1256 public function list_fields($table = '')
1258 $this->link or $this->connect();
1260 return $this->driver->list_fields($this->config['table_prefix'].$table);
1264 * Escapes a value for a query.
1266 * @param mixed value to escape
1269 public function escape($value)
1271 return $this->driver->escape($value);
1275 * Escapes a string for a query.
1277 * @param string string to escape
1280 public function escape_str($str)
1282 return $this->driver->escape_str($str);
1286 * Escapes a table name for a query.
1288 * @param string string to escape
1291 public function escape_table($table)
1293 return $this->driver->escape_table($table);
1297 * Escapes a column name for a query.
1299 * @param string string to escape
1302 public function escape_column($table)
1304 return $this->driver->escape_column($table);
1308 * Returns table prefix of current configuration.
1312 public function table_prefix()
1314 return $this->config['table_prefix'];
1318 * Clears the query cache.
1320 * @param string|TRUE clear cache by SQL statement or TRUE for last query
1321 * @return Database_Core This Database object.
1323 public function clear_cache($sql = NULL)
1327 $this->driver->clear_cache($this->last_query);
1329 elseif (is_string($sql))
1331 $this->driver->clear_cache($sql);
1335 $this->driver->clear_cache();
1342 * Pushes existing query space onto the query stack. Use push
1343 * and pop to prevent queries from clashing before they are
1346 * @return Database_Core This Databaes object
1348 public function push()
1350 array_push($this->query_history, array(
1364 $this->reset_select();
1370 * Pops from query stack into the current query space.
1372 * @return Database_Core This Databaes object
1374 public function pop()
1376 if (count($this->query_history) == 0)
1394 ) = array_pop($this->query_history);
1400 * Count the number of records in the last query, without LIMIT or OFFSET applied.
1404 public function count_last_query()
1406 if ($sql = $this->last_query())
1408 if (stripos($sql, 'LIMIT') !== FALSE)
1410 // Remove LIMIT from the SQL
1411 $sql = preg_replace('/\sLIMIT\s+[^a-z]+/i', ' ', $sql);
1414 if (stripos($sql, 'OFFSET') !== FALSE)
1416 // Remove OFFSET from the SQL
1417 $sql = preg_replace('/\sOFFSET\s+\d+/i', '', $sql);
1420 // Get the total rows from the last query executed
1421 $result = $this->query
1423 'SELECT COUNT(*) AS '.$this->escape_column('total_rows').' '.
1424 'FROM ('.trim($sql).') AS '.$this->escape_table('counted_results')
1427 // Return the total number of rows from the query
1428 return (int) $result->current()->total_rows;
1434 } // End Database Class
1438 * Sets the code for a Database exception.
1440 class Kohana_Database_Exception extends Kohana_Exception {
1442 protected $code = E_DATABASE_ERROR;
1444 } // End Kohana Database Exception