Merge pull request #129 from cedriclombardot/feat-explain
Allow to show explain plans on each queries
This commit is contained in:
commit
e15eccc0cd
|
@ -12,6 +12,7 @@ namespace Propel\PropelBundle\Controller;
|
||||||
|
|
||||||
use Symfony\Bridge\Propel1\DataCollector\PropelDataCollector;
|
use Symfony\Bridge\Propel1\DataCollector\PropelDataCollector;
|
||||||
use Symfony\Component\DependencyInjection\ContainerAware;
|
use Symfony\Component\DependencyInjection\ContainerAware;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PanelController is designed to display information in the Propel Panel.
|
* PanelController is designed to display information in the Propel Panel.
|
||||||
|
@ -39,4 +40,44 @@ class PanelController extends ContainerAware
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the profiler panel for the given token.
|
||||||
|
*
|
||||||
|
* @param string $token The profiler token
|
||||||
|
* @param string $connection The connection name
|
||||||
|
* @param integer $query
|
||||||
|
*
|
||||||
|
* @return Symfony\Component\HttpFoundation\Response A Response instance
|
||||||
|
*/
|
||||||
|
public function explainAction($token, $connection, $query)
|
||||||
|
{
|
||||||
|
$profiler = $this->container->get('profiler');
|
||||||
|
$profiler->disable();
|
||||||
|
|
||||||
|
$profile = $profiler->loadProfile($token);
|
||||||
|
$queries = $profile->getCollector('propel')->getQueries();
|
||||||
|
|
||||||
|
if (!isset($queries[$query])) {
|
||||||
|
return new Response('This query does not exist.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the connection
|
||||||
|
$con = \Propel::getConnection($connection);
|
||||||
|
|
||||||
|
// Get the adapter
|
||||||
|
$db = \Propel::getDB($connection);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt = $db->doExplainPlan($con, $queries[$query]['sql']);
|
||||||
|
$results = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return new Response('<div class="error">This query cannot be explained.</div>');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->container->get('templating')->renderResponse('PropelBundle:Panel:explain.html.twig', array(
|
||||||
|
'data' => $results,
|
||||||
|
'query' => $query,
|
||||||
|
));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ class PropelBundle extends Bundle
|
||||||
$config->setParameter('debugpdo.logging.details', array(
|
$config->setParameter('debugpdo.logging.details', array(
|
||||||
'time' => array('enabled' => true),
|
'time' => array('enabled' => true),
|
||||||
'mem' => array('enabled' => true),
|
'mem' => array('enabled' => true),
|
||||||
|
'connection' => array('enabled' => true),
|
||||||
));
|
));
|
||||||
|
|
||||||
\Propel::setLogger($this->container->get('propel.logger'));
|
\Propel::setLogger($this->container->get('propel.logger'));
|
||||||
|
|
|
@ -42,6 +42,23 @@
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
margin: 3px 0;
|
margin: 3px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.SQLExplain {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SQLExplain .error {
|
||||||
|
background-color: #F2DEDE;
|
||||||
|
border-color: #EED3D7;
|
||||||
|
color: #B94A48;
|
||||||
|
padding: 8px 35px 8px 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content .SQLExplain h2 {
|
||||||
|
font-size: 17px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<h2>Queries</h2>
|
<h2>Queries</h2>
|
||||||
|
@ -55,11 +72,28 @@
|
||||||
{% if not collector.querycount %}
|
{% if not collector.querycount %}
|
||||||
<tr><td>No queries.</td></tr>
|
<tr><td>No queries.</td></tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% for query in collector.queries %}
|
{% for i, query in collector.queries %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
<a name="propel-query-{{ i }}" ></a>
|
||||||
<code>{{ query.sql|format_sql }}</code>
|
<code>{{ query.sql|format_sql }}</code>
|
||||||
<div class="SQLInfo">Time: {{ query.time }} - Memory: {{ query.memory }}</div>
|
{% if app.request.query.has('query') and app.request.query.get('query') == i %}
|
||||||
|
<div class="SQLExplain">
|
||||||
|
{% render 'PropelBundle:Panel:explain' with {
|
||||||
|
'token': token,
|
||||||
|
'panel': 'propel',
|
||||||
|
'query': app.request.query.get('query'),
|
||||||
|
'connection': app.request.query.get('connection')
|
||||||
|
} %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="SQLInfo">
|
||||||
|
Time: {{ query.time }} - Memory: {{ query.memory }} - Connection: {{ query.connection }}
|
||||||
|
|
||||||
|
{% if app.request.query.get('query', -1) != i %}
|
||||||
|
- <a href="{{ path('_profiler', {'panel': 'propel', 'token': token, 'connection': query.connection, 'query': i}) }}#propel-query-{{ i }}">Explain the query</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
16
Resources/views/Panel/explain.html.twig
Normal file
16
Resources/views/Panel/explain.html.twig
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<h2>Explanation</h2>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
{% for label in data[0]|keys %}
|
||||||
|
<th>{{ label }}</th>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% for row in data %}
|
||||||
|
<tr>
|
||||||
|
{% for item in row %}
|
||||||
|
<td>{{ item }}</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
Loading…
Reference in a new issue