Skip to content

Commit

Permalink
DBAL-11 - Changed Interface of SQLLogger to allow for timing variable…
Browse files Browse the repository at this point in the history
…s, added tests for logging. Contract of Loggers changed, they are not called before the query but after the query they are logging, which means queries that fail wont appear in the logs.
  • Loading branch information
beberlei committed Jun 20, 2010
1 parent 93ad4c2 commit fe0f0e4
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 17 deletions.
18 changes: 14 additions & 4 deletions lib/Doctrine/DBAL/Connection.php
Expand Up @@ -552,8 +552,9 @@ public function executeQuery($query, array $params = array(), $types = array())
{
$this->connect();

if ($this->_config->getSQLLogger() !== null) {
$this->_config->getSQLLogger()->logSQL($query, $params);
$hasLogger = $this->_config->getSQLLogger() !== null;
if ($hasLogger) {
$queryStart = microtime(true);
}

if ($params) {
Expand All @@ -568,6 +569,10 @@ public function executeQuery($query, array $params = array(), $types = array())
$stmt = $this->_conn->query($query);
}

if ($hasLogger) {
$this->_config->getSQLLogger()->logSQL($query, $params, microtime(true) - $queryStart);
}

return $stmt;
}

Expand Down Expand Up @@ -624,8 +629,9 @@ public function executeUpdate($query, array $params = array(), array $types = ar
{
$this->connect();

if ($this->_config->getSQLLogger() !== null) {
$this->_config->getSQLLogger()->logSQL($query, $params);
$hasLogger = $this->_config->getSQLLogger() !== null;
if ($hasLogger) {
$queryStart = microtime(true);
}

if ($params) {
Expand All @@ -641,6 +647,10 @@ public function executeUpdate($query, array $params = array(), array $types = ar
$result = $this->_conn->exec($query);
}

if ($hasLogger) {
$this->_config->getSQLLogger()->logSQL($query, $params, microtime(true) - $queryStart);
}

return $result;
}

Expand Down
4 changes: 2 additions & 2 deletions lib/Doctrine/DBAL/Logging/DebugStack.php
Expand Up @@ -44,10 +44,10 @@ class DebugStack implements SQLLogger
/**
* {@inheritdoc}
*/
public function logSQL($sql, array $params = null)
public function logSQL($sql, array $params = null, $executionMS = null)
{
if ($this->enabled) {
$this->queries[] = array('sql' => $sql, 'params' => $params);
$this->queries[] = array('sql' => $sql, 'params' => $params, 'executionMS' => $executionMS);
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion lib/Doctrine/DBAL/Logging/EchoSQLLogger.php
Expand Up @@ -38,12 +38,14 @@ class EchoSQLLogger implements SQLLogger
/**
* {@inheritdoc}
*/
public function logSQL($sql, array $params = null)
public function logSQL($sql, array $params = null, $executionMS = null)
{
echo $sql . PHP_EOL;

if ($params) {
var_dump($params);
}

echo "Took " . number_format($executionMS, 4) . " seconds" . PHP_EOL;
}
}
6 changes: 4 additions & 2 deletions lib/Doctrine/DBAL/Logging/SQLLogger.php
Expand Up @@ -23,7 +23,7 @@

/**
* Interface for SQL loggers.
*
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
Expand All @@ -40,6 +40,8 @@ interface SQLLogger
*
* @param string $sql The SQL to be executed.
* @param array $params The SQL parameters.
* @param float $executionMS The microtime difference it took to execute this query.
* @return void
*/
function logSQL($sql, array $params = null);
function logSQL($sql, array $params = null, $executionMS = null);
}
15 changes: 11 additions & 4 deletions lib/Doctrine/DBAL/Statement.php
Expand Up @@ -123,11 +123,18 @@ public function bindParam($name, &$var, $type = PDO::PARAM_STR)
*/
public function execute($params = null)
{
if ($this->_conn->getConfiguration()->getSQLLogger()) {
$this->_conn->getConfiguration()->getSQLLogger()->logSQL($this->_sql, $this->_params);
}
$this->_params = array();
return $this->_stmt->execute($params);
$hasLogger = $this->_conn->getConfiguration()->getSQLLogger();
if ($hasLogger) {
$queryStart = microtime(true);
}

$stmt = $this->_stmt->execute($params);

if ($hasLogger) {
$this->_conn->getConfiguration()->getSQLLogger()->logSQL($this->_sql, $this->_params, microtime(true) - $queryStart);
}
return $stmt;
}

/**
Expand Down
24 changes: 24 additions & 0 deletions tests/Doctrine/Tests/DBAL/ConnectionTest.php
Expand Up @@ -115,4 +115,28 @@ public function testConnectDispatchEvent()
$conn = new Connection(array('platform' => $platform), $driverMock, new Configuration(), $eventManager);
$conn->connect();
}

/**
* Pretty dumb test, however we want to check that the EchoSQLLogger correctly implements the interface.
*
* @group DBAL-11
*/
public function testEchoSQLLogger()
{
$logger = new \Doctrine\DBAL\Logging\EchoSQLLogger();
$this->_conn->getConfiguration()->setSQLLogger($logger);
$this->assertSame($logger, $this->_conn->getConfiguration()->getSQLLogger());
}

/**
* Pretty dumb test, however we want to check that the DebugStack correctly implements the interface.
*
* @group DBAL-11
*/
public function testDebugSQLStack()
{
$logger = new \Doctrine\DBAL\Logging\DebugStack();
$this->_conn->getConfiguration()->setSQLLogger($logger);
$this->assertSame($logger, $this->_conn->getConfiguration()->getSQLLogger());
}
}
1 change: 1 addition & 0 deletions tests/Doctrine/Tests/DBAL/Functional/AllTests.php
Expand Up @@ -29,6 +29,7 @@ public static function suite()
$suite->addTestSuite('Doctrine\Tests\DBAL\Functional\ConnectionTest');
$suite->addTestSuite('Doctrine\Tests\DBAL\Functional\DataAccessTest');
$suite->addTestSuite('Doctrine\Tests\DBAL\Functional\WriteTest');
$suite->addTestSuite('Doctrine\Tests\DBAL\Functional\LoggingTest');

return $suite;
}
Expand Down
34 changes: 34 additions & 0 deletions tests/Doctrine/Tests/DBAL/Functional/LoggingTest.php
@@ -0,0 +1,34 @@
<?php

namespace Doctrine\Tests\DBAL\Functional;

require_once __DIR__ . '/../../TestInit.php';

class LoggingTest extends \Doctrine\Tests\DbalFunctionalTestCase
{
public function testLogExecuteQuery()
{
$sql = $this->_conn->getDatabasePlatform()->getDummySelectSQL();

$logMock = $this->getMock('Doctrine\DBAL\Logging\SQLLogger');
$logMock->expects($this->once())
->method('logSQL')
->with($this->equalTo($sql), $this->equalTo(array()), $this->isType('float'));
$this->_conn->getConfiguration()->setSQLLogger($logMock);
$this->_conn->executeQuery($sql, array());
}

public function testLogPrepareExecute()
{
$sql = $this->_conn->getDatabasePlatform()->getDummySelectSQL();

$logMock = $this->getMock('Doctrine\DBAL\Logging\SQLLogger');
$logMock->expects($this->once())
->method('logSQL')
->with($this->equalTo($sql), $this->equalTo(array()), $this->isType('float'));
$this->_conn->getConfiguration()->setSQLLogger($logMock);

$stmt = $this->_conn->prepare($sql);
$stmt->execute();
}
}
Expand Up @@ -23,13 +23,10 @@ protected function setUp()
$testClass = end($e);
$dbms = strtolower(str_replace('SchemaManagerTest', null, $testClass));

if ($this->_conn->getDatabasePlatform()->getName() !== $dbms)
{
if ($this->_conn->getDatabasePlatform()->getName() !== $dbms) {
$this->markTestSkipped('The ' . $testClass .' requires the use of ' . $dbms);
}

#$this->_conn->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);

$this->_sm = $this->_conn->getSchemaManager();
}

Expand Down

1 comment on commit fe0f0e4

@mridgway
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes it very difficult to tell which query is failing if you get a query exception.

Wouldn't it make more sense to change the interface for the SQLLogger class to have a queryStart() and a queryEnd() function? This way ALL queries can be logged, and timing isn't something that happens automatically, but is left up to the logger if it chooses to do so.

Please sign in to comment.