TRUE, 'persistent' => FALSE, 'connection' => '', 'character_set' => 'utf8', 'table_prefix' => '', 'object' => TRUE, 'cache' => FALSE, 'escape' => TRUE, ); // Database driver object protected $driver; protected $link; // Un-compiled parts of the SQL query protected $select = array(); protected $set = array(); protected $from = array(); protected $join = array(); protected $where = array(); protected $orderby = array(); protected $order = array(); protected $groupby = array(); protected $having = array(); protected $distinct = FALSE; protected $limit = FALSE; protected $offset = FALSE; protected $last_query = ''; // Stack of queries for push/pop protected $query_history = array(); /** * Returns a singleton instance of Database. * * @param mixed configuration array or DSN * @return Database_Core */ public static function & instance($name = 'default', $config = NULL) { if ( ! isset(Database::$instances[$name])) { // Create a new instance Database::$instances[$name] = new Database($config === NULL ? $name : $config); } return Database::$instances[$name]; } /** * Returns the name of a given database instance. * * @param Database instance of Database * @return string */ public static function instance_name(Database $db) { return array_search($db, Database::$instances, TRUE); } /** * Sets up the database configuration, loads the Database_Driver. * * @throws Kohana_Database_Exception */ public function __construct($config = array()) { if (empty($config)) { // Load the default group $config = Kohana::config('database.default'); } elseif (is_array($config) AND count($config) > 0) { if ( ! array_key_exists('connection', $config)) { $config = array('connection' => $config); } } elseif (is_string($config)) { // The config is a DSN string if (strpos($config, '://') !== FALSE) { $config = array('connection' => $config); } // The config is a group name else { $name = $config; // Test the config group name if (($config = Kohana::config('database.'.$config)) === NULL) throw new Kohana_Database_Exception('database.undefined_group', $name); } } // Merge the default config with the passed config $this->config = array_merge($this->config, $config); if (is_string($this->config['connection'])) { // Make sure the connection is valid if (strpos($this->config['connection'], '://') === FALSE) throw new Kohana_Database_Exception('database.invalid_dsn', $this->config['connection']); // Parse the DSN, creating an array to hold the connection parameters $db = array ( 'type' => FALSE, 'user' => FALSE, 'pass' => FALSE, 'host' => FALSE, 'port' => FALSE, 'socket' => FALSE, 'database' => FALSE ); // Get the protocol and arguments list ($db['type'], $connection) = explode('://', $this->config['connection'], 2); if (strpos($connection, '@') !== FALSE) { // Get the username and password list ($db['pass'], $connection) = explode('@', $connection, 2); // Check if a password is supplied $logindata = explode(':', $db['pass'], 2); $db['pass'] = (count($logindata) > 1) ? $logindata[1] : ''; $db['user'] = $logindata[0]; // Prepare for finding the database $connection = explode('/', $connection); // Find the database name $db['database'] = array_pop($connection); // Reset connection string $connection = implode('/', $connection); // Find the socket if (preg_match('/^unix\([^)]++\)/', $connection)) { // This one is a little hairy: we explode based on the end of // the socket, removing the 'unix(' from the connection string list ($db['socket'], $connection) = explode(')', substr($connection, 5), 2); } elseif (strpos($connection, ':') !== FALSE) { // Fetch the host and port name list ($db['host'], $db['port']) = explode(':', $connection, 2); } else { $db['host'] = $connection; } } else { // File connection $connection = explode('/', $connection); // Find database file name $db['database'] = array_pop($connection); // Find database directory name $db['socket'] = implode('/', $connection).'/'; } // Reset the connection array to the database config $this->config['connection'] = $db; } // Set driver name $driver = 'Database_'.ucfirst($this->config['connection']['type']).'_Driver'; // Load the driver if ( ! Kohana::auto_load($driver)) throw new Kohana_Database_Exception('core.driver_not_found', $this->config['connection']['type'], get_class($this)); // Initialize the driver $this->driver = new $driver($this->config); // Validate the driver if ( ! ($this->driver instanceof Database_Driver)) throw new Kohana_Database_Exception('core.driver_implements', $this->config['connection']['type'], get_class($this), 'Database_Driver'); Kohana::log('debug', 'Database Library initialized'); } /** * Simple connect method to get the database queries up and running. * * @return void */ public function connect() { // A link can be a resource or an object if ( ! is_resource($this->link) AND ! is_object($this->link)) { $this->link = $this->driver->connect(); if ( ! is_resource($this->link) AND ! is_object($this->link)) throw new Kohana_Database_Exception('database.connection', $this->driver->show_error()); // Clear password after successful connect $this->config['connection']['pass'] = NULL; } } /** * Runs a query into the driver and returns the result. * * @param string SQL query to execute * @return Database_Result */ public function query($sql = '') { if ($sql == '') return FALSE; // No link? Connect! $this->link or $this->connect(); // Start the benchmark $start = microtime(TRUE); if (func_num_args() > 1) //if we have more than one argument ($sql) { $argv = func_get_args(); $binds = (is_array(next($argv))) ? current($argv) : array_slice($argv, 1); } // Compile binds if needed if (isset($binds)) { $sql = $this->compile_binds($sql, $binds); } // Fetch the result $result = $this->driver->query($this->last_query = $sql); // Stop the benchmark $stop = microtime(TRUE); if ($this->config['benchmark'] == TRUE) { // Benchmark the query Database::$benchmarks[] = array('query' => $sql, 'time' => $stop - $start, 'rows' => count($result)); } return $result; } /** * Selects the column names for a database query. * * @param string string or array of column names to select * @return Database_Core This Database object. */ public function select($sql = '*') { if (func_num_args() > 1) { $sql = func_get_args(); } elseif (is_string($sql)) { $sql = explode(',', $sql); } else { $sql = (array) $sql; } foreach ($sql as $val) { if (($val = trim($val)) === '') continue; if (strpos($val, '(') === FALSE AND $val !== '*') { if (preg_match('/^DISTINCT\s++(.+)$/i', $val, $matches)) { // Only prepend with table prefix if table name is specified $val = (strpos($matches[1], '.') !== FALSE) ? $this->config['table_prefix'].$matches[1] : $matches[1]; $this->distinct = TRUE; } else { $val = (strpos($val, '.') !== FALSE) ? $this->config['table_prefix'].$val : $val; } $val = $this->driver->escape_column($val); } $this->select[] = $val; } return $this; } /** * Selects the from table(s) for a database query. * * @param string string or array of tables to select * @return Database_Core This Database object. */ public function from($sql) { if (func_num_args() > 1) { $sql = func_get_args(); } elseif (is_string($sql)) { $sql = explode(',', $sql); } else { $sql = array($sql); } foreach ($sql as $val) { if (is_string($val)) { if (($val = trim($val)) === '') continue; // TODO: Temporary solution, this should be moved to database driver (AS is checked for twice) if (stripos($val, ' AS ') !== FALSE) { $val = str_ireplace(' AS ', ' AS ', $val); list($table, $alias) = explode(' AS ', $val); // Attach prefix to both sides of the AS $val = $this->config['table_prefix'].$table.' AS '.$this->config['table_prefix'].$alias; } else { $val = $this->config['table_prefix'].$val; } } $this->from[] = $val; } return $this; } /** * Generates the JOIN portion of the query. * * @param string table name * @param string|array where key or array of key => value pairs * @param string where value * @param string type of join * @return Database_Core This Database object. */ public function join($table, $key, $value = NULL, $type = '') { $join = array(); if ( ! empty($type)) { $type = strtoupper(trim($type)); if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE)) { $type = ''; } else { $type .= ' '; } } $cond = array(); $keys = is_array($key) ? $key : array($key => $value); foreach ($keys as $key => $value) { $key = (strpos($key, '.') !== FALSE) ? $this->config['table_prefix'].$key : $key; if (is_string($value)) { // Only escape if it's a string $value = $this->driver->escape_column($this->config['table_prefix'].$value); } $cond[] = $this->driver->where($key, $value, 'AND ', count($cond), FALSE); } if ( ! is_array($this->join)) { $this->join = array(); } if ( ! is_array($table)) { $table = array($table); } foreach ($table as $t) { if (is_string($t)) { // TODO: Temporary solution, this should be moved to database driver (AS is checked for twice) if (stripos($t, ' AS ') !== FALSE) { $t = str_ireplace(' AS ', ' AS ', $t); list($table, $alias) = explode(' AS ', $t); // Attach prefix to both sides of the AS $t = $this->config['table_prefix'].$table.' AS '.$this->config['table_prefix'].$alias; } else { $t = $this->config['table_prefix'].$t; } } $join['tables'][] = $this->driver->escape_column($t); } $join['conditions'] = '('.trim(implode(' ', $cond)).')'; $join['type'] = $type; $this->join[] = $join; return $this; } /** * Selects the where(s) for a database query. * * @param string|array key name or array of key => value pairs * @param string value to match with key * @param boolean disable quoting of WHERE clause * @return Database_Core This Database object. */ public function where($key, $value = NULL, $quote = TRUE) { $quote = (func_num_args() < 2 AND ! is_array($key)) ? -1 : $quote; if (is_object($key)) { $keys = array((string) $key => ''); } elseif ( ! is_array($key)) { $keys = array($key => $value); } else { $keys = $key; } foreach ($keys as $key => $value) { $key = (strpos($key, '.') !== FALSE) ? $this->config['table_prefix'].$key : $key; $this->where[] = $this->driver->where($key, $value, 'AND ', count($this->where), $quote); } return $this; } /** * Selects the or where(s) for a database query. * * @param string|array key name or array of key => value pairs * @param string value to match with key * @param boolean disable quoting of WHERE clause * @return Database_Core This Database object. */ public function orwhere($key, $value = NULL, $quote = TRUE) { $quote = (func_num_args() < 2 AND ! is_array($key)) ? -1 : $quote; if (is_object($key)) { $keys = array((string) $key => ''); } elseif ( ! is_array($key)) { $keys = array($key => $value); } else { $keys = $key; } foreach ($keys as $key => $value) { $key = (strpos($key, '.') !== FALSE) ? $this->config['table_prefix'].$key : $key; $this->where[] = $this->driver->where($key, $value, 'OR ', count($this->where), $quote); } return $this; } /** * Selects the like(s) for a database query. * * @param string|array field name or array of field => match pairs * @param string like value to match with field * @param boolean automatically add starting and ending wildcards * @return Database_Core This Database object. */ public function like($field, $match = '', $auto = TRUE) { $fields = is_array($field) ? $field : array($field => $match); foreach ($fields as $field => $match) { $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; $this->where[] = $this->driver->like($field, $match, $auto, 'AND ', count($this->where)); } return $this; } /** * Selects the or like(s) for a database query. * * @param string|array field name or array of field => match pairs * @param string like value to match with field * @param boolean automatically add starting and ending wildcards * @return Database_Core This Database object. */ public function orlike($field, $match = '', $auto = TRUE) { $fields = is_array($field) ? $field : array($field => $match); foreach ($fields as $field => $match) { $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; $this->where[] = $this->driver->like($field, $match, $auto, 'OR ', count($this->where)); } return $this; } /** * Selects the not like(s) for a database query. * * @param string|array field name or array of field => match pairs * @param string like value to match with field * @param boolean automatically add starting and ending wildcards * @return Database_Core This Database object. */ public function notlike($field, $match = '', $auto = TRUE) { $fields = is_array($field) ? $field : array($field => $match); foreach ($fields as $field => $match) { $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; $this->where[] = $this->driver->notlike($field, $match, $auto, 'AND ', count($this->where)); } return $this; } /** * Selects the or not like(s) for a database query. * * @param string|array field name or array of field => match pairs * @param string like value to match with field * @return Database_Core This Database object. */ public function ornotlike($field, $match = '', $auto = TRUE) { $fields = is_array($field) ? $field : array($field => $match); foreach ($fields as $field => $match) { $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; $this->where[] = $this->driver->notlike($field, $match, $auto, 'OR ', count($this->where)); } return $this; } /** * Selects the like(s) for a database query. * * @param string|array field name or array of field => match pairs * @param string like value to match with field * @return Database_Core This Database object. */ public function regex($field, $match = '') { $fields = is_array($field) ? $field : array($field => $match); foreach ($fields as $field => $match) { $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; $this->where[] = $this->driver->regex($field, $match, 'AND ', count($this->where)); } return $this; } /** * Selects the or like(s) for a database query. * * @param string|array field name or array of field => match pairs * @param string like value to match with field * @return Database_Core This Database object. */ public function orregex($field, $match = '') { $fields = is_array($field) ? $field : array($field => $match); foreach ($fields as $field => $match) { $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; $this->where[] = $this->driver->regex($field, $match, 'OR ', count($this->where)); } return $this; } /** * Selects the not regex(s) for a database query. * * @param string|array field name or array of field => match pairs * @param string regex value to match with field * @return Database_Core This Database object. */ public function notregex($field, $match = '') { $fields = is_array($field) ? $field : array($field => $match); foreach ($fields as $field => $match) { $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; $this->where[] = $this->driver->notregex($field, $match, 'AND ', count($this->where)); } return $this; } /** * Selects the or not regex(s) for a database query. * * @param string|array field name or array of field => match pairs * @param string regex value to match with field * @return Database_Core This Database object. */ public function ornotregex($field, $match = '') { $fields = is_array($field) ? $field : array($field => $match); foreach ($fields as $field => $match) { $field = (strpos($field, '.') !== FALSE) ? $this->config['table_prefix'].$field : $field; $this->where[] = $this->driver->notregex($field, $match, 'OR ', count($this->where)); } return $this; } /** * Chooses the column to group by in a select query. * * @param string column name to group by * @return Database_Core This Database object. */ public function groupby($by) { if ( ! is_array($by)) { $by = explode(',', (string) $by); } foreach ($by as $val) { $val = trim($val); if ($val != '') { // Add the table prefix if we are using table.column names if(strpos($val, '.')) { $val = $this->config['table_prefix'].$val; } $this->groupby[] = $this->driver->escape_column($val); } } return $this; } /** * Selects the having(s) for a database query. * * @param string|array key name or array of key => value pairs * @param string value to match with key * @param boolean disable quoting of WHERE clause * @return Database_Core This Database object. */ public function having($key, $value = '', $quote = TRUE) { $this->having[] = $this->driver->where($key, $value, 'AND', count($this->having), TRUE); return $this; } /** * Selects the or having(s) for a database query. * * @param string|array key name or array of key => value pairs * @param string value to match with key * @param boolean disable quoting of WHERE clause * @return Database_Core This Database object. */ public function orhaving($key, $value = '', $quote = TRUE) { $this->having[] = $this->driver->where($key, $value, 'OR', count($this->having), TRUE); return $this; } /** * Chooses which column(s) to order the select query by. * * @param string|array column(s) to order on, can be an array, single column, or comma seperated list of columns * @param string direction of the order * @return Database_Core This Database object. */ public function orderby($orderby, $direction = NULL) { if ( ! is_array($orderby)) { $orderby = array($orderby => $direction); } foreach ($orderby as $column => $direction) { $direction = strtoupper(trim($direction)); // Add a direction if the provided one isn't valid if ( ! in_array($direction, array('ASC', 'DESC', 'RAND()', 'RANDOM()', 'NULL'))) { $direction = 'ASC'; } // Add the table prefix if a table.column was passed if (strpos($column, '.')) { $column = $this->config['table_prefix'].$column; } $this->orderby[] = $this->driver->escape_column($column).' '.$direction; } return $this; } /** * Selects the limit section of a query. * * @param integer number of rows to limit result to * @param integer offset in result to start returning rows from * @return Database_Core This Database object. */ public function limit($limit, $offset = NULL) { $this->limit = (int) $limit; if ($offset !== NULL OR ! is_int($this->offset)) { $this->offset($offset); } return $this; } /** * Sets the offset portion of a query. * * @param integer offset value * @return Database_Core This Database object. */ public function offset($value) { $this->offset = (int) $value; return $this; } /** * Allows key/value pairs to be set for inserting or updating. * * @param string|array key name or array of key => value pairs * @param string value to match with key * @return Database_Core This Database object. */ public function set($key, $value = '') { if ( ! is_array($key)) { $key = array($key => $value); } foreach ($key as $k => $v) { // Add a table prefix if the column includes the table. if (strpos($k, '.')) $k = $this->config['table_prefix'].$k; $this->set[$k] = $this->driver->escape($v); } return $this; } /** * Compiles the select statement based on the other functions called and runs the query. * * @param string table name * @param string limit clause * @param string offset clause * @return Database_Result */ public function get($table = '', $limit = NULL, $offset = NULL) { if ($table != '') { $this->from($table); } if ( ! is_null($limit)) { $this->limit($limit, $offset); } $sql = $this->driver->compile_select(get_object_vars($this)); $this->reset_select(); $result = $this->query($sql); $this->last_query = $sql; return $result; } /** * Compiles the select statement based on the other functions called and runs the query. * * @param string table name * @param array where clause * @param string limit clause * @param string offset clause * @return Database_Core This Database object. */ public function getwhere($table = '', $where = NULL, $limit = NULL, $offset = NULL) { if ($table != '') { $this->from($table); } if ( ! is_null($where)) { $this->where($where); } if ( ! is_null($limit)) { $this->limit($limit, $offset); } $sql = $this->driver->compile_select(get_object_vars($this)); $this->reset_select(); $result = $this->query($sql); return $result; } /** * Compiles the select statement based on the other functions called and returns the query string. * * @param string table name * @param string limit clause * @param string offset clause * @return string sql string */ public function compile($table = '', $limit = NULL, $offset = NULL) { if ($table != '') { $this->from($table); } if ( ! is_null($limit)) { $this->limit($limit, $offset); } $sql = $this->driver->compile_select(get_object_vars($this)); $this->reset_select(); return $sql; } /** * Compiles an insert string and runs the query. * * @param string table name * @param array array of key/value pairs to insert * @return Database_Result Query result */ public function insert($table = '', $set = NULL) { if ( ! is_null($set)) { $this->set($set); } if ($this->set == NULL) throw new Kohana_Database_Exception('database.must_use_set'); if ($table == '') { if ( ! isset($this->from[0])) throw new Kohana_Database_Exception('database.must_use_table'); $table = $this->from[0]; } // If caching is enabled, clear the cache before inserting ($this->config['cache'] === TRUE) and $this->clear_cache(); $sql = $this->driver->insert($this->config['table_prefix'].$table, array_keys($this->set), array_values($this->set)); $this->reset_write(); return $this->query($sql); } /** * Adds an "IN" condition to the where clause * * @param string Name of the column being examined * @param mixed An array or string to match against * @param bool Generate a NOT IN clause instead * @return Database_Core This Database object. */ public function in($field, $values, $not = FALSE) { if (is_array($values)) { $escaped_values = array(); foreach ($values as $v) { if (is_numeric($v)) { $escaped_values[] = $v; } else { $escaped_values[] = "'".$this->driver->escape_str($v)."'"; } } $values = implode(",", $escaped_values); } $where = $this->driver->escape_column(((strpos($field,'.') !== FALSE) ? $this->config['table_prefix'] : ''). $field).' '.($not === TRUE ? 'NOT ' : '').'IN ('.$values.')'; $this->where[] = $this->driver->where($where, '', 'AND ', count($this->where), -1); return $this; } /** * Adds a "NOT IN" condition to the where clause * * @param string Name of the column being examined * @param mixed An array or string to match against * @return Database_Core This Database object. */ public function notin($field, $values) { return $this->in($field, $values, TRUE); } /** * Compiles a merge string and runs the query. * * @param string table name * @param array array of key/value pairs to merge * @return Database_Result Query result */ public function merge($table = '', $set = NULL) { if ( ! is_null($set)) { $this->set($set); } if ($this->set == NULL) throw new Kohana_Database_Exception('database.must_use_set'); if ($table == '') { if ( ! isset($this->from[0])) throw new Kohana_Database_Exception('database.must_use_table'); $table = $this->from[0]; } $sql = $this->driver->merge($this->config['table_prefix'].$table, array_keys($this->set), array_values($this->set)); $this->reset_write(); return $this->query($sql); } /** * Compiles an update string and runs the query. * * @param string table name * @param array associative array of update values * @param array where clause * @return Database_Result Query result */ public function update($table = '', $set = NULL, $where = NULL) { if ( is_array($set)) { $this->set($set); } if ( ! is_null($where)) { $this->where($where); } if ($this->set == FALSE) throw new Kohana_Database_Exception('database.must_use_set'); if ($table == '') { if ( ! isset($this->from[0])) throw new Kohana_Database_Exception('database.must_use_table'); $table = $this->from[0]; } $sql = $this->driver->update($this->config['table_prefix'].$table, $this->set, $this->where); $this->reset_write(); return $this->query($sql); } /** * Compiles a delete string and runs the query. * * @param string table name * @param array where clause * @return Database_Result Query result */ public function delete($table = '', $where = NULL) { if ($table == '') { if ( ! isset($this->from[0])) throw new Kohana_Database_Exception('database.must_use_table'); $table = $this->from[0]; } else { $table = $this->config['table_prefix'].$table; } if (! is_null($where)) { $this->where($where); } if (count($this->where) < 1) throw new Kohana_Database_Exception('database.must_use_where'); $sql = $this->driver->delete($table, $this->where); $this->reset_write(); return $this->query($sql); } /** * Returns the last query run. * * @return string SQL */ public function last_query() { return $this->last_query; } /** * Count query records. * * @param string table name * @param array where clause * @return integer */ public function count_records($table = FALSE, $where = NULL) { if (count($this->from) < 1) { if ($table == FALSE) throw new Kohana_Database_Exception('database.must_use_table'); $this->from($table); } if ($where !== NULL) { $this->where($where); } $query = $this->select('COUNT(*) AS '.$this->escape_column('records_found'))->get()->result(TRUE); return (int) $query->current()->records_found; } /** * Resets all private select variables. * * @return void */ protected function reset_select() { $this->select = array(); $this->from = array(); $this->join = array(); $this->where = array(); $this->orderby = array(); $this->groupby = array(); $this->having = array(); $this->distinct = FALSE; $this->limit = FALSE; $this->offset = FALSE; } /** * Resets all private insert and update variables. * * @return void */ protected function reset_write() { $this->set = array(); $this->from = array(); $this->where = array(); } /** * Lists all the tables in the current database. * * @return array */ public function list_tables() { $this->link or $this->connect(); return $this->driver->list_tables(); } /** * See if a table exists in the database. * * @param string table name * @param boolean True to attach table prefix * @return boolean */ public function table_exists($table_name, $prefix = TRUE) { if ($prefix) return in_array($this->config['table_prefix'].$table_name, $this->list_tables()); else return in_array($table_name, $this->list_tables()); } /** * Combine a SQL statement with the bind values. Used for safe queries. * * @param string query to bind to the values * @param array array of values to bind to the query * @return string */ public function compile_binds($sql, $binds) { foreach ((array) $binds as $val) { // If the SQL contains no more bind marks ("?"), we're done. if (($next_bind_pos = strpos($sql, '?')) === FALSE) break; // Properly escape the bind value. $val = $this->driver->escape($val); // Temporarily replace possible bind marks ("?"), in the bind value itself, with a placeholder. $val = str_replace('?', '{%B%}', $val); // Replace the first bind mark ("?") with its corresponding value. $sql = substr($sql, 0, $next_bind_pos).$val.substr($sql, $next_bind_pos + 1); } // Restore placeholders. return str_replace('{%B%}', '?', $sql); } /** * Get the field data for a database table, along with the field's attributes. * * @param string table name * @return array */ public function field_data($table = '') { $this->link or $this->connect(); return $this->driver->field_data($this->config['table_prefix'].$table); } /** * Get the field data for a database table, along with the field's attributes. * * @param string table name * @return array */ public function list_fields($table = '') { $this->link or $this->connect(); return $this->driver->list_fields($this->config['table_prefix'].$table); } /** * Escapes a value for a query. * * @param mixed value to escape * @return string */ public function escape($value) { return $this->driver->escape($value); } /** * Escapes a string for a query. * * @param string string to escape * @return string */ public function escape_str($str) { return $this->driver->escape_str($str); } /** * Escapes a table name for a query. * * @param string string to escape * @return string */ public function escape_table($table) { return $this->driver->escape_table($table); } /** * Escapes a column name for a query. * * @param string string to escape * @return string */ public function escape_column($table) { return $this->driver->escape_column($table); } /** * Returns table prefix of current configuration. * * @return string */ public function table_prefix() { return $this->config['table_prefix']; } /** * Clears the query cache. * * @param string|TRUE clear cache by SQL statement or TRUE for last query * @return Database_Core This Database object. */ public function clear_cache($sql = NULL) { if ($sql === TRUE) { $this->driver->clear_cache($this->last_query); } elseif (is_string($sql)) { $this->driver->clear_cache($sql); } else { $this->driver->clear_cache(); } return $this; } /** * Pushes existing query space onto the query stack. Use push * and pop to prevent queries from clashing before they are * executed * * @return Database_Core This Databaes object */ public function push() { array_push($this->query_history, array( $this->select, $this->from, $this->join, $this->where, $this->orderby, $this->order, $this->groupby, $this->having, $this->distinct, $this->limit, $this->offset )); $this->reset_select(); return $this; } /** * Pops from query stack into the current query space. * * @return Database_Core This Databaes object */ public function pop() { if (count($this->query_history) == 0) { // No history return $this; } list( $this->select, $this->from, $this->join, $this->where, $this->orderby, $this->order, $this->groupby, $this->having, $this->distinct, $this->limit, $this->offset ) = array_pop($this->query_history); return $this; } /** * Count the number of records in the last query, without LIMIT or OFFSET applied. * * @return integer */ public function count_last_query() { if ($sql = $this->last_query()) { if (stripos($sql, 'LIMIT') !== FALSE) { // Remove LIMIT from the SQL $sql = preg_replace('/\sLIMIT\s+[^a-z]+/i', ' ', $sql); } if (stripos($sql, 'OFFSET') !== FALSE) { // Remove OFFSET from the SQL $sql = preg_replace('/\sOFFSET\s+\d+/i', '', $sql); } // Get the total rows from the last query executed $result = $this->query ( 'SELECT COUNT(*) AS '.$this->escape_column('total_rows').' '. 'FROM ('.trim($sql).') AS '.$this->escape_table('counted_results') ); // Return the total number of rows from the query return (int) $result->current()->total_rows; } return FALSE; } } // End Database Class /** * Sets the code for a Database exception. */ class Kohana_Database_Exception extends Kohana_Exception { protected $code = E_DATABASE_ERROR; } // End Kohana Database Exception