diff --git a/lib/Doctrine/Adapter/Mock.php b/lib/Doctrine/Adapter/Mock.php index a2971ad96..b1c8becf5 100644 --- a/lib/Doctrine/Adapter/Mock.php +++ b/lib/Doctrine/Adapter/Mock.php @@ -31,7 +31,7 @@ * @since 1.0 * @version $Revision$ */ -class Doctrine_Adapter_Mock implements Doctrine_Adapter_Interface +class Doctrine_Adapter_Mock implements Doctrine_Adapter_Interface, Countable { private $name; @@ -59,7 +59,10 @@ class Doctrine_Adapter_Mock implements Doctrine_Adapter_Interface } public function prepare($query) { - return new Doctrine_Adapter_Statement_Mock($this, $query); + $mock = new Doctrine_Adapter_Statement_Mock($this, $query); + $mock->queryString = $query; + + return $mock; } public function addQuery($query) { @@ -79,7 +82,10 @@ class Doctrine_Adapter_Mock implements Doctrine_Adapter_Interface throw new $name($e[1], $e[2]); } - return new Doctrine_Adapter_Statement_Mock($this, $query); + $stmt = new Doctrine_Adapter_Statement_Mock($this, $query); + $stmt->queryString = $query; + + return $stmt; } public function getAll() { @@ -122,6 +128,10 @@ class Doctrine_Adapter_Mock implements Doctrine_Adapter_Interface return 1; } } + public function count() + { + return count($this->queries); + } public function beginTransaction() { $this->queries[] = 'BEGIN TRANSACTION'; diff --git a/lib/Doctrine/Adapter/Statement/Mock.php b/lib/Doctrine/Adapter/Statement/Mock.php index b8ed9b646..3104becd6 100644 --- a/lib/Doctrine/Adapter/Statement/Mock.php +++ b/lib/Doctrine/Adapter/Statement/Mock.php @@ -35,12 +35,11 @@ class Doctrine_Adapter_Statement_Mock { private $mock; - private $query; + public $queryString; - public function __construct(Doctrine_Adapter_Mock $mock, $query) + public function __construct($mock) { $this->mock = $mock; - $this->query = $query; } public function fetch($fetchMode) { @@ -52,7 +51,9 @@ class Doctrine_Adapter_Statement_Mock } public function execute() { - $this->mock->addQuery($this->query); + if(is_object($this->mock)) { + $this->mock->addQuery($this->queryString); + } return true; } public function fetchColumn($colnum = 0) diff --git a/lib/Doctrine/Cache.php b/lib/Doctrine/Cache.php index d7202ec51..6aa809eef 100644 --- a/lib/Doctrine/Cache.php +++ b/lib/Doctrine/Cache.php @@ -41,6 +41,8 @@ class Doctrine_Cache extends Doctrine_Db_EventListener implements Countable, Ite protected $_driver; + protected $_data; + public function __construct($driverName, $options = array()) { $class = 'Doctrine_Cache_' . ucwords(strtolower($driverName)); @@ -51,10 +53,17 @@ class Doctrine_Cache extends Doctrine_Db_EventListener implements Countable, Ite $this->_driver = new $class($options); } + + + public function getDriver() + { + return $this->_driver; + } /** * addQuery * - * @param string $query sql query string + * @param string|array $query sql query string + * @param string $namespace connection namespace * @return void */ public function add($query, $namespace = null) @@ -134,6 +143,9 @@ class Doctrine_Cache extends Doctrine_Db_EventListener implements Countable, Ite $stats = array(); foreach ($queries as $query) { + if (is_array($query)) { + $query = $query[0]; + } if (isset($stats[$query])) { $stats[$query]++; } else { @@ -143,7 +155,7 @@ class Doctrine_Cache extends Doctrine_Db_EventListener implements Countable, Ite sort($stats); $i = $this->_options['size']; - + while ($i--) { $element = next($stats); $query = key($stats); @@ -166,15 +178,34 @@ class Doctrine_Cache extends Doctrine_Db_EventListener implements Countable, Ite public function onPreQuery(Doctrine_Db_Event $event) { + $query = $event->getQuery(); + + // only process SELECT statements + if (substr(trim(strtoupper($query)), 0, 6) == 'SELECT') { + $this->add($query, $event->getInvoker()->getName()); + + $data = $this->_driver->fetch(md5($query)); + + $this->_data = $data; + + return true; + } + + return false; } + public function onQuery(Doctrine_Db_Event $event) - { - $this->add($event->getQuery(), $event->getInvoker()->getName()); + { + } + public function onPreFetchAll(Doctrine_Db_Event $event) + { + return $this->_data; + } public function onPrePrepare(Doctrine_Db_Event $event) - { + { } public function onPrepare(Doctrine_Db_Event $event) @@ -187,16 +218,29 @@ class Doctrine_Cache extends Doctrine_Db_EventListener implements Countable, Ite } public function onExec(Doctrine_Db_Event $event) - { + { } public function onPreExecute(Doctrine_Db_Event $event) { + $query = $event->getQuery(); + + // only process SELECT statements + if (substr(trim(strtoupper($query)), 0, 6) == 'SELECT') { + $this->add($query, $event->getInvoker()->getDbh()->getName()); + + $data = $this->_driver->fetch(md5(serialize(array($query, $event->getParams())))); + + $this->_data = $data; + + return true; + } + + return false; } public function onExecute(Doctrine_Db_Event $event) - { - $this->add($event->getQuery(), $event->getInvoker()->getName()); + { } } diff --git a/lib/Doctrine/Cache/Apc.php b/lib/Doctrine/Cache/Apc.php index 87c379041..e0ee5e691 100644 --- a/lib/Doctrine/Cache/Apc.php +++ b/lib/Doctrine/Cache/Apc.php @@ -86,7 +86,7 @@ class Doctrine_Cache_Apc extends Doctrine_Cache_Driver * @param int $lifeTime if != false, set a specific lifetime for this cache record (null => infinite lifeTime) * @return boolean true if no problem */ - public function save($data, $id, $lifeTime = false) + public function save($id, $data, $lifeTime = false) { $lifeTime = $this->getLifeTime($lifeTime); diff --git a/lib/Doctrine/Cache/Array.php b/lib/Doctrine/Cache/Array.php index 3039ea18f..b79046f93 100644 --- a/lib/Doctrine/Cache/Array.php +++ b/lib/Doctrine/Cache/Array.php @@ -74,7 +74,7 @@ class Doctrine_Cache_Array * @param int $lifeTime if != false, set a specific lifetime for this cache record (null => infinite lifeTime) * @return boolean true if no problem */ - public function save($data, $id, $lifeTime = false) + public function save($id, $data, $lifeTime = false) { $this->data[$id] = $data; } diff --git a/lib/Doctrine/Cache/Memcache.php b/lib/Doctrine/Cache/Memcache.php index 1c5f11812..92b7acbdc 100644 --- a/lib/Doctrine/Cache/Memcache.php +++ b/lib/Doctrine/Cache/Memcache.php @@ -109,7 +109,7 @@ class Doctrine_Cache_Memcache extends Doctrine_Cache_Driver * @param int $lifeTime if != false, set a specific lifetime for this cache record (null => infinite lifeTime) * @return boolean true if no problem */ - public function save($data, $id, $lifeTime = false) + public function save($id, $data, $lifeTime = false) { $lifeTime = $this->getLifeTime($specificLifeTime); diff --git a/lib/Doctrine/Db.php b/lib/Doctrine/Db.php index ee7e88225..2ef5c1a94 100644 --- a/lib/Doctrine/Db.php +++ b/lib/Doctrine/Db.php @@ -74,15 +74,13 @@ class Doctrine_Db implements Countable, IteratorAggregate, Doctrine_Adapter_Inte * listener for listening events */ protected $listener; - /** - * @var integer $querySequence - */ - protected $querySequence = 0; /** * @var string $name name of this connection * @see Doctrine_Manager::openConnection() */ protected $name; + + protected $count = 0; private static $driverMap = array('oracle' => 'oci8', @@ -120,17 +118,10 @@ class Doctrine_Db implements Countable, IteratorAggregate, Doctrine_Adapter_Inte $this->options['password'] = $pass; $this->listener = new Doctrine_Db_EventListener(); } - - public function nextQuerySequence() + + public function incrementQueryCount() { - return ++$this->querySequence; - } - /** - * getQuerySequence - */ - public function getQuerySequence() - { - return $this->querySequence; + $this->count++; } /** * getDbh @@ -139,6 +130,15 @@ class Doctrine_Db implements Countable, IteratorAggregate, Doctrine_Adapter_Inte { return $this->dbh; } + /** + * getAdapter + * + * @return Doctrine_Adapter_Interface|PDO $adapter + */ + public function getAdapter() + { + return $this->dbh; + } /** * setAdapter * @@ -410,8 +410,6 @@ class Doctrine_Db implements Countable, IteratorAggregate, Doctrine_Adapter_Inte $this->listener->onPrepare($event); - $this->querySequence++; - return new Doctrine_Db_Statement($this, $stmt); } /** @@ -426,16 +424,23 @@ class Doctrine_Db implements Countable, IteratorAggregate, Doctrine_Adapter_Inte $event = new Doctrine_Db_Event($this, Doctrine_Db_Event::QUERY, $statement); - $this->listener->onPreQuery($event); + $skip = $this->listener->onPreQuery($event); if ( ! empty($params)) { - $stmt = $this->dbh->query($statement)->execute($params); + $stmt = $this->dbh->prepare($statement); + return $stmt->execute($params); } else { - $stmt = $this->dbh->query($statement); + if ( ! $skip) { + $stmt = $this->dbh->query($statement); + $this->count++; + } else { + $stmt = new stdClass; + $stmt->queryString = $statement; + } + $stmt = new Doctrine_Db_Statement($this, $stmt); } - $this->listener->onQuery($event); - $this->querySequence++; + $this->listener->onQuery($event); return $stmt; } @@ -471,6 +476,8 @@ class Doctrine_Db implements Countable, IteratorAggregate, Doctrine_Adapter_Inte $rows = $this->dbh->exec($statement); + $this->count++; + $this->listener->onExec($event); return $rows; @@ -591,8 +598,9 @@ class Doctrine_Db implements Countable, IteratorAggregate, Doctrine_Adapter_Inte */ public function getIterator() { - if ($this->listener instanceof Doctrine_Db_Profiler) + if ($this->listener instanceof Doctrine_Db_Profiler) { return $this->listener; + } } /** * count @@ -602,6 +610,6 @@ class Doctrine_Db implements Countable, IteratorAggregate, Doctrine_Adapter_Inte */ public function count() { - return $this->querySequence; + return $this->count; } } diff --git a/lib/Doctrine/Db/EventListener/Chain.php b/lib/Doctrine/Db/EventListener/Chain.php index db0c85e20..5ed67511c 100644 --- a/lib/Doctrine/Db/EventListener/Chain.php +++ b/lib/Doctrine/Db/EventListener/Chain.php @@ -87,9 +87,16 @@ class Doctrine_Db_EventListener_Chain extends Doctrine_Access implements Doctrin } public function onPreQuery(Doctrine_Db_Event $event) { + $return = null; + foreach ($this->listeners as $listener) { - $listener->onPreQuery($event); + $tmp = $listener->onPreQuery($event); + + if ($tmp !== null) { + $return = $tmp; + } } + return $return; } public function onPreExec(Doctrine_Db_Event $event) @@ -145,9 +152,16 @@ class Doctrine_Db_EventListener_Chain extends Doctrine_Access implements Doctrin public function onPreFetchAll(Doctrine_Db_Event $event) { + $return = null; + foreach ($this->listeners as $listener) { - $listener->onPreFetchAll($event); + $tmp = $listener->onPreFetchAll($event); + + if ($tmp !== null) { + $return = $tmp; + } } + return $return; } public function onFetchAll(Doctrine_Db_Event $event) { @@ -184,9 +198,16 @@ class Doctrine_Db_EventListener_Chain extends Doctrine_Access implements Doctrin public function onPreExecute(Doctrine_Db_Event $event) { + $return = null; + foreach ($this->listeners as $listener) { - $listener->onPreExecute($event); + $tmp = $listener->onPreExecute($event); + + if ($tmp !== null) { + $return = $tmp; + } } + return $return; } public function onExecute(Doctrine_Db_Event $event) { diff --git a/lib/Doctrine/Db/Profiler.php b/lib/Doctrine/Db/Profiler.php index f60f98b95..b8b753e02 100644 --- a/lib/Doctrine/Db/Profiler.php +++ b/lib/Doctrine/Db/Profiler.php @@ -30,7 +30,7 @@ Doctrine::autoload('Doctrine_Overloadable'); * @since 1.0 * @version $Revision$ */ -class Doctrine_Db_Profiler extends Doctrine_Access implements Doctrine_Overloadable, IteratorAggregate +class Doctrine_Db_Profiler extends Doctrine_Access implements Doctrine_Overloadable, IteratorAggregate, Countable { /** * @param array $listeners an array containing all availible listeners @@ -109,11 +109,10 @@ class Doctrine_Db_Profiler extends Doctrine_Access implements Doctrine_Overloada */ if ( ! is_null($this->filterTypes)) { if ( ! ($a[0]->getQueryType() & $this->_filterTypes)) { - return false; + } } - - return true; + } /** * get @@ -148,6 +147,15 @@ class Doctrine_Db_Profiler extends Doctrine_Access implements Doctrine_Overloada { return new ArrayIterator($this->events); } + /** + * count + * + * @return integer + */ + public function count() + { + return count($this->events); + } /** * pop the last event from the event stack * diff --git a/lib/Doctrine/Db/Statement.php b/lib/Doctrine/Db/Statement.php index e6dbc2834..e50aa2cf5 100644 --- a/lib/Doctrine/Db/Statement.php +++ b/lib/Doctrine/Db/Statement.php @@ -42,7 +42,13 @@ class Doctrine_Db_Statement implements Doctrine_Adapter_Statement_Interface $this->adapter = $adapter; $this->stmt = $stmt; } - + /** + * + */ + public function getDbh() + { + return $this->adapter; + } public function getQuery() { return $this->stmt->queryString; @@ -62,9 +68,9 @@ class Doctrine_Db_Statement implements Doctrine_Adapter_Statement_Interface public function bindColumn($column, $param, $type = null) { if($type === null) { - return $this->stmt->bindValue($column, $param); + return $this->stmt->bindColumn($column, $param); } else { - return $this->stmt->bindValue($column, $param, $type); + return $this->stmt->bindColumn($column, $param, $type); } } /** @@ -187,9 +193,12 @@ class Doctrine_Db_Statement implements Doctrine_Adapter_Statement_Interface { $event = new Doctrine_Db_Event($this, Doctrine_Db_Event::EXECUTE, $this->stmt->queryString, $params); - $this->adapter->getListener()->onPreExecute($event); + $skip = $this->adapter->getListener()->onPreExecute($event); - $this->stmt->execute($params); + if ( ! $skip) { + $this->stmt->execute($params); + $this->adapter->incrementQueryCount(); + } $this->adapter->getListener()->onExecute($event); @@ -242,11 +251,21 @@ class Doctrine_Db_Statement implements Doctrine_Adapter_Statement_Interface public function fetchAll($fetchStyle = Doctrine::FETCH_BOTH, $columnIndex = null) { - if($columnIndex !== null) { - return $this->stmt->fetchAll($fetchStyle, $columnIndex); - } else { - return $this->stmt->fetchAll($fetchStyle); + $event = new Doctrine_Db_Event($this, Doctrine_Db_Event::FETCHALL, $this->stmt->queryString, array($fetchStyle, $columnIndex)); + + $data = $this->adapter->getListener()->onPreFetchAll($event); + + if ($data === null) { + if ($columnIndex !== null) { + $data = $this->stmt->fetchAll($fetchStyle, $columnIndex); + } else { + $data = $this->stmt->fetchAll($fetchStyle); + } } + + $this->adapter->getListener()->onFetchAll($event); + + return $data; } /** * fetchColumn diff --git a/tests/CacheTestCase.php b/tests/CacheTestCase.php index 5996995a5..3cbba8492 100644 --- a/tests/CacheTestCase.php +++ b/tests/CacheTestCase.php @@ -39,13 +39,48 @@ class Doctrine_Cache_TestCase extends Doctrine_UnitTestCase { } public function prepareData() { } - + /** public function testAdapterQueryAddsQueriesToCacheStack() { $this->dbh->query('SELECT * FROM user'); $this->assertEqual($this->cache->getAll(), array('main' => array('SELECT * FROM user'))); } + */ + public function testAdapterQueryChecksCache() + { + $query = 'SELECT * FROM user'; + + $resultSet = array(array('name' => 'John'), array('name' => 'Arnold')); + + $this->cache->getDriver()->save(md5($query), $resultSet); + + $count = $this->dbh->getAdapter()->count(); + + $stmt = $this->dbh->query($query); + $data = $stmt->fetchAll(Doctrine::FETCH_ASSOC); + + $this->assertEqual($data, $resultSet); + $this->assertEqual($this->dbh->getAdapter()->count(), $count); + } + public function testAdapterStatementExecuteChecksCache() + { + $query = 'SELECT * FROM user WHERE id = ?'; + $params = array(1); + $resultSet = array(array('name' => 'John'), array('name' => 'Arnold')); + + $this->cache->getDriver()->save(md5(serialize(array($query, $params))), $resultSet); + + $count = $this->dbh->getAdapter()->count(); + + $stmt = $this->dbh->prepare($query); + $stmt->execute($params); + $data = $stmt->fetchAll(Doctrine::FETCH_ASSOC); + + $this->assertEqual($data, $resultSet); + $this->assertEqual($this->dbh->getAdapter()->count(), $count); + } + /** public function testAdapterStatementExecuteAddsQueriesToCacheStack() { $stmt = $this->dbh->prepare('SELECT * FROM user'); @@ -54,13 +89,22 @@ class Doctrine_Cache_TestCase extends Doctrine_UnitTestCase $this->assertEqual($this->cache->getAll(), array('main' => array('SELECT * FROM user'))); } + public function testAdapterStatementFetchCallsCacheFetch() + { + $stmt = $this->dbh->prepare('SELECT * FROM user'); + + $stmt->execute(); + + $a = $stmt->fetchAll(); + } + */ public function setUp() { parent::setUp(); if ( ! isset($this->cache)) { $this->cache = new Doctrine_Cache('Array'); - + $this->dbh->setAdapter(new Doctrine_Adapter_Mock()); $this->dbh->addListener($this->cache); } diff --git a/tests/UnitTestCase.php b/tests/UnitTestCase.php index 8fa58bb5c..956ffcee2 100644 --- a/tests/UnitTestCase.php +++ b/tests/UnitTestCase.php @@ -7,7 +7,7 @@ class Doctrine_UnitTestCase extends UnitTestCase { protected $old; protected $dbh; protected $listener; - protected $cache; + protected $users; protected $valueHolder; protected $tables = array(); diff --git a/tests/run.php b/tests/run.php index 9c30a1625..83e81b85d 100644 --- a/tests/run.php +++ b/tests/run.php @@ -214,12 +214,12 @@ $test->addTestCase(new Doctrine_Query_JoinCondition_TestCase()); $test->addTestCase(new Doctrine_ColumnAlias_TestCase()); $test->addTestCase(new Doctrine_Query_Subquery_TestCase()); $test->addTestCase(new Doctrine_Query_Orderby_TestCase()); -/** + $test->addTestCase(new Doctrine_Cache_TestCase()); $test->addTestCase(new Doctrine_Cache_Apc_TestCase()); $test->addTestCase(new Doctrine_Cache_Memcache_TestCase()); $test->addTestCase(new Doctrine_Cache_Sqlite_TestCase()); -*/ + // Cache tests //$test->addTestCase(new Doctrine_Cache_Query_SqliteTestCase()); //$test->addTestCase(new Doctrine_Cache_FileTestCase());