Commit 352ab0de authored by romanb's avatar romanb

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

parent 896b9915
......@@ -32,7 +32,7 @@
* @version $Revision: 3192 $
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*/
class Doctrine_Hydrator_Default extends Doctrine_Hydrator_Abstract
class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
{
/**
* hydrateResultSet
......@@ -73,9 +73,9 @@ class Doctrine_Hydrator_Default extends Doctrine_Hydrator_Abstract
}
if ($hydrationMode === Doctrine::HYDRATE_ARRAY) {
$driver = new Doctrine_Hydrator_Default_ArrayDriver();
$driver = new Doctrine_Hydrator_ArrayDriver();
} else {
$driver = new Doctrine_Hydrator_Default_RecordDriver();
$driver = new Doctrine_Hydrator_RecordDriver();
}
$event = new Doctrine_Event(null, Doctrine_Event::HYDRATE, null);
......
......@@ -31,7 +31,7 @@
* @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*/
class Doctrine_Hydrator_Default_ArrayDriver
class Doctrine_Hydrator_ArrayDriver
{
public function getElementCollection($component)
{
......
......@@ -31,7 +31,7 @@
* @version $Revision$
* @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();
......
......@@ -1018,14 +1018,14 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
}
/**
* _getSqlQueryBase
* _buildSqlQueryBase
* returns the base of the generated sql query
* On mysql driver special strategy has to be used for DELETE statements
* (where is this special strategy??)
*
* @return string the base of the generated sql query
*/
protected function _getSqlQueryBase()
protected function _buildSqlQueryBase()
{
switch ($this->_type) {
case self::DELETE:
......@@ -1193,7 +1193,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$this->_pendingFields = array();
// build the basic query
$q = $this->_getSqlQueryBase();
$q = $this->_buildSqlQueryBase();
$q .= $this->_buildSqlFromPart();
if ( ! empty($this->_sqlParts['set'])) {
......@@ -1355,8 +1355,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$part = trim($part, "\"'`");
if ($this->hasTableAlias($part)) {
$parts[$k] = $this->_conn->quoteIdentifier($this->generateNewTableAlias($part));
if ($this->hasSqlTableAlias($part)) {
$parts[$k] = $this->_conn->quoteIdentifier($this->generateNewSqlTableAlias($part));
continue;
}
......@@ -1367,7 +1367,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
foreach ($m[0] as $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]);
}
......
......@@ -248,7 +248,7 @@ abstract class Doctrine_Query_Abstract
$connection = Doctrine_Manager::getInstance()->getCurrentConnection();
}
if ($hydrator === null) {
$hydrator = new Doctrine_Hydrator_Default();
$hydrator = new Doctrine_Hydrator();
}
$this->_conn = $connection;
$this->_hydrator = $hydrator;
......@@ -862,14 +862,29 @@ abstract class Doctrine_Query_Abstract
* _execute
*
* @param array $params
* @return void
* @return PDOStatement The executed PDOStatement.
*/
protected function _execute($params)
{
$params = $this->_conn->convertBooleans($params);
if ( ! $this->_view) {
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 {
$query = $this->_view->getSelectSql();
}
......@@ -884,7 +899,7 @@ abstract class Doctrine_Query_Abstract
if ($this->_type !== self::SELECT) {
return $this->_conn->exec($query, $params);
}
//echo $query . "<br /><br />";
$stmt = $this->_conn->execute($query, $params);
return $stmt;
}
......@@ -916,44 +931,62 @@ abstract class Doctrine_Query_Abstract
// cache miss
$stmt = $this->_execute($params);
$this->_hydrator->setQueryComponents($this->_queryComponents);
$array = $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap,
$result = $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap,
Doctrine::HYDRATE_ARRAY);
$cached = $this->getCachedForm($array);
$cached = $this->getCachedForm($result);
$cacheDriver->save($hash, $cached, $this->_resultCacheTTL);
return $result;
} else {
return $this->_constructQueryFromCache($cached);
}
} else {
$stmt = $this->_execute($params);
if (is_integer($stmt)) {
return $stmt;
}
$this->_hydrator->setQueryComponents($this->_queryComponents);
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];
$array = $cached[0];
$customComponent = $cached[0];
$map = array();
foreach ($cached[1] as $k => $v) {
$e = explode('.', $v[0]);
$queryComponents = array();
$cachedComponents = $cached[1];
foreach ($cachedComponents as $alias => $components) {
$e = explode('.', $components[0]);
if (count($e) === 1) {
$map[$k]['table'] = $this->_conn->getTable($e[0]);
$queryComponents[$alias]['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();
$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])) {
$map[$k]['agg'] = $v[1];
$queryComponents[$alias]['agg'] = $components[1];
}
if (isset($v[2])) {
$queryComponents[$alias]['map'] = $components[2];
}
$this->_queryComponents = $map;
}
} else {
$stmt = $this->_execute($params);
$this->_queryComponents = $queryComponents;
if (is_integer($stmt)) {
return $stmt;
}
$this->_hydrator->setQueryComponents($this->_queryComponents);
$array = $this->_hydrator->hydrateResultSet($stmt, $this->_tableAliasMap, $hydrationMode);
}
return $array;
return $customComponent;
}
/**
......@@ -963,22 +996,25 @@ abstract class Doctrine_Query_Abstract
* @param array $resultSet
* @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) {
if ( ! isset($v['parent'])) {
$map[$k][] = $v['table']->getComponentName();
foreach ($this->getQueryComponents() as $alias => $components) {
if ( ! isset($components['parent'])) {
$componentInfo[$alias][] = $components['table']->getComponentName();
} else {
$map[$k][] = $v['parent'] . '.' . $v['relation']->getAlias();
$componentInfo[$alias][] = $components['parent'] . '.' . $components['relation']->getAlias();
}
if (isset($components['agg'])) {
$componentInfo[$alias][] = $components['agg'];
}
if (isset($v['agg'])) {
$map[$k][] = $v['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
*/
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.';
throw new Doctrine_Query_Exception($msg);
}
......@@ -1484,9 +1520,15 @@ abstract class Doctrine_Query_Abstract
* @param integer $timeToLive how long the cache entry is valid
* @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 @@
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()
{
$q = new Doctrine_Query();
......@@ -87,6 +105,7 @@ class Doctrine_Query_Cache_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($cache->count(), 1);
$this->assertEqual(count($coll), 1);
}
public function testUseCacheSupportsBooleanTrueAsParameter()
{
$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