Commit 352ab0de authored by romanb's avatar romanb

renamed the default hydrator. started to implement a query cache.

parent 896b9915
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
* @version $Revision: 3192 $ * @version $Revision: 3192 $
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*/ */
class Doctrine_Hydrator_Default extends Doctrine_Hydrator_Abstract class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
{ {
/** /**
* hydrateResultSet * hydrateResultSet
...@@ -73,9 +73,9 @@ class Doctrine_Hydrator_Default extends Doctrine_Hydrator_Abstract ...@@ -73,9 +73,9 @@ class Doctrine_Hydrator_Default extends Doctrine_Hydrator_Abstract
} }
if ($hydrationMode === Doctrine::HYDRATE_ARRAY) { if ($hydrationMode === Doctrine::HYDRATE_ARRAY) {
$driver = new Doctrine_Hydrator_Default_ArrayDriver(); $driver = new Doctrine_Hydrator_ArrayDriver();
} else { } else {
$driver = new Doctrine_Hydrator_Default_RecordDriver(); $driver = new Doctrine_Hydrator_RecordDriver();
} }
$event = new Doctrine_Event(null, Doctrine_Event::HYDRATE, null); $event = new Doctrine_Event(null, Doctrine_Event::HYDRATE, null);
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* @version $Revision$ * @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*/ */
class Doctrine_Hydrator_Default_ArrayDriver class Doctrine_Hydrator_ArrayDriver
{ {
public function getElementCollection($component) public function getElementCollection($component)
{ {
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* @version $Revision$ * @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*/ */
class Doctrine_Hydrator_Default_RecordDriver extends Doctrine_Locator_Injectable class Doctrine_Hydrator_RecordDriver extends Doctrine_Locator_Injectable
{ {
protected $_collections = array(); protected $_collections = array();
......
...@@ -1018,14 +1018,14 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria ...@@ -1018,14 +1018,14 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
} }
/** /**
* _getSqlQueryBase * _buildSqlQueryBase
* returns the base of the generated sql query * returns the base of the generated sql query
* On mysql driver special strategy has to be used for DELETE statements * On mysql driver special strategy has to be used for DELETE statements
* (where is this special strategy??) * (where is this special strategy??)
* *
* @return string the base of the generated sql query * @return string the base of the generated sql query
*/ */
protected function _getSqlQueryBase() protected function _buildSqlQueryBase()
{ {
switch ($this->_type) { switch ($this->_type) {
case self::DELETE: case self::DELETE:
...@@ -1169,7 +1169,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria ...@@ -1169,7 +1169,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$needsSubQuery = false; $needsSubQuery = false;
$subquery = ''; $subquery = '';
$map = reset($this->_queryComponents); $map = reset($this->_queryComponents);
$table = $map['table']; $table = $map['table'];
$rootAlias = key($this->_queryComponents); $rootAlias = key($this->_queryComponents);
...@@ -1193,7 +1193,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria ...@@ -1193,7 +1193,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$this->_pendingFields = array(); $this->_pendingFields = array();
// build the basic query // build the basic query
$q = $this->_getSqlQueryBase(); $q = $this->_buildSqlQueryBase();
$q .= $this->_buildSqlFromPart(); $q .= $this->_buildSqlFromPart();
if ( ! empty($this->_sqlParts['set'])) { if ( ! empty($this->_sqlParts['set'])) {
...@@ -1355,8 +1355,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria ...@@ -1355,8 +1355,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$part = trim($part, "\"'`"); $part = trim($part, "\"'`");
if ($this->hasTableAlias($part)) { if ($this->hasSqlTableAlias($part)) {
$parts[$k] = $this->_conn->quoteIdentifier($this->generateNewTableAlias($part)); $parts[$k] = $this->_conn->quoteIdentifier($this->generateNewSqlTableAlias($part));
continue; continue;
} }
...@@ -1367,7 +1367,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria ...@@ -1367,7 +1367,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
foreach ($m[0] as $match) { foreach ($m[0] as $match) {
$e = explode('.', $match); $e = explode('.', $match);
$e[0] = $this->generateNewTableAlias($e[0]); $e[0] = $this->generateNewSqlTableAlias($e[0]);
$parts[$k] = str_replace($match, implode('.', $e), $parts[$k]); $parts[$k] = str_replace($match, implode('.', $e), $parts[$k]);
} }
......
...@@ -248,7 +248,7 @@ abstract class Doctrine_Query_Abstract ...@@ -248,7 +248,7 @@ abstract class Doctrine_Query_Abstract
$connection = Doctrine_Manager::getInstance()->getCurrentConnection(); $connection = Doctrine_Manager::getInstance()->getCurrentConnection();
} }
if ($hydrator === null) { if ($hydrator === null) {
$hydrator = new Doctrine_Hydrator_Default(); $hydrator = new Doctrine_Hydrator();
} }
$this->_conn = $connection; $this->_conn = $connection;
$this->_hydrator = $hydrator; $this->_hydrator = $hydrator;
...@@ -862,14 +862,29 @@ abstract class Doctrine_Query_Abstract ...@@ -862,14 +862,29 @@ abstract class Doctrine_Query_Abstract
* _execute * _execute
* *
* @param array $params * @param array $params
* @return void * @return PDOStatement The executed PDOStatement.
*/ */
protected function _execute($params) protected function _execute($params)
{ {
$params = $this->_conn->convertBooleans($params); $params = $this->_conn->convertBooleans($params);
if ( ! $this->_view) { if ( ! $this->_view) {
$query = $this->getSqlQuery($params); if ($this->_queryCache) {
$queryCacheDriver = $this->getQueryCacheDriver();
// calculate hash for dql query
$dql = $this->getDql();
$hash = md5($dql);
$cached = $queryCacheDriver->fetch($hash);
if ($cached) {
$query = $this->_constructQueryFromCache($cached);
} else {
$query = $this->getSqlQuery($params);
$serializedQuery = $this->getCachedForm($query);
$queryCacheDriver->save($hash, $serializedQuery, $this->_queryCacheTTL);
}
} else {
$query = $this->getSqlQuery($params);
}
} else { } else {
$query = $this->_view->getSelectSql(); $query = $this->_view->getSelectSql();
} }
...@@ -884,7 +899,7 @@ abstract class Doctrine_Query_Abstract ...@@ -884,7 +899,7 @@ abstract class Doctrine_Query_Abstract
if ($this->_type !== self::SELECT) { if ($this->_type !== self::SELECT) {
return $this->_conn->exec($query, $params); return $this->_conn->exec($query, $params);
} }
//echo $query . "<br /><br />";
$stmt = $this->_conn->execute($query, $params); $stmt = $this->_conn->execute($query, $params);
return $stmt; return $stmt;
} }
...@@ -916,32 +931,14 @@ abstract class Doctrine_Query_Abstract ...@@ -916,32 +931,14 @@ abstract class Doctrine_Query_Abstract
// cache miss // cache miss
$stmt = $this->_execute($params); $stmt = $this->_execute($params);
$this->_hydrator->setQueryComponents($this->_queryComponents); $this->_hydrator->setQueryComponents($this->_queryComponents);
$array = $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap, $result = $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap,
Doctrine::HYDRATE_ARRAY); Doctrine::HYDRATE_ARRAY);
$cached = $this->getCachedForm($array); $cached = $this->getCachedForm($result);
$cacheDriver->save($hash, $cached, $this->_resultCacheTTL); $cacheDriver->save($hash, $cached, $this->_resultCacheTTL);
return $result;
} else { } else {
$cached = unserialize($cached); return $this->_constructQueryFromCache($cached);
$this->_tableAliasMap = $cached[2];
$array = $cached[0];
$map = array();
foreach ($cached[1] as $k => $v) {
$e = explode('.', $v[0]);
if (count($e) === 1) {
$map[$k]['table'] = $this->_conn->getTable($e[0]);
} else {
$map[$k]['parent'] = $e[0];
$map[$k]['relation'] = $map[$e[0]]['table']->getRelation($e[1]);
$map[$k]['table'] = $map[$k]['relation']->getTable();
}
if (isset($v[1])) {
$map[$k]['agg'] = $v[1];
}
}
$this->_queryComponents = $map;
} }
} else { } else {
$stmt = $this->_execute($params); $stmt = $this->_execute($params);
...@@ -951,9 +948,45 @@ abstract class Doctrine_Query_Abstract ...@@ -951,9 +948,45 @@ abstract class Doctrine_Query_Abstract
} }
$this->_hydrator->setQueryComponents($this->_queryComponents); $this->_hydrator->setQueryComponents($this->_queryComponents);
$array = $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap, $hydrationMode); return $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap, $hydrationMode);
}
}
/**
* Constructs the query from the cached form.
*
* @param string The cached query, in a serialized form.
* @return array The custom component that was cached together with the essential
* query data. This can be either a result set (result caching)
* or an SQL query string (query caching).
*/
protected function _constructQueryFromCache($cached)
{
$cached = unserialize($cached);
$this->_tableAliasMap = $cached[2];
$customComponent = $cached[0];
$queryComponents = array();
$cachedComponents = $cached[1];
foreach ($cachedComponents as $alias => $components) {
$e = explode('.', $components[0]);
if (count($e) === 1) {
$queryComponents[$alias]['table'] = $this->_conn->getTable($e[0]);
} else {
$queryComponents[$alias]['parent'] = $e[0];
$queryComponents[$alias]['relation'] = $queryComponents[$e[0]]['table']->getRelation($e[1]);
$queryComponents[$alias]['table'] = $queryComponents[$alias]['relation']->getTable();
}
if (isset($v[1])) {
$queryComponents[$alias]['agg'] = $components[1];
}
if (isset($v[2])) {
$queryComponents[$alias]['map'] = $components[2];
}
} }
return $array; $this->_queryComponents = $queryComponents;
return $customComponent;
} }
/** /**
...@@ -963,22 +996,25 @@ abstract class Doctrine_Query_Abstract ...@@ -963,22 +996,25 @@ abstract class Doctrine_Query_Abstract
* @param array $resultSet * @param array $resultSet
* @return string serialized string representation of this query * @return string serialized string representation of this query
*/ */
public function getCachedForm(array $resultSet) public function getCachedForm($customComponent = null)
{ {
$map = array(); $componentInfo = array();
foreach ($this->getAliasMap() as $k => $v) { foreach ($this->getQueryComponents() as $alias => $components) {
if ( ! isset($v['parent'])) { if ( ! isset($components['parent'])) {
$map[$k][] = $v['table']->getComponentName(); $componentInfo[$alias][] = $components['table']->getComponentName();
} else { } else {
$map[$k][] = $v['parent'] . '.' . $v['relation']->getAlias(); $componentInfo[$alias][] = $components['parent'] . '.' . $components['relation']->getAlias();
} }
if (isset($v['agg'])) { if (isset($components['agg'])) {
$map[$k][] = $v['agg']; $componentInfo[$alias][] = $components['agg'];
}
if (isset($components['map'])) {
$componentInfo[$alias][] = $components['map'];
} }
} }
return serialize(array($resultSet, $map, $this->getTableAliasMap())); return serialize(array($customComponent, $componentInfo, $this->getTableAliasMap()));
} }
/** /**
...@@ -1468,7 +1504,7 @@ abstract class Doctrine_Query_Abstract ...@@ -1468,7 +1504,7 @@ abstract class Doctrine_Query_Abstract
*/ */
public function useResultCache($driver = true, $timeToLive = null) public function useResultCache($driver = true, $timeToLive = null)
{ {
if($driver !== null && $driver !== true && ! ($driver instanceOf Doctrine_Cache_Interface)){ if ($driver !== null && $driver !== true && ! ($driver instanceOf Doctrine_Cache_Interface)){
$msg = 'First argument should be instance of Doctrine_Cache_Interface or null.'; $msg = 'First argument should be instance of Doctrine_Cache_Interface or null.';
throw new Doctrine_Query_Exception($msg); throw new Doctrine_Query_Exception($msg);
} }
...@@ -1484,9 +1520,15 @@ abstract class Doctrine_Query_Abstract ...@@ -1484,9 +1520,15 @@ abstract class Doctrine_Query_Abstract
* @param integer $timeToLive how long the cache entry is valid * @param integer $timeToLive how long the cache entry is valid
* @return Doctrine_Hydrate this object * @return Doctrine_Hydrate this object
*/ */
public function useQueryCache($driver = null, $timeToLive = null) public function useQueryCache($driver = true, $timeToLive = null)
{ {
throw new Doctrine_Query_Exception("Not yet implemented."); if ($driver !== null && $driver !== true && ! ($driver instanceof Doctrine_Cache_Interface)){
$msg = 'First argument should be instance of Doctrine_Cache_Interface or null.';
throw new Doctrine_Query_Exception($msg);
}
$this->_queryCache = $driver;
return $this->setQueryCacheLifeSpan($timeToLive);
} }
/** /**
......
...@@ -33,6 +33,24 @@ ...@@ -33,6 +33,24 @@
class Doctrine_Query_Cache_TestCase extends Doctrine_UnitTestCase class Doctrine_Query_Cache_TestCase extends Doctrine_UnitTestCase
{ {
public function testQueryCacheAddsQueryIntoCache()
{
$cache = new Doctrine_Cache_Array();
$q = new Doctrine_Query();
$q->select('u.name')->from('User u')->leftJoin('u.Phonenumber p')
->useQueryCache($cache);
$coll = $q->execute();
$this->assertEqual($cache->count(), 1);
$this->assertEqual(count($coll), 8);
$coll = $q->execute();
$this->assertEqual($cache->count(), 1);
$this->assertEqual(count($coll), 8);
}
public function testResultSetCacheAddsResultSetsIntoCache() public function testResultSetCacheAddsResultSetsIntoCache()
{ {
$q = new Doctrine_Query(); $q = new Doctrine_Query();
...@@ -86,7 +104,8 @@ class Doctrine_Query_Cache_TestCase extends Doctrine_UnitTestCase ...@@ -86,7 +104,8 @@ class Doctrine_Query_Cache_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($cache->count(), 1); $this->assertEqual($cache->count(), 1);
$this->assertEqual(count($coll), 1); $this->assertEqual(count($coll), 1);
} }
public function testUseCacheSupportsBooleanTrueAsParameter() public function testUseCacheSupportsBooleanTrueAsParameter()
{ {
$q = new Doctrine_Query(); $q = new Doctrine_Query();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment