Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch '3.2/master' of git://github.com/kohana/database into 3.…

…2/master
  • Loading branch information...
commit 926bf56f5d996c02732c9677a6fb9a03e24a0338 2 parents 0ba6065 + f0944e8
Andrew Ellis authored
View
9 classes/config/database.php
@@ -1,3 +1,12 @@
<?php defined('SYSPATH') or die('No direct script access.');
+/**
+ * Transparent extension for the Kohana_Config_Database class
+ *
+ * @package Kohana/Database
+ * @category Configuration
+ * @author Kohana Team
+ * @copyright (c) 2011 Kohana Team
+ * @license http://kohanaframework.org/license
+ */
class Config_Database extends Kohana_Config_Database {}
View
15 classes/config/database/reader.php
@@ -0,0 +1,15 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+
+/**
+ * Transparent extension of the Kohana_Config_Database_Reader class
+ *
+ * @package Kohana/Database
+ * @category Configuration
+ * @author Kohana Team
+ * @copyright (c) 2011 Kohana Team
+ * @license http://kohanaframework.org/license
+ */
+class Config_Database_Reader extends Kohana_Config_Database_Reader
+{
+
+}
View
15 classes/config/database/writer.php
@@ -0,0 +1,15 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+
+/**
+ * Transparent extension for the Kohana_Config_Database_Writer class
+ *
+ * @package Kohana/Database
+ * @category Configuration
+ * @author Kohana Team
+ * @copyright (c) 2011 Kohana Team
+ * @license http://kohanaframework.org/license
+ */
+class Config_Database_Writer extends Kohana_Config_Database_Writer
+{
+
+}
View
98 classes/kohana/config/database.php
@@ -1,97 +1,15 @@
<?php defined('SYSPATH') or die('No direct script access.');
+
/**
- * Database-based configuration loader.
- *
- * Schema for configuration table:
- *
- * group_name varchar(128)
- * config_key varchar(128)
- * config_value text
- * primary key (group_name, config_key)
+ * Backwards compatibility extension for the database writer.
*
* @package Kohana/Database
* @category Configuration
* @author Kohana Team
- * @copyright (c) 2009 Kohana Team
- * @license http://kohanaphp.com/license
+ * @copyright (c) 2011 Kohana Team
+ * @license http://kohanaframework.org/license
*/
-class Kohana_Config_Database extends Config_Reader {
-
- protected $_database_instance = 'default';
-
- protected $_database_table = 'config';
-
- public function __construct(array $config = NULL)
- {
- if (isset($config['instance']))
- {
- $this->_database_instance = $config['instance'];
- }
-
- if (isset($config['table']))
- {
- $this->_database_table = $config['table'];
- }
-
- parent::__construct();
- }
-
- /**
- * Query the configuration table for all values for this group and
- * unserialize each of the values.
- *
- * @param string group name
- * @param array configuration array
- * @return $this clone of the current object
- */
- public function load($group, array $config = NULL)
- {
- if ($config === NULL AND $group !== 'database')
- {
- // Load all of the configuration values for this group
- $query = DB::select('config_key', 'config_value')
- ->from($this->_database_table)
- ->where('group_name', '=', $group)
- ->execute($this->_database_instance);
-
- if (count($query) > 0)
- {
- // Unserialize the configuration values
- $config = array_map('unserialize', $query->as_array('config_key', 'config_value'));
- }
- }
-
- return parent::load($group, $config);
- }
-
- /**
- * Overload setting offsets to insert or update the database values as
- * changes occur.
- *
- * @param string array key
- * @param mixed new value
- * @return mixed
- */
- public function offsetSet($key, $value)
- {
- if ( ! $this->offsetExists($key))
- {
- // Insert a new value
- DB::insert($this->_database_table, array('group_name', 'config_key', 'config_value'))
- ->values(array($this->_configuration_group, $key, serialize($value)))
- ->execute($this->_database_instance);
- }
- elseif ($this->offsetGet($key) !== $value)
- {
- // Update the value
- DB::update($this->_database_table)
- ->value('config_value', serialize($value))
- ->where('group_name', '=', $this->_configuration_group)
- ->where('config_key', '=', $key)
- ->execute($this->_database_instance);
- }
-
- return parent::offsetSet($key, $value);
- }
-
-} // End Kohana_Config_Database
+class Kohana_Config_Database extends Kohana_Config_Database_Writer
+{
+
+}
View
53 classes/kohana/config/database/reader.php
@@ -0,0 +1,53 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+
+/**
+ * Database reader for the kohana config system
+ *
+ * @package Kohana/Database
+ * @category Configuration
+ * @author Kohana Team
+ * @copyright (c) 2011 Kohana Team
+ * @license http://kohanaframework.org/license
+ */
+class Kohana_Config_Database_Reader implements Kohana_Config_Reader
+{
+ protected $_db_instance = 'default';
+
+ protected $_table_name = 'config';
+
+ /**
+ * Constructs the database reader object
+ *
+ * @param array Configuration for the reader
+ */
+ public function __construct(array $config = NULL)
+ {
+ if (isset($config['instance']))
+ {
+ $this->_db_instance = $config['instance'];
+ }
+
+ if (isset($config['table_name']))
+ {
+ $this->_table_name = $config['table_name'];
+ }
+ }
+
+ /**
+ * Tries to load the specificed configuration group
+ *
+ * Returns FALSE if group does not exist or an array if it does
+ *
+ * @param string $group Configuration group
+ * @return boolean|array
+ */
+ public function load($group)
+ {
+ $query = DB::select('config_key', 'config_value')
+ ->from($this->_table_name)
+ ->where('group_name', '=', $group)
+ ->execute($this->_db_instance);
+
+ return count($query) ? array_map('unserialize', $query->as_array('config_key', 'config_value')) : FALSE;
+ }
+}
View
110 classes/kohana/config/database/writer.php
@@ -0,0 +1,110 @@
+<?php defined('SYSPATH') or die('No direct script access.');
+
+/**
+ * Database writer for the config system
+ *
+ * @package Kohana
+ * @category Configuration
+ * @author Kohana Team
+ * @copyright (c) 2007-2011 Kohana Team
+ * @license http://kohanaframework.org/license
+ */
+class Kohana_Config_Database_Writer extends Config_Database_Reader implements Kohana_Config_Writer
+{
+ protected $_loaded_keys = array();
+
+ /**
+ * Tries to load the specificed configuration group
+ *
+ * Returns FALSE if group does not exist or an array if it does
+ *
+ * @param string $group Configuration group
+ * @return boolean|array
+ */
+ public function load($group)
+ {
+ $config = parent::load($group);
+
+ if ($config !== FALSE)
+ {
+ $this->_loaded_keys[$group] = array_combine(array_keys($config), array_keys($config));
+ }
+
+ return $config;
+ }
+
+ /**
+ * Writes the passed config for $group
+ *
+ * Returns chainable instance on success or throws
+ * Kohana_Config_Exception on failure
+ *
+ * @param string $group The config group
+ * @param string $key The config key to write to
+ * @param array $config The configuration to write
+ * @return boolean
+ */
+ public function write($group, $key, $config)
+ {
+ $config = serialize($config);
+
+ // Check to see if we've loaded the config from the table already
+ if (isset($this->_loaded_keys[$group][$key]))
+ {
+ $this->_update($group, $key, $config);
+ }
+ else
+ {
+ // Attempt to run an insert query
+ // This may fail if the config key already exists in the table
+ // and we don't know about it
+ try
+ {
+ $this->_insert($group, $key, $config);
+ }
+ catch (Database_Exception $e)
+ {
+ // Attempt to run an update instead
+ $this->_update($group, $key, $config);
+ }
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Insert the config values into the table
+ *
+ * @param string $group The config group
+ * @param string $key The config key to write to
+ * @param array $config The serialized configuration to write
+ * @return boolean
+ */
+ protected function _insert($group, $key, $config)
+ {
+ DB::insert($this->_table_name, array('group_name', 'config_key', 'config_value'))
+ ->values(array($group, $key, $config))
+ ->execute($this->_db_instance);
+
+ return $this;
+ }
+
+ /**
+ * Update the config values in the table
+ *
+ * @param string $group The config group
+ * @param string $key The config key to write to
+ * @param array $config The serialized configuration to write
+ * @return boolean
+ */
+ protected function _update($group, $key, $config)
+ {
+ DB::update($this->_table_name)
+ ->set(array('config_value' => $config))
+ ->where('group_name', '=', $group)
+ ->where('config_key', '=', $key)
+ ->execute($this->_db_instance);
+
+ return $this;
+ }
+}
View
32 classes/kohana/database.php
@@ -62,7 +62,7 @@ public static function instance($name = NULL, array $config = NULL)
if ($config === NULL)
{
// Load the configuration for this database
- $config = Kohana::config('database')->$name;
+ $config = Kohana::$config->load('database')->$name;
}
if ( ! isset($config['type']))
@@ -416,7 +416,7 @@ public function table_prefix()
* $db->quote('fred'); // 'fred'
*
* Objects passed to this function will be converted to strings.
- * [Database_Expression] objects will use the value of the expression.
+ * [Database_Expression] objects will be compiled.
* [Database_Query] objects will be compiled and converted to a sub-query.
* All other objects will be converted using the `__toString` method.
*
@@ -447,8 +447,8 @@ public function quote($value)
}
elseif ($value instanceof Database_Expression)
{
- // Use a raw expression
- return $value->value();
+ // Compile the expression
+ return $value->compile($this);
}
else
{
@@ -483,6 +483,11 @@ public function quote($value)
* // The value of "column" will be quoted
* $column = $db->quote_column('COUNT("column")');
*
+ * Objects passed to this function will be converted to strings.
+ * [Database_Expression] objects will be compiled.
+ * [Database_Query] objects will be compiled and converted to a sub-query.
+ * All other objects will be converted using the `__toString` method.
+ *
* @param mixed column name or array(column, alias)
* @return string
* @uses Database::quote_identifier
@@ -502,8 +507,8 @@ public function quote_column($column)
}
elseif ($column instanceof Database_Expression)
{
- // Use a raw expression
- $column = $column->value();
+ // Compile the expression
+ $column = $column->compile($this);
}
else
{
@@ -562,6 +567,11 @@ public function quote_column($column)
*
* $table = $db->quote_table($table);
*
+ * Objects passed to this function will be converted to strings.
+ * [Database_Expression] objects will be compiled.
+ * [Database_Query] objects will be compiled and converted to a sub-query.
+ * All other objects will be converted using the `__toString` method.
+ *
* @param mixed table name or array(table, alias)
* @return string
* @uses Database::quote_identifier
@@ -581,8 +591,8 @@ public function quote_table($table)
}
elseif ($table instanceof Database_Expression)
{
- // Use a raw expression
- $table = $table->value();
+ // Compile the expression
+ $table = $table->compile($this);
}
else
{
@@ -630,7 +640,7 @@ public function quote_table($table)
* Quote a database identifier
*
* Objects passed to this function will be converted to strings.
- * [Database_Expression] objects will use the value of the expression.
+ * [Database_Expression] objects will be compiled.
* [Database_Query] objects will be compiled and converted to a sub-query.
* All other objects will be converted using the `__toString` method.
*
@@ -651,8 +661,8 @@ public function quote_identifier($value)
}
elseif ($value instanceof Database_Expression)
{
- // Use a raw expression
- $value = $value->value();
+ // Compile the expression
+ $value = $value->compile($this);
}
else
{
View
78 classes/kohana/database/expression.php
@@ -18,6 +18,9 @@
*/
class Kohana_Database_Expression {
+ // Unquoted parameters
+ protected $_parameters;
+
// Raw expression string
protected $_value;
@@ -26,12 +29,56 @@ class Kohana_Database_Expression {
*
* $expression = new Database_Expression('COUNT(users.id)');
*
+ * @param string $value raw SQL expression string
+ * @param array $parameters unquoted parameter values
* @return void
*/
- public function __construct($value)
+ public function __construct($value, $parameters = array())
{
// Set the expression string
$this->_value = $value;
+ $this->_parameters = $parameters;
+ }
+
+ /**
+ * Bind a variable to a parameter.
+ *
+ * @param string $param parameter key to replace
+ * @param mixed $var variable to use
+ * @return $this
+ */
+ public function bind($param, & $var)
+ {
+ $this->_parameters[$param] =& $var;
+
+ return $this;
+ }
+
+ /**
+ * Set the value of a parameter.
+ *
+ * @param string $param parameter key to replace
+ * @param mixed $value value to use
+ * @return $this
+ */
+ public function param($param, $value)
+ {
+ $this->_parameters[$param] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Add multiple parameter values.
+ *
+ * @param array $params list of parameter values
+ * @return $this
+ */
+ public function parameters(array $params)
+ {
+ $this->_parameters = $params + $this->_parameters;
+
+ return $this;
}
/**
@@ -59,4 +106,33 @@ public function __toString()
return $this->value();
}
+ /**
+ * Compile the SQL expression and return it. Replaces any parameters with
+ * their given values.
+ *
+ * @param mixed Database instance or name of instance
+ * @return string
+ */
+ public function compile($db = NULL)
+ {
+ if ( ! is_object($db))
+ {
+ // Get the database instance
+ $db = Database::instance($db);
+ }
+
+ $value = $this->value();
+
+ if ( ! empty($this->_parameters))
+ {
+ // Quote all of the parameter values
+ $params = array_map(array($db, 'quote'), $this->_parameters);
+
+ // Replace the values in the expression
+ $value = strtr($value, $params);
+ }
+
+ return $value;
+ }
+
} // End Database_Expression
View
19 classes/kohana/database/mysql.php
@@ -59,14 +59,14 @@ public function connect()
$this->_connection = mysql_connect($hostname, $username, $password, TRUE);
}
}
- catch (ErrorException $e)
+ catch (Exception $e)
{
// No connection exists
$this->_connection = NULL;
throw new Database_Exception(':error',
- array(':error' => mysql_error()),
- mysql_errno());
+ array(':error' => $e->getMessage()),
+ $e->getCode());
}
// \xFF is a better delimiter, but the PHP driver uses underscore
@@ -79,6 +79,19 @@ public function connect()
// Set the character set
$this->set_charset($this->_config['charset']);
}
+
+ if ( ! empty($this->_config['connection']['variables']))
+ {
+ // Set session variables
+ $variables = array();
+
+ foreach ($this->_config['connection']['variables'] as $var => $val)
+ {
+ $variables[] = 'SESSION '.$var.' = '.$this->quote($val);
+ }
+
+ mysql_query('SET '.implode(', ', $variables), $this->_connection);
+ }
}
/**
View
45 classes/kohana/database/pdo.php
@@ -68,6 +68,51 @@ public function connect()
}
}
+ /**
+ * Create or redefine a SQL aggregate function.
+ *
+ * [!!] Works only with SQLite
+ *
+ * @link http://php.net/manual/function.pdo-sqlitecreateaggregate
+ *
+ * @param string $name Name of the SQL function to be created or redefined
+ * @param callback $step Called for each row of a result set
+ * @param callback $final Called after all rows of a result set have been processed
+ * @param integer $arguments Number of arguments that the SQL function takes
+ *
+ * @return boolean
+ */
+ public function create_aggregate($name, $step, $final, $arguments = -1)
+ {
+ $this->_connection or $this->connect();
+
+ return $this->_connection->sqliteCreateAggregate(
+ $name, $step, $final, $arguments
+ );
+ }
+
+ /**
+ * Create or redefine a SQL function.
+ *
+ * [!!] Works only with SQLite
+ *
+ * @link http://php.net/manual/function.pdo-sqlitecreatefunction
+ *
+ * @param string $name Name of the SQL function to be created or redefined
+ * @param callback $callback Callback which implements the SQL function
+ * @param integer $arguments Number of arguments that the SQL function takes
+ *
+ * @return boolean
+ */
+ public function create_function($name, $callback, $arguments = -1)
+ {
+ $this->_connection or $this->connect();
+
+ return $this->_connection->sqliteCreateFunction(
+ $name, $callback, $arguments
+ );
+ }
+
public function disconnect()
{
// Destroy the PDO object
View
34 classes/kohana/database/query.php
@@ -13,6 +13,9 @@ class Kohana_Database_Query {
// Query type
protected $_type;
+ // Execute the query during a cache hit
+ protected $_force_execute = FALSE;
+
// Cache lifetime
protected $_lifetime = NULL;
@@ -72,11 +75,12 @@ public function type()
/**
* Enables the query to be cached for a specified amount of time.
*
- * @param integer number of seconds to cache
+ * @param integer number of seconds to cache, 0 deletes it from the cache
+ * @param boolean whether or not to execute the query during a cache hit
* @return $this
* @uses Kohana::$cache_life
*/
- public function cached($lifetime = NULL)
+ public function cached($lifetime = NULL, $force = FALSE)
{
if ($lifetime === NULL)
{
@@ -84,6 +88,7 @@ public function cached($lifetime = NULL)
$lifetime = Kohana::$cache_life;
}
+ $this->_force_execute = $force;
$this->_lifetime = $lifetime;
return $this;
@@ -194,11 +199,14 @@ public function compile(Database $db)
* Execute the current query on the given database.
*
* @param mixed Database instance or name of instance
+ * @param string result object classname, TRUE for stdClass or FALSE for array
+ * @param array result object constructor arguments
+ *
* @return object Database_Result for SELECT queries
* @return mixed the insert id for INSERT queries
* @return integer number of affected rows for all other queries
*/
- public function execute($db = NULL)
+ public function execute($db = NULL, $as_object = NULL, $object_params = NULL)
{
if ( ! is_object($db))
{
@@ -206,6 +214,16 @@ public function execute($db = NULL)
$db = Database::instance($db);
}
+ if ($as_object === NULL)
+ {
+ $as_object = $this->_as_object;
+ }
+
+ if ($object_params === NULL)
+ {
+ $object_params = $this->_object_params;
+ }
+
// Compile the SQL query
$sql = $this->compile($db);
@@ -214,17 +232,19 @@ public function execute($db = NULL)
// Set the cache key based on the database instance name and SQL
$cache_key = 'Database::query("'.$db.'", "'.$sql.'")';
- if ($result = Kohana::cache($cache_key, NULL, $this->_lifetime))
+ // Read the cache first to delete a possible hit with lifetime <= 0
+ if (($result = Kohana::cache($cache_key, NULL, $this->_lifetime)) !== NULL
+ AND ! $this->_force_execute)
{
// Return a cached result
- return new Database_Result_Cached($result, $sql, $this->_as_object, $this->_object_params);
+ return new Database_Result_Cached($result, $sql, $as_object, $object_params);
}
}
// Execute the query
- $result = $db->query($this->_type, $sql, $this->_as_object, $this->_object_params);
+ $result = $db->query($this->_type, $sql, $as_object, $object_params);
- if (isset($cache_key))
+ if (isset($cache_key) AND $this->_lifetime > 0)
{
// Cache the result array
Kohana::cache($cache_key, $result->as_array(), $this->_lifetime);
View
61 classes/kohana/database/query/builder.php
@@ -118,8 +118,16 @@ protected function _compile_conditions(Database $db, array $conditions)
if ($column)
{
- // Apply proper quoting to the column
- $column = $db->quote_column($column);
+ if (is_array($column))
+ {
+ // Use the column name
+ $column = $db->quote_identifier(reset($column));
+ }
+ else
+ {
+ // Apply proper quoting to the column
+ $column = $db->quote_column($column);
+ }
}
// Append the statement to the query
@@ -164,6 +172,36 @@ protected function _compile_set(Database $db, array $values)
}
/**
+ * Compiles an array of GROUP BY columns into an SQL partial.
+ *
+ * @param object Database instance
+ * @param array columns
+ * @return string
+ */
+ protected function _compile_group_by(Database $db, array $columns)
+ {
+ $group = array();
+
+ foreach ($columns as $column)
+ {
+ if (is_array($column))
+ {
+ // Use the column alias
+ $column = $db->quote_identifier(end($column));
+ }
+ else
+ {
+ // Apply proper quoting to the column
+ $column = $db->quote_column($column);
+ }
+
+ $group[] = $column;
+ }
+
+ return 'GROUP BY '.implode(', ', $group);
+ }
+
+ /**
* Compiles an array of ORDER BY statements into an SQL partial.
*
* @param object Database instance
@@ -177,19 +215,24 @@ protected function _compile_order_by(Database $db, array $columns)
{
list ($column, $direction) = $group;
- if ($direction)
+ if (is_array($column))
{
- // Make the direction uppercase
- $direction = strtoupper($direction);
+ // Use the column alias
+ $column = $db->quote_identifier(end($column));
}
-
- if ($column)
+ else
{
- // Quote the column, if it has a value
+ // Apply proper quoting to the column
$column = $db->quote_column($column);
}
- $sort[] = trim($column.' '.$direction);
+ if ($direction)
+ {
+ // Make the direction uppercase
+ $direction = ' '.strtoupper($direction);
+ }
+
+ $sort[] = $column.$direction;
}
return 'ORDER BY '.implode(', ', $sort);
View
9 classes/kohana/database/query/builder/select.php
@@ -308,12 +308,12 @@ public function union($select, $all = TRUE)
/**
* Start returning results after "OFFSET ..."
*
- * @param integer starting result number
+ * @param integer starting result number or NULL to reset
* @return $this
*/
public function offset($number)
{
- $this->_offset = (int) $number;
+ $this->_offset = $number;
return $this;
}
@@ -372,8 +372,8 @@ public function compile(Database $db)
if ( ! empty($this->_group_by))
{
- // Add sorting
- $query .= ' GROUP BY '.implode(', ', array_map($quote_column, $this->_group_by));
+ // Add grouping
+ $query .= ' '.$this->_compile_group_by($db, $this->_group_by);
}
if ( ! empty($this->_having))
@@ -442,4 +442,3 @@ public function reset()
}
} // End Database_Query_Select
-
View
4 classes/kohana/database/query/builder/where.php
@@ -147,12 +147,12 @@ public function order_by($column, $direction = NULL)
/**
* Return up to "LIMIT ..." results
*
- * @param integer maximum results to return
+ * @param integer maximum results to return or NULL to reset
* @return $this
*/
public function limit($number)
{
- $this->_limit = (int) $number;
+ $this->_limit = $number;
return $this;
}
View
5 classes/kohana/db.php
@@ -129,11 +129,12 @@ public static function delete($table = NULL)
* $users = ORM::factory('user')->where(DB::expr("BINARY `hash`"), '=', $hash)->find();
*
* @param string expression
+ * @param array parameters
* @return Database_Expression
*/
- public static function expr($string)
+ public static function expr($string, $parameters = array())
{
- return new Database_Expression($string);
+ return new Database_Expression($string, $parameters);
}
} // End DB
View
10 classes/kohana/session/database.php
@@ -176,6 +176,16 @@ protected function _write()
return TRUE;
}
+ /**
+ * @return bool
+ */
+ protected function _restart()
+ {
+ $this->_regenerate();
+
+ return TRUE;
+ }
+
protected function _destroy()
{
if ($this->_update_id === NULL)
View
1  config/database.php
@@ -14,6 +14,7 @@
* string username database username
* string password database password
* boolean persistent use persistent connections?
+ * array variables system variables as "key => value" pairs
*
* Ports and sockets may be appended to the hostname.
*/
View
2  guide/database/examples.md
@@ -28,7 +28,7 @@ In this example, we loop through an array of whitelisted input fields and for ea
$count = $pagination_query->select('COUNT("*") AS mycount')->execute()->get('mycount');
//pass the total item count to Pagination
- $config = Kohana::config('pagination');
+ $config = Kohana::$config->load('pagination');
$pagination = Pagination::factory(array(
'total_items' => $count,
'current_page' => array('source' => 'route', 'key' => 'page'),
Please sign in to comment.
Something went wrong with that request. Please try again.