Skip to content

Commit

Permalink
Merge pull request #129 from cedriclombardot/feat-explain
Browse files Browse the repository at this point in the history
Allow to show explain plans on each queries
  • Loading branch information
willdurand committed Mar 26, 2012
2 parents 4754fea + 295f732 commit e15eccc
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 2 deletions.
41 changes: 41 additions & 0 deletions Controller/PanelController.php
Expand Up @@ -12,6 +12,7 @@

use Symfony\Bridge\Propel1\DataCollector\PropelDataCollector;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\Response;

/**
* PanelController is designed to display information in the Propel Panel.
Expand Down Expand Up @@ -39,4 +40,44 @@ public function configurationAction()
);
}

/**
* 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,
));

}
}
1 change: 1 addition & 0 deletions PropelBundle.php
Expand Up @@ -51,6 +51,7 @@ public function boot()
$config->setParameter('debugpdo.logging.details', array(
'time' => array('enabled' => true),
'mem' => array('enabled' => true),
'connection' => array('enabled' => true),
));

\Propel::setLogger($this->container->get('propel.logger'));
Expand Down
38 changes: 36 additions & 2 deletions Resources/views/Collector/propel.html.twig
Expand Up @@ -42,6 +42,23 @@
font-size: 0.9em;
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>

<h2>Queries</h2>
Expand All @@ -55,11 +72,28 @@
{% if not collector.querycount %}
<tr><td>No queries.</td></tr>
{% else %}
{% for query in collector.queries %}
{% for i, query in collector.queries %}
<tr>
<td>
<a name="propel-query-{{ i }}" ></a>
<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>
</tr>
{% endfor %}
Expand Down
16 changes: 16 additions & 0 deletions Resources/views/Panel/explain.html.twig
@@ -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>

0 comments on commit e15eccc

Please sign in to comment.