Skip to content

Instantly share code, notes, and snippets.

@kmuenkel
Last active November 4, 2021 16:51
Show Gist options
  • Save kmuenkel/d2a659fa5876b659dde26add19976bc3 to your computer and use it in GitHub Desktop.
Save kmuenkel/d2a659fa5876b659dde26add19976bc3 to your computer and use it in GitHub Desktop.
SQL Debugging: Set a start and end point, and gather some data on all queries executed between those two points.
<?php
if (!function_exists('debug_query')) {
/**
* @param bool $trace
* @param bool $full
* @param bool $cache
* @return @void
*/
function debug_query($trace = true, $full = false)
{
$connections = array_keys(config('database.connections'));
foreach ($connections as $name) {
/** @var \App\Overrides\Database\Connection $connection */
$connection = DB::connection($name);
$connection->enableQueryLog();
$connection->flushQueryLog();
}
}
}
if (!function_exists('debug_query_output')) {
/**
* @param array|null $fields
* @return string|array
*/
function debug_query_output($fields = [])
{
$compiledByConnection = [];
$connections = array_keys(config('database.connections'));
foreach ($connections as $name) {
/** @var \App\Overrides\Database\Connection $connection */
$connection = DB::connection($name);
$fields = array_unique(array_merge((array)$fields, ['query', 'time']));
$compiled = [];
$queries = $connection->getQueryLog();
$connection->disableQueryLog();
$connection->flushQueryLog();
$useDb = null;
$sum = 0;
foreach ($queries as $query) {
$sql = compile_query($query['query'], $query['bindings']);
if ($connection->getDatabaseName() != $useDb) {
$useDb = $connection->getDatabaseName();
$compiled[] = "USE `$useDb`;";
}
$time = $query['time'] / 1000;
$sum += $time;
$query = compact('sql', 'time');
$compiled[] = $query;
}
if (empty($compiled)) {
$compiled[] = 'USE `' . $connection->getDatabaseName() . '`;';
}
$compiled[] = "Total time: $sum seconds";
if (!$trace) {
#$compiled = implode("\n", array_unique($compiled));
$compiled = implode("\n", $compiled);
}
$compiledByConnection[] = $compiled;
}
return $compiledByConnection;
}
}
if (!function_exists('compile_query')) {
/**
* @param string|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Expression $sql
* @param array $values
* @return string
*/
function compile_query($sql, array $values = [])
{
if (is_object($sql) && (
$sql instanceof \Illuminate\Database\Eloquent\Builder
|| $sql instanceof \Illuminate\Database\Query\Builder
)
) {
$values = $sql->getBindings();
$sql = $sql->toSql();
}
$enclosures = [
'back_tick' => '`',
'apostrophe' => "'"
];
$matches = [];
foreach ($enclosures as $name => $enclosure) {
$matches[$name] = [];
preg_match_all("/$enclosure.*?$enclosure/", $sql, $matches[$name]);
$matches[$name] = array_last($matches[$name]);
$sql = preg_replace("/$enclosure.*?$enclosure/", "$enclosure?$enclosure", $sql);
}
$sql = strtoupper($sql);
foreach ($enclosures as $name => $enclosure) {
$sql = str_replace_array("$enclosure?$enclosure", $matches[$name], $sql);
}
$values = array_map(function ($value) {
if (!is_numeric($value) && !is_null($value)) {
$value = DB::connection()->getPdo()->quote($value);
}
return $value;
}, $values);
$sql = str_replace(' AND 1', '', $sql);
$sql = str_replace('WHERE 1 AND ', 'WHERE ', $sql);
$sql = str_replace_array('?', $values, $sql);
$sql = preg_replace('/\s+/', ' ', $sql);
// $sql = preg_replace('/(` AS `)(.+?)(`)/', "$1'$2'", $sql);
// $sql = str_replace('`', '', $sql);
// $sql = preg_replace("/( AS )(')(.+?)(')/", "$1`$3`", $sql);
$sql = rtrim($sql, ';').';';
#$sql .= '# '.$query['time'].'ms';
return $sql;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment