[DoctrineBridge] Refactored the query sanitization in the collector
The original parameters are kept whenever possible to allow using them again to explain the query.
This commit is contained in:
parent
3b260d268b
commit
e37783f4f9
@ -13,6 +13,7 @@ namespace Symfony\Bridge\Doctrine\DataCollector;
|
||||
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use Doctrine\DBAL\Logging\DebugStack;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@ -54,7 +55,7 @@ class DoctrineDataCollector extends DataCollector
|
||||
{
|
||||
$queries = array();
|
||||
foreach ($this->loggers as $name => $logger) {
|
||||
$queries[$name] = $this->sanitizeQueries($logger->queries);
|
||||
$queries[$name] = $this->sanitizeQueries($name, $logger->queries);
|
||||
}
|
||||
|
||||
$this->data = array(
|
||||
@ -104,48 +105,73 @@ class DoctrineDataCollector extends DataCollector
|
||||
return 'db';
|
||||
}
|
||||
|
||||
private function sanitizeQueries($queries)
|
||||
private function sanitizeQueries($connectionName, $queries)
|
||||
{
|
||||
foreach ($queries as $i => $query) {
|
||||
foreach ((array) $query['params'] as $j => $param) {
|
||||
$queries[$i]['params'][$j] = $this->varToString($param);
|
||||
}
|
||||
$queries[$i] = $this->sanitizeQuery($connectionName, $query);
|
||||
}
|
||||
|
||||
return $queries;
|
||||
}
|
||||
|
||||
private function varToString($var)
|
||||
private function sanitizeQuery($connectionName, $query)
|
||||
{
|
||||
$query['explainable'] = true;
|
||||
$query['params'] = (array) $query['params'];
|
||||
foreach ($query['params'] as $j => &$param) {
|
||||
if (isset($query['types'][$j])) {
|
||||
// Transform the param according to the type
|
||||
$type = $query['types'][$j];
|
||||
if (is_string($type)) {
|
||||
$type = Type::getType($type);
|
||||
}
|
||||
if ($type instanceof Type) {
|
||||
$query['types'][$j] = $type->getBindingType();
|
||||
$param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform());
|
||||
}
|
||||
}
|
||||
|
||||
list($param, $explainable) = $this->sanitizeParam($param);
|
||||
if (!$explainable) {
|
||||
$query['explainable'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes a param.
|
||||
*
|
||||
* The return value is an array with the sanitized value and a boolean
|
||||
* indicating if the original value was kept (allowing to use the sanitized
|
||||
* value to explain the query).
|
||||
*
|
||||
* @param mixed $var
|
||||
* @return array
|
||||
*/
|
||||
private function sanitizeParam($var)
|
||||
{
|
||||
if (is_object($var)) {
|
||||
return sprintf('Object(%s)', get_class($var));
|
||||
return array(sprintf('Object(%s)', get_class($var)), false);
|
||||
}
|
||||
|
||||
if (is_array($var)) {
|
||||
$a = array();
|
||||
$original = true;
|
||||
foreach ($var as $k => $v) {
|
||||
$a[] = sprintf('%s => %s', $k, $this->varToString($v));
|
||||
list($value, $orig) = $this->sanitizeParam($v);
|
||||
$original = $original && $orig;
|
||||
$a[$k] = $value;
|
||||
}
|
||||
|
||||
return sprintf("Array(%s)", implode(', ', $a));
|
||||
return array($a, $original);
|
||||
}
|
||||
|
||||
if (is_resource($var)) {
|
||||
return sprintf('Resource(%s)', get_resource_type($var));
|
||||
return array(sprintf('Resource(%s)', get_resource_type($var)), false);
|
||||
}
|
||||
|
||||
if (null === $var) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
if (false === $var) {
|
||||
return 'false';
|
||||
}
|
||||
|
||||
if (true === $var) {
|
||||
return 'true';
|
||||
}
|
||||
|
||||
return (string) $var;
|
||||
return array($var, true);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Tests\Bridge\Doctrine\DataCollector;
|
||||
|
||||
use Doctrine\DBAL\Platforms\MySqlPlatform;
|
||||
use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@ -70,25 +71,26 @@ class DoctrineDataCollectorTest extends \PHPUnit_Framework_TestCase
|
||||
/**
|
||||
* @dataProvider paramProvider
|
||||
*/
|
||||
public function testCollectQueries($param, $expected)
|
||||
public function testCollectQueries($param, $types, $expected, $explainable)
|
||||
{
|
||||
$queries = array(
|
||||
array('sql' => "SELECT * FROM table1 WHERE field1 = ?1", 'params' => array($param), 'types' => array(), 'executionMS' => 1)
|
||||
array('sql' => "SELECT * FROM table1 WHERE field1 = ?1", 'params' => array($param), 'types' => $types, 'executionMS' => 1)
|
||||
);
|
||||
$c = $this->createCollector($queries);
|
||||
$c->collect(new Request(), new Response());
|
||||
|
||||
$collected_queries = $c->getQueries();
|
||||
$this->assertEquals($expected, $collected_queries['default'][0]['params'][0]);
|
||||
$this->assertEquals($explainable, $collected_queries['default'][0]['explainable']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider paramProvider
|
||||
*/
|
||||
public function testSerialization($param, $expected)
|
||||
public function testSerialization($param, $types, $expected, $explainable)
|
||||
{
|
||||
$queries = array(
|
||||
array('sql' => "SELECT * FROM table1 WHERE field1 = ?1", 'params' => array($param), 'types' => array(), 'executionMS' => 1)
|
||||
array('sql' => "SELECT * FROM table1 WHERE field1 = ?1", 'params' => array($param), 'types' => $types, 'executionMS' => 1)
|
||||
);
|
||||
$c = $this->createCollector($queries);
|
||||
$c->collect(new Request(), new Response());
|
||||
@ -96,23 +98,31 @@ class DoctrineDataCollectorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$collected_queries = $c->getQueries();
|
||||
$this->assertEquals($expected, $collected_queries['default'][0]['params'][0]);
|
||||
$this->assertEquals($explainable, $collected_queries['default'][0]['explainable']);
|
||||
}
|
||||
|
||||
public function paramProvider()
|
||||
{
|
||||
return array(
|
||||
array('some value', 'some value'),
|
||||
array(1, '1'),
|
||||
array(true, 'true'),
|
||||
array(null, 'null'),
|
||||
array(new \stdClass(), 'Object(stdClass)'),
|
||||
array(fopen(__FILE__, 'r'), 'Resource(stream)'),
|
||||
array(new \SplFileInfo(__FILE__), 'Object(SplFileInfo)'),
|
||||
array('some value', array(), 'some value', true),
|
||||
array(1, array(), 1, true),
|
||||
array(true, array(), true, true),
|
||||
array(null, array(), null, true),
|
||||
array(new \DateTime('2011-09-11'), array('date'), '2011-09-11', true),
|
||||
array(fopen(__FILE__, 'r'), array(), 'Resource(stream)', false),
|
||||
array(new \SplFileInfo(__FILE__), array(), 'Object(SplFileInfo)', false),
|
||||
);
|
||||
}
|
||||
|
||||
private function createCollector($queries)
|
||||
{
|
||||
$connection = $this->getMockBuilder('Doctrine\DBAL\Connection')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$connection->expects($this->any())
|
||||
->method('getDatabasePlatform')
|
||||
->will($this->returnValue(new MySqlPlatform()));
|
||||
|
||||
$registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
|
||||
$registry
|
||||
->expects($this->any())
|
||||
@ -122,6 +132,9 @@ class DoctrineDataCollectorTest extends \PHPUnit_Framework_TestCase
|
||||
->expects($this->any())
|
||||
->method('getManagerNames')
|
||||
->will($this->returnValue(array('default' => 'doctrine.orm.default_entity_manager')));
|
||||
$registry->expects($this->any())
|
||||
->method('getConnection')
|
||||
->will($this->returnValue($connection));
|
||||
|
||||
$logger = $this->getMock('Doctrine\DBAL\Logging\DebugStack');
|
||||
$logger->queries = $queries;
|
||||
|
Reference in New Issue
Block a user