mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-26 14:26:54 +08:00
Fixed issues in accidental merge of unfinished #15398
This commit is contained in:
@ -320,9 +320,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface
|
||||
}
|
||||
|
||||
$command = $db->createCommand($sql, $params);
|
||||
if ($this->hasCache()) {
|
||||
$command->cache($this->queryCacheDuration, $this->queryCacheDependency);
|
||||
}
|
||||
$this->setCommandCache($command);
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
@ -345,9 +344,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface
|
||||
->from(['c' => "({$this->sql})"])
|
||||
->params($this->params)
|
||||
->createCommand($db);
|
||||
if ($this->hasCache()) {
|
||||
$command->cache($this->queryCacheDuration, $this->queryCacheDependency);
|
||||
}
|
||||
$this->setCommandCache($command);
|
||||
|
||||
return $command->queryScalar();
|
||||
}
|
||||
|
||||
|
@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace yii\db;
|
||||
|
||||
/**
|
||||
* Trait CacheableQueryTrait provides methods to cache query execution result.
|
||||
*
|
||||
* The class that uses this trait must have the $db property:
|
||||
* @property Connection $db
|
||||
*
|
||||
* @author hubeiwei <hubeiwei@hotmail.com>
|
||||
* @author Dmytro Naumenko <d.naumenko.a@gmail.com>
|
||||
* @since 2.0.14
|
||||
*/
|
||||
trait CacheableQueryTrait
|
||||
{
|
||||
/**
|
||||
* @var int the default number of seconds that query results can remain valid in cache.
|
||||
* Use 0 to indicate that the cached data will never expire. And use a negative number to indicate
|
||||
* query cache should not be used.
|
||||
* @see cache()
|
||||
*/
|
||||
public $queryCacheDuration;
|
||||
/**
|
||||
* @var \yii\caching\Dependency the dependency to be associated with the cached query result for this command
|
||||
* @see cache()
|
||||
*/
|
||||
public $queryCacheDependency;
|
||||
|
||||
/**
|
||||
* Enables query cache for this command or query.
|
||||
* @param int $duration the number of seconds that query result of this command or query can remain valid in the cache.
|
||||
* If this is not set, the value of [[Connection::queryCacheDuration]] will be used instead.
|
||||
* Use 0 to indicate that the cached data will never expire.
|
||||
* @param \yii\caching\Dependency $dependency the cache dependency associated with the cached result.
|
||||
* @return $this the command or query object itself
|
||||
*/
|
||||
public function cache($duration = null, $dependency = null)
|
||||
{
|
||||
$this->queryCacheDuration = $duration !== null ? $duration : $this->db->queryCacheDuration;
|
||||
$this->queryCacheDependency = $dependency;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables query cache for this command or query.
|
||||
* @return $this the command or query object itself
|
||||
*/
|
||||
public function noCache()
|
||||
{
|
||||
$this->queryCacheDuration = -1;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, whether caching is enabled
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCache()
|
||||
{
|
||||
return $this->queryCacheDuration !== null || $this->queryCacheDependency !== null;
|
||||
}
|
||||
}
|
@ -56,8 +56,6 @@ use yii\base\NotSupportedException;
|
||||
*/
|
||||
class Command extends Component
|
||||
{
|
||||
use CacheableQueryTrait;
|
||||
|
||||
/**
|
||||
* @var Connection the DB connection that this command is associated with
|
||||
*/
|
||||
@ -77,6 +75,18 @@ class Command extends Component
|
||||
* and is used to generate [[rawSql]]. Do not modify it directly.
|
||||
*/
|
||||
public $params = [];
|
||||
/**
|
||||
* @var int the default number of seconds that query results can remain valid in cache.
|
||||
* Use 0 to indicate that the cached data will never expire. And use a negative number to indicate
|
||||
* query cache should not be used.
|
||||
* @see cache()
|
||||
*/
|
||||
public $queryCacheDuration;
|
||||
/**
|
||||
* @var \yii\caching\Dependency the dependency to be associated with the cached query result for this command
|
||||
* @see cache()
|
||||
*/
|
||||
public $queryCacheDependency;
|
||||
|
||||
/**
|
||||
* @var array pending parameters to be bound to the current PDO statement.
|
||||
@ -101,6 +111,30 @@ class Command extends Component
|
||||
*/
|
||||
private $_retryHandler;
|
||||
|
||||
/**
|
||||
* Enables query cache for this command.
|
||||
* @param int $duration the number of seconds that query result of this command can remain valid in the cache.
|
||||
* If this is not set, the value of [[Connection::queryCacheDuration]] will be used instead.
|
||||
* Use 0 to indicate that the cached data will never expire.
|
||||
* @param \yii\caching\Dependency $dependency the cache dependency associated with the cached query result.
|
||||
* @return $this the command object itself
|
||||
*/
|
||||
public function cache($duration = null, $dependency = null)
|
||||
{
|
||||
$this->queryCacheDuration = $duration === null ? $this->db->queryCacheDuration : $duration;
|
||||
$this->queryCacheDependency = $dependency;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables query cache for this command.
|
||||
* @return $this the command object itself
|
||||
*/
|
||||
public function noCache()
|
||||
{
|
||||
$this->queryCacheDuration = -1;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL statement for this command.
|
||||
|
@ -50,7 +50,6 @@ use yii\base\InvalidParamException;
|
||||
class Query extends Component implements QueryInterface
|
||||
{
|
||||
use QueryTrait;
|
||||
use CacheableQueryTrait;
|
||||
|
||||
/**
|
||||
* @var array the columns being selected. For example, `['id', 'name']`.
|
||||
@ -115,7 +114,19 @@ class Query extends Component implements QueryInterface
|
||||
* For example, `[':name' => 'Dan', ':age' => 31]`.
|
||||
*/
|
||||
public $params = [];
|
||||
|
||||
/**
|
||||
* @var int|true the default number of seconds that query results can remain valid in cache.
|
||||
* Use 0 to indicate that the cached data will never expire.
|
||||
* Use a negative number to indicate that query cache should not be used.
|
||||
* Use boolean `true` to indicate that [[Connection::queryCacheDuration]] should be used.
|
||||
* @see cache()
|
||||
*/
|
||||
public $queryCacheDuration;
|
||||
/**
|
||||
* @var \yii\caching\Dependency the dependency to be associated with the cached query result for this query
|
||||
* @see cache()
|
||||
*/
|
||||
public $queryCacheDependency;
|
||||
|
||||
/**
|
||||
* Creates a DB command that can be used to execute this query.
|
||||
@ -131,9 +142,8 @@ class Query extends Component implements QueryInterface
|
||||
list($sql, $params) = $db->getQueryBuilder()->build($this);
|
||||
|
||||
$command = $db->createCommand($sql, $params);
|
||||
if ($this->hasCache()) {
|
||||
$command->cache($this->queryCacheDuration, $this->queryCacheDependency);
|
||||
}
|
||||
$this->setCommandCache($command);
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
@ -458,9 +468,8 @@ class Query extends Component implements QueryInterface
|
||||
->select([$selectExpression])
|
||||
->from(['c' => $this])
|
||||
->createCommand($db);
|
||||
if ($this->hasCache()) {
|
||||
$command->cache($this->queryCacheDuration, $this->queryCacheDependency);
|
||||
}
|
||||
$this->setCommandCache($command);
|
||||
|
||||
return $command->queryScalar();
|
||||
}
|
||||
|
||||
@ -1211,6 +1220,51 @@ PATTERN;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables query cache for this Query.
|
||||
* @param int|true the number of seconds that query results can remain valid in cache.
|
||||
* Use 0 to indicate that the cached data will never expire.
|
||||
* Use a negative number to indicate that query cache should not be used.
|
||||
* Use boolean `true` to indicate that [[Connection::queryCacheDuration]] should be used.
|
||||
* Defaults to `true`.
|
||||
* @param \yii\caching\Dependency $dependency the cache dependency associated with the cached result.
|
||||
* @return $this the Query object itself
|
||||
*/
|
||||
public function cache($duration = true, $dependency = null)
|
||||
{
|
||||
$this->queryCacheDuration = $duration;
|
||||
$this->queryCacheDependency = $dependency;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables query cache for this Query.
|
||||
* @return $this the Query object itself
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public function noCache()
|
||||
{
|
||||
$this->queryCacheDuration = -1;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets $command cache, if this query has enabled caching.
|
||||
*
|
||||
* @param Command $command
|
||||
* @return Command
|
||||
* @since 2.0.14
|
||||
*/
|
||||
protected function setCommandCache($command)
|
||||
{
|
||||
if ($this->queryCacheDuration !== null || $this->queryCacheDependency !== null) {
|
||||
$duration = $this->queryCacheDuration === true ? null : $this->queryCacheDuration;
|
||||
$command->cache($duration, $this->queryCacheDependency);
|
||||
}
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Query object and copies its property values from an existing one.
|
||||
* The properties being copies are the ones to be used by query builders.
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
namespace yiiunit\framework\db;
|
||||
|
||||
use yii\caching\ArrayCache;
|
||||
use yii\db\Connection;
|
||||
use yii\db\Expression;
|
||||
use yii\db\Query;
|
||||
@ -621,4 +622,57 @@ abstract class QueryTest extends DatabaseTestCase
|
||||
$result = $query->one($db);
|
||||
$this->assertEquals('user3', $result['name']);
|
||||
}
|
||||
|
||||
public function testQueryCache()
|
||||
{
|
||||
$db = $this->getConnection();
|
||||
$db->enableQueryCache = true;
|
||||
$db->queryCache = new ArrayCache();
|
||||
$query = (new Query())
|
||||
->select(['name'])
|
||||
->from('customer');
|
||||
$update = $db->createCommand('UPDATE {{customer}} SET [[name]] = :name WHERE [[id]] = :id');
|
||||
|
||||
$this->assertEquals('user1', $query->where(['id' => 1])->scalar($db), 'Asserting initial value');
|
||||
|
||||
// No cache
|
||||
$update->bindValues([':id' => 1, ':name' => 'user11'])->execute();
|
||||
$this->assertEquals('user11', $query->where(['id' => 1])->scalar($db), 'Query reflects DB changes when caching is disabled');
|
||||
|
||||
// Connection cache
|
||||
$db->cache(function (Connection $db) use ($query, $update) {
|
||||
$this->assertEquals('user2', $query->where(['id' => 2])->scalar($db), 'Asserting initial value for user #2');
|
||||
|
||||
$update->bindValues([':id' => 2, ':name' => 'user22'])->execute();
|
||||
$this->assertEquals('user2', $query->where(['id' => 2])->scalar($db), 'Query does NOT reflect DB changes when wrapped in connection caching');
|
||||
|
||||
$db->noCache(function () use ($query, $db) {
|
||||
$this->assertEquals('user22', $query->where(['id' => 2])->scalar($db), 'Query reflects DB changes when wrapped in connection caching and noCache simultaneously');
|
||||
});
|
||||
|
||||
$this->assertEquals('user2', $query->where(['id' => 2])->scalar($db), 'Cache does not get changes after getting newer data from DB in noCache block.');
|
||||
}, 10);
|
||||
|
||||
|
||||
$db->enableQueryCache = false;
|
||||
$db->cache(function ($db) use ($query, $update) {
|
||||
$this->assertEquals('user22', $query->where(['id' => 2])->scalar($db), 'When cache is disabled for the whole connection, Query inside cache block does not get cached');
|
||||
$update->bindValues([':id' => 2, ':name' => 'user2'])->execute();
|
||||
$this->assertEquals('user2', $query->where(['id' => 2])->scalar($db));
|
||||
}, 10);
|
||||
|
||||
|
||||
$db->enableQueryCache = true;
|
||||
$query->cache();
|
||||
|
||||
$this->assertEquals('user11', $query->where(['id' => 1])->scalar($db));
|
||||
$update->bindValues([':id' => 1, ':name' => 'user1'])->execute();
|
||||
$this->assertEquals('user11', $query->where(['id' => 1])->scalar($db), 'When both Connection and Query have cache enabled, we get cached value');
|
||||
$this->assertEquals('user1', $query->noCache()->where(['id' => 1])->scalar($db), 'When Query has disabled cache, we get actual data');
|
||||
|
||||
$db->cache(function (Connection $db) use ($query, $update) {
|
||||
$this->assertEquals('user1', $query->noCache()->where(['id' => 1])->scalar($db));
|
||||
$this->assertEquals('user11', $query->cache()->where(['id' => 1])->scalar($db));
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user