From 37c874f1a267c520d300b022bc2af5584864f001 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Thu, 31 May 2012 18:25:25 -0400 Subject: [PATCH] ... --- framework/caching/Cache.php | 12 ++-- framework/caching/ChainedDependency.php | 89 +++++++++++++++--------------- framework/caching/DbCache.php | 4 +- framework/caching/DbDependency.php | 88 +++++++++++++++-------------- framework/caching/ExpressionDependency.php | 12 ++-- framework/caching/FileDependency.php | 2 +- framework/db/ar/ActiveQuery.php | 2 +- framework/db/dao/BaseQuery.php | 10 ++-- framework/db/dao/Connection.php | 18 +++--- framework/db/dao/Query.php | 7 +++ 10 files changed, 123 insertions(+), 121 deletions(-) diff --git a/framework/caching/Cache.php b/framework/caching/Cache.php index 9e080ae..4e6cb8f 100644 --- a/framework/caching/Cache.php +++ b/framework/caching/Cache.php @@ -16,7 +16,7 @@ use yii\base\ApplicationComponent; * * A data item can be stored in cache by calling [[set()]] and be retrieved back * later (in the same or different request) by [[get()]]. In both operations, - * a key identifying the data item is required. An expiration time and/or a [[CacheDependency|dependency]] + * a key identifying the data item is required. An expiration time and/or a [[Dependency|dependency]] * can also be specified when calling [[set()]]. If the data item expires or the dependency * changes at the time of calling [[get()]], the cache will return no data. * @@ -60,7 +60,7 @@ abstract class Cache extends ApplicationComponent implements \ArrayAccess * a two-element array. The first element specifies the serialization function, and the second the deserialization * function. If this property is set false, data will be directly sent to and retrieved from the underlying * cache component without any serialization or deserialization. You should not turn off serialization if - * you are using [[CacheDependency|cache dependency]], because it relies on data serialization. + * you are using [[Dependency|cache dependency]], because it relies on data serialization. */ public $serializer; @@ -102,7 +102,7 @@ abstract class Cache extends ApplicationComponent implements \ArrayAccess } else { $value = call_user_func($this->serializer[1], $value); } - if (is_array($value) && ($value[1] instanceof CacheDependency) || !$value[1]->getHasChanged()) { + if (is_array($value) && ($value[1] instanceof Dependency) || !$value[1]->getHasChanged()) { return $value[0]; } else { return false; @@ -136,7 +136,7 @@ abstract class Cache extends ApplicationComponent implements \ArrayAccess $results[$id] = false; if (isset($values[$uid])) { $value = $this->serializer === null ? unserialize($values[$uid]) : call_user_func($this->serializer[1], $values[$uid]); - if (is_array($value) && (!($value[1] instanceof CacheDependency) || !$value[1]->getHasChanged())) { + if (is_array($value) && (!($value[1] instanceof Dependency) || !$value[1]->getHasChanged())) { $results[$id] = $value[0]; } } @@ -153,7 +153,7 @@ abstract class Cache extends ApplicationComponent implements \ArrayAccess * @param string $id the key identifying the value to be cached * @param mixed $value the value to be cached * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. - * @param CacheDependency $dependency dependency of the cached item. If the dependency changes, + * @param Dependency $dependency dependency of the cached item. If the dependency changes, * the corresponding value in the cache will be invalidated when it is fetched via [[get()]]. * @return boolean whether the value is successfully stored into cache */ @@ -176,7 +176,7 @@ abstract class Cache extends ApplicationComponent implements \ArrayAccess * @param string $id the key identifying the value to be cached * @param mixed $value the value to be cached * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. - * @param CacheDependency $dependency dependency of the cached item. If the dependency changes, + * @param Dependency $dependency dependency of the cached item. If the dependency changes, * the corresponding value in the cache will be invalidated when it is fetched via [[get()]]. * @return boolean whether the value is successfully stored into cache */ diff --git a/framework/caching/ChainedDependency.php b/framework/caching/ChainedDependency.php index fef56ce..664fc10 100644 --- a/framework/caching/ChainedDependency.php +++ b/framework/caching/ChainedDependency.php @@ -10,16 +10,12 @@ namespace yii\caching; /** - * ChainedDependency represents a list of cache dependencies. + * ChainedDependency represents a dependency which is composed of a list of other dependencies. * - * If any of the dependencies reports a dependency change, ChainedDependency - * will return true for the checking. + * When [[dependOnAll]] is true, if any of the dependencies has changed, this dependency is + * considered changed; When [[dependOnAll]] is false, if one of the dependencies has NOT changed, + * this dependency is considered NOT changed. * - * To add dependencies to ChainedDependency, use {@link getDependencies Dependencies} - * which gives a {@link CTypedList} instance and can be used like an array - * (see {@link CList} for more details}). - * - * @property CTypedList $dependencies List of dependency objects. * @property boolean $hasChanged Whether the dependency is changed or not. * * @author Qiang Xue @@ -27,55 +23,52 @@ namespace yii\caching; */ class ChainedDependency extends Dependency { - private $_dependencies=null; - /** - * Constructor. - * @param array $dependencies the dependencies to be added to this chain. - * @since 1.1.4 + * @var array list of dependencies that this dependency is composed of. + * Each array element should be a dependency object or a configuration array + * that can be used to create a dependency object via [[\Yii::createObject()]]. */ - public function __construct($dependencies=array()) - { - if(!empty($dependencies)) - $this->setDependencies($dependencies); - } + public $dependencies = array(); + /** + * @var boolean whether this dependency is depending on every dependency in [[dependencies]]. + * Defaults to true, meaning if any of the dependencies has changed, this dependency is considered changed. + * When it is set false, it means if one of the dependencies has NOT changed, this dependency + * is considered NOT changed. + */ + public $dependOnAll = true; /** - * @return CTypedList list of dependency objects + * Constructor. + * @param array $dependencies list of dependencies that this dependency is composed of. + * Each array element should be a dependency object or a configuration array + * that can be used to create a dependency object via [[\Yii::createObject()]]. */ - public function getDependencies() + public function __construct($dependencies = array()) { - if($this->_dependencies===null) - $this->_dependencies=new CTypedList('ICacheDependency'); - return $this->_dependencies; + $this->dependencies = $dependencies; } /** - * @param array $values list of dependency objects or configurations to be added to this chain. - * If a depedency is specified as a configuration, it must be an array that can be recognized - * by {@link YiiBase::createComponent}. + * Evaluates the dependency by generating and saving the data related with dependency. */ - public function setDependencies($values) + public function evaluateDependency() { - $dependencies=$this->getDependencies(); - foreach($values as $value) - { - if(is_array($value)) - $value=Yii::createComponent($value); - $dependencies->add($value); + foreach ($this->dependencies as $dependency) { + if (!$dependency instanceof Dependency) { + $dependency = \Yii::createObject($dependency); + } + $dependency->evalulateDependency(); } } /** - * Evaluates the dependency by generating and saving the data related with dependency. + * Generates the data needed to determine if dependency has been changed. + * This method does nothing in this class. + * @return mixed the data needed to determine if dependency has been changed. */ - public function evaluateDependency() + protected function generateDependencyData() { - if($this->_dependencies!==null) - { - foreach($this->_dependencies as $dependency) - $dependency->evaluateDependency(); - } + return null; } /** @@ -86,12 +79,16 @@ class ChainedDependency extends Dependency */ public function getHasChanged() { - if($this->_dependencies!==null) - { - foreach($this->_dependencies as $dependency) - if($dependency->getHasChanged()) - return true; + foreach ($this->dependencies as $dependency) { + if (!$dependency instanceof Dependency) { + $dependency = \Yii::createObject($dependency); + } + if ($this->dependOnAll && $dependency->getHasChanged()) { + return true; + } elseif (!$this->dependOnAll && !$dependency->getHasChanged()) { + return false; + } } - return false; + return !$this->dependOnAll; } } diff --git a/framework/caching/DbCache.php b/framework/caching/DbCache.php index ca4198e..2d8b4fd 100644 --- a/framework/caching/DbCache.php +++ b/framework/caching/DbCache.php @@ -47,8 +47,7 @@ use yii\db\dao\Query; class DbCache extends Cache { /** - * @var string the ID of the [[Connection|DB connection]] application component. - * Defaults to 'db'. + * @var string the ID of the [[Connection|DB connection]] application component. Defaults to 'db'. */ public $connectionID = 'db'; /** @@ -108,6 +107,7 @@ class DbCache extends Cache ->where('id = :id AND (expire = 0 OR expire > :time)', array(':id' => $key, ':time' => time())); $db = $this->getDbConnection(); if ($db->queryCachingDuration >= 0) { + // temporarily disable and re-enable query caching $duration = $db->queryCachingDuration; $db->queryCachingDuration = -1; $result = $query->createCommand($db)->queryScalar(); diff --git a/framework/caching/DbDependency.php b/framework/caching/DbDependency.php index 005a969..b0b44be 100644 --- a/framework/caching/DbDependency.php +++ b/framework/caching/DbDependency.php @@ -9,44 +9,42 @@ namespace yii\caching; +use yii\base\Exception; +use yii\db\dao\Connection; +use yii\db\dao\Query; /** * DbDependency represents a dependency based on the query result of a SQL statement. * - * If the query result (a scalar) changes, the dependency is considered as changed. - * To specify the SQL statement, set {@link sql} property. - * The {@link connectionID} property specifies the ID of a {@link CDbConnection} application - * component. It is this DB connection that is used to perform the query. + * If the query result changes, the dependency is considered as changed. + * The query is specified via the [[query]] property. * * @author Qiang Xue * @since 2.0 */ -class DbDependency extends CacheDependency +class DbDependency extends Dependency { /** - * @var string the ID of a {@link CDbConnection} application component. Defaults to 'db'. + * @var string the ID of the [[Connection|DB connection]] application component. Defaults to 'db'. */ public $connectionID = 'db'; /** - * @var string the SQL statement whose result is used to determine if the dependency has been changed. - * Note, the SQL statement should return back a single value. + * @var Query the SQL query whose result is used to determine if the dependency has been changed. + * Only the first row of the query result will be used. */ - public $sql; + public $query; /** - * @var array parameters (name=>value) to be bound to the SQL statement specified by {@link sql}. - * @since 1.1.4 + * @var Connection the DB connection instance */ - public $params; - private $_db; /** * Constructor. - * @param string $sql the SQL statement whose result is used to determine if the dependency has been changed. + * @param Query $query the SQL query whose result is used to determine if the dependency has been changed. */ - public function __construct($sql = null) + public function __construct($query = null) { - $this->sql = $sql; + $this->query = $query; } /** @@ -67,44 +65,44 @@ class DbDependency extends CacheDependency */ protected function generateDependencyData() { - if ($this->sql !== null) { - $db = $this->getDbConnection(); - $command = $db->createCommand($this->sql); - if (is_array($this->params)) { - foreach ($this->params as $name => $value) { - $command->bindValue($name, $value); - } - } - if ($db->queryCachingDuration > 0) { - // temporarily disable and re-enable query caching - $duration = $db->queryCachingDuration; - $db->queryCachingDuration = 0; - $result = $command->queryRow(); - $db->queryCachingDuration = $duration; - } else { - $result = $command->queryRow(); - } - return $result; + $db = $this->getDbConnection(); + $command = $this->query->createCommand($db); + if ($db->queryCachingDuration >= 0) { + // temporarily disable and re-enable query caching + $duration = $db->queryCachingDuration; + $db->queryCachingDuration = -1; + $result = $command->queryRow(); + $db->queryCachingDuration = $duration; } else { - throw new CException(Yii::t('yii', 'DbDependency.sql cannot be empty.')); + $result = $command->queryRow(); } + return $result; } /** - * @return CDbConnection the DB connection instance - * @throws CException if {@link connectionID} does not point to a valid application component. + * Returns the DB connection instance used for caching purpose. + * @return Connection the DB connection instance + * @throws Exception if [[connectionID]] does not point to a valid application component. */ - protected function getDbConnection() + public function getDbConnection() { - if ($this->_db !== null) { - return $this->_db; - } else { - if (($this->_db = \Yii::$application->getComponent($this->connectionID)) instanceof CDbConnection) { - return $this->_db; + if ($this->_db === null) { + $db = \Yii::$application->getComponent($this->connectionID); + if ($db instanceof Connection) { + $this->_db = $db; } else { - throw new CException(Yii::t('yii', 'DbDependency.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.', - array('{id}' => $this->connectionID))); + throw new Exception("DbDependency.connectionID must refer to the ID of a DB connection application component."); } } + return $this->_db; + } + + /** + * Sets the DB connection used by the cache component. + * @param Connection $value the DB connection instance + */ + public function setDbConnection($value) + { + $this->_db = $value; } } diff --git a/framework/caching/ExpressionDependency.php b/framework/caching/ExpressionDependency.php index 18f6c54..19b3b48 100644 --- a/framework/caching/ExpressionDependency.php +++ b/framework/caching/ExpressionDependency.php @@ -1,6 +1,6 @@ * @since 2.0 */ -class CExpressionDependency extends CCacheDependency +class ExpressionDependency extends Dependency { /** * @var string the PHP expression whose result is used to determine the dependency. @@ -35,9 +35,9 @@ class CExpressionDependency extends CCacheDependency * Constructor. * @param string $expression the PHP expression whose result is used to determine the dependency. */ - public function __construct($expression='true') + public function __construct($expression = 'true') { - $this->expression=$expression; + $this->expression = $expression; } /** diff --git a/framework/caching/FileDependency.php b/framework/caching/FileDependency.php index 3e1b2b6..cd02b12 100644 --- a/framework/caching/FileDependency.php +++ b/framework/caching/FileDependency.php @@ -42,6 +42,6 @@ class FileDependency extends Dependency */ protected function generateDependencyData() { - return $this->fileName !== null ? @filemtime($this->fileName) : 0; + return @filemtime($this->fileName); } } diff --git a/framework/db/ar/ActiveQuery.php b/framework/db/ar/ActiveQuery.php index a3ff65e..3c389eb 100644 --- a/framework/db/ar/ActiveQuery.php +++ b/framework/db/ar/ActiveQuery.php @@ -129,7 +129,7 @@ class ActiveQuery extends BaseActiveQuery implements \IteratorAggregate, \ArrayA * It changes the query caching parameter of the {@link dbConnection} instance. * @param integer $duration the number of seconds that query results may remain valid in cache. * If this is 0, the caching will be disabled. - * @param CCacheDependency $dependency the dependency that will be used when saving the query results into cache. + * @param \yii\caching\Dependency $dependency the dependency that will be used when saving the query results into cache. * @param integer $queryCount number of SQL queries that need to be cached after calling this method. Defaults to 1, * meaning that the next SQL query will be cached. * @return ActiveRecord the active record instance itself. diff --git a/framework/db/dao/BaseQuery.php b/framework/db/dao/BaseQuery.php index 3c4bfed..c2d5a2e 100644 --- a/framework/db/dao/BaseQuery.php +++ b/framework/db/dao/BaseQuery.php @@ -78,16 +78,16 @@ class BaseQuery extends \yii\base\Component */ public $having; /** - * @var array list of query parameter values indexed by parameter placeholders. - * For example, `array(':name'=>'Dan', ':age'=>31)`. - */ - public $params; - /** * @var string|BaseQuery[] the UNION clause(s) in a SQL statement. This can be either a string * representing a single UNION clause or an array representing multiple UNION clauses. * Each union clause can be a string or a `BaseQuery` object which refers to the SQL statement. */ public $union; + /** + * @var array list of query parameter values indexed by parameter placeholders. + * For example, `array(':name'=>'Dan', ':age'=>31)`. + */ + public $params; /** * Sets the SELECT part of the query. diff --git a/framework/db/dao/Connection.php b/framework/db/dao/Connection.php index 13dca3a..7b0f5f7 100644 --- a/framework/db/dao/Connection.php +++ b/framework/db/dao/Connection.php @@ -238,15 +238,15 @@ class Connection extends \yii\base\ApplicationComponent * [[Driver]] class to support DBMS that is not supported by Yii. */ public $driverMap = array( - 'pgsql' => '\yii\db\dao\pgsql\Driver', // PostgreSQL - 'mysqli' => '\yii\db\dao\mysql\Driver', // MySQL - 'mysql' => '\yii\db\dao\mysql\Driver', // MySQL - 'sqlite' => '\yii\db\dao\sqlite\Driver', // sqlite 3 - 'sqlite2' => '\yii\db\dao\sqlite\Driver', // sqlite 2 - 'mssql' => '\yii\db\dao\mssql\Driver', // Mssql driver on windows hosts - 'dblib' => '\yii\db\dao\mssql\Driver', // dblib drivers on linux (and maybe others os) hosts - 'sqlsrv' => '\yii\db\dao\mssql\Driver', // Mssql - 'oci' => '\yii\db\dao\oci\Driver', // Oracle driver + 'pgsql' => 'yii\db\dao\pgsql\Driver', // PostgreSQL + 'mysqli' => 'yii\db\dao\mysql\Driver', // MySQL + 'mysql' => 'yii\db\dao\mysql\Driver', // MySQL + 'sqlite' => 'yii\db\dao\sqlite\Driver', // sqlite 3 + 'sqlite2' => 'yii\db\dao\sqlite\Driver', // sqlite 2 + 'mssql' => 'yi\db\dao\mssql\Driver', // Mssql driver on windows hosts + 'dblib' => 'yii\db\dao\mssql\Driver', // dblib drivers on linux (and maybe others os) hosts + 'sqlsrv' => 'yii\db\dao\mssql\Driver', // Mssql + 'oci' => 'yii\db\dao\oci\Driver', // Oracle driver ); /** * @var Transaction the currently active transaction diff --git a/framework/db/dao/Query.php b/framework/db/dao/Query.php index 7d30d42..862154c 100644 --- a/framework/db/dao/Query.php +++ b/framework/db/dao/Query.php @@ -47,6 +47,10 @@ class Query extends BaseQuery * If this property is not set, it means this query represents a SELECT statement. */ public $operation; + /** + * @var string the SQL statement that this query represents. This is directly set by user. + */ + public $sql; /** * Generates and returns the SQL statement according to this query. @@ -58,6 +62,9 @@ class Query extends BaseQuery */ public function getSql($connection = null) { + if ($this->sql !== null) { + return $this->sql; + } if ($connection === null) { $connection = \Yii::$application->db; }