Browse Source

Merge pull request #3751 from cakephp/3.0-no-sql-dump

3.0 - log queries with errors
José Lorenzo Rodríguez 11 years ago
parent
commit
8a6b3ecff3

+ 7 - 0
src/Database/Log/LoggedQuery.php

@@ -51,6 +51,13 @@ class LoggedQuery {
 	public $numRows = 0;
 
 /**
+ * The exception that was thrown by the execution of this query
+ *
+ * @var \Exception
+ */
+	public $error;
+
+/**
  * Returns the string representation of this logged query
  *
  * @return void

+ 24 - 5
src/Database/Log/LoggingStatement.php

@@ -46,16 +46,35 @@ class LoggingStatement extends StatementDecorator {
  */
 	public function execute($params = null) {
 		$t = microtime(true);
-		$result = parent::execute($params);
-
 		$query = new LoggedQuery;
-		$query->took = round((microtime(true) - $t) * 1000, 0);
+
+		try {
+			$result = parent::execute($params);
+		} catch (\Exception $e) {
+			$query->error = $e;
+			$this->_log($query, $params, $t);
+			throw $e;
+		}
+
 		$query->numRows = $this->rowCount();
+		$this->_log($query, $params, $t);
+		return $result;
+	}
+
+/**
+ * Copies the logging data to the passed LoggedQuery and sends it
+ * to the logging system.
+ *
+ * @param \Cake\Database\Log\LoggedQuery $query
+ * @param array $params list of values to be bound to query
+ * @param float $startTime the microtime when the query was executed
+ * @return void
+ */
+	protected function _log($query, $params, $startTime) {
+		$query->took = round((microtime(true) - $startTime) * 1000, 0);
 		$query->params = $params ?: $this->_compiledParams;
 		$query->query = $this->queryString;
 		$this->logger()->log($query);
-
-		return $result;
 	}
 
 /**

+ 0 - 81
src/Template/Element/sql_dump.ctp

@@ -1,81 +0,0 @@
-<?php
-/**
- * SQL Dump element. Dumps out SQL log information
- *
- * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- * @link          http://cakephp.org CakePHP(tm) Project
- * @since         1.3.0
- * @license       http://www.opensource.org/licenses/mit-license.php MIT License
- */
-
-if (!class_exists('ConnectionManager')) {
-	return false;
-}
-$noLogs = !isset($sqlLogs);
-if ($noLogs):
-	$sources = ConnectionManager::sourceList();
-
-	$sqlLogs = array();
-	foreach ($sources as $source):
-		$db = ConnectionManager::getDataSource($source);
-		if (!method_exists($db, 'getLog')):
-			continue;
-		endif;
-		$sqlLogs[$source] = $db->getLog();
-	endforeach;
-endif;
-
-if ($noLogs || isset($_forced_from_dbo_)):
-	foreach ($sqlLogs as $source => $logInfo):
-		$text = $logInfo['count'] > 1 ? 'queries' : 'query';
-		printf(
-			'<table class="cake-sql-log" id="cakeSqlLog_%s" summary="Cake SQL Log" cellspacing="0">',
-			preg_replace('/[^A-Za-z0-9_]/', '_', uniqid(time(), true))
-		);
-		printf('<caption>(%s) %s %s took %s ms</caption>', $source, $logInfo['count'], $text, $logInfo['time']);
-	?>
-	<thead>
-		<tr><th>Nr</th><th>Query</th><th>Error</th><th>Affected</th><th>Num. rows</th><th>Took (ms)</th></tr>
-	</thead>
-	<tbody>
-	<?php
-		foreach ($logInfo['log'] as $k => $i) :
-			$i += array('error' => '');
-			if (!empty($i['params']) && is_array($i['params'])) {
-				$bindParam = $bindType = null;
-				if (preg_match('/.+ :.+/', $i['query'])) {
-					$bindType = true;
-				}
-				foreach ($i['params'] as $bindKey => $bindVal) {
-					if ($bindType === true) {
-						$bindParam .= h($bindKey) . " => " . h($bindVal) . ", ";
-					} else {
-						$bindParam .= h($bindVal) . ", ";
-					}
-				}
-				$i['query'] .= " , params[ " . rtrim($bindParam, ', ') . " ]";
-			}
-			printf('<tr><td>%d</td><td>%s</td><td>%s</td><td style="text-align: right">%d</td><td style="text-align: right">%d</td><td style="text-align: right">%d</td></tr>%s',
-				$k + 1,
-				h($i['query']),
-				$i['error'],
-				$i['affected'],
-				$i['numRows'],
-				$i['took'],
-				"\n"
-			);
-		endforeach;
-	?>
-	</tbody></table>
-	<?php
-	endforeach;
-else:
-	echo '<p>Encountered unexpected $sqlLogs. Cannot generate SQL log.</p>';
-endif;

+ 30 - 3
tests/TestCase/Database/Log/LoggingStatementTest.php

@@ -61,7 +61,7 @@ class LoggingStatementTest extends \Cake\TestSuite\TestCase {
 			->with($this->logicalAnd(
 				$this->isInstanceOf('\Cake\Database\Log\LoggedQuery'),
 				$this->attributeEqualTo('query', 'SELECT bar FROM foo'),
-				$this->attributeEqualTo('took', 5, 5),
+				$this->attributeEqualTo('took', 5, 200),
 				$this->attributeEqualTo('numRows', 4),
 				$this->attributeEqualTo('params', ['a' => 1, 'b' => 2])
 			));
@@ -85,7 +85,7 @@ class LoggingStatementTest extends \Cake\TestSuite\TestCase {
 			->with($this->logicalAnd(
 				$this->isInstanceOf('\Cake\Database\Log\LoggedQuery'),
 				$this->attributeEqualTo('query', 'SELECT bar FROM foo'),
-				$this->attributeEqualTo('took', 5, 5),
+				$this->attributeEqualTo('took', 5, 200),
 				$this->attributeEqualTo('numRows', 4),
 				$this->attributeEqualTo('params', ['a' => 1, 'b' => '2013-01-01'])
 			));
@@ -94,7 +94,7 @@ class LoggingStatementTest extends \Cake\TestSuite\TestCase {
 			->with($this->logicalAnd(
 				$this->isInstanceOf('\Cake\Database\Log\LoggedQuery'),
 				$this->attributeEqualTo('query', 'SELECT bar FROM foo'),
-				$this->attributeEqualTo('took', 5, 5),
+				$this->attributeEqualTo('took', 5, 200),
 				$this->attributeEqualTo('numRows', 4),
 				$this->attributeEqualTo('params', ['a' => 1, 'b' => '2014-01-01'])
 			));
@@ -112,4 +112,31 @@ class LoggingStatementTest extends \Cake\TestSuite\TestCase {
 		$st->execute();
 	}
 
+/**
+ * Tests that queries are logged despite database errors
+ *
+ * @expectedException \LogicException
+ * @expectedExceptionMessage This is bad
+ * @return void
+ */
+	public function testExecuteWithError() {
+		$exception = new \LogicException('This is bad');
+		$inner = $this->getMock('PDOStatement');
+		$inner->expects($this->once())->method('execute')
+			->will($this->throwException($exception));
+		$logger = $this->getMock('\Cake\Database\Log\QueryLogger');
+		$logger->expects($this->once())
+			->method('log')
+			->with($this->logicalAnd(
+				$this->isInstanceOf('\Cake\Database\Log\LoggedQuery'),
+				$this->attributeEqualTo('query', 'SELECT bar FROM foo'),
+				$this->attributeEqualTo('took', 5, 200),
+				$this->attributeEqualTo('params', []),
+				$this->attributeEqualTo('error', $exception)
+			));
+		$st = new LoggingStatement($inner);
+		$st->queryString = 'SELECT bar FROM foo';
+		$st->logger($logger);
+		$st->execute();
+	}
 }