From e9ccc5d72d121859c8a766bd64a87d45d42f62a2 Mon Sep 17 00:00:00 2001 From: Michael Foster Date: Sat, 7 Sep 2013 12:40:35 +1000 Subject: [PATCH] Optionally EXPLAIN all SQL queries when in debug mode --- inc/config.php | 2 ++ inc/database.php | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/inc/config.php b/inc/config.php index 81cae233..43550dc3 100644 --- a/inc/config.php +++ b/inc/config.php @@ -44,6 +44,8 @@ $config['debug'] = false; // For development purposes. Displays (and "dies" on) all errors and warnings. Turn on with the above. $config['verbose_errors'] = true; + // EXPLAIN all SQL queries (when in debug mode). + $config['debug_explain'] = false; // Directory where temporary files will be created. $config['tmp'] = sys_get_temp_dir(); diff --git a/inc/database.php b/inc/database.php index d2f1af04..2c60015a 100644 --- a/inc/database.php +++ b/inc/database.php @@ -7,21 +7,29 @@ defined('TINYBOARD') or exit; class PreparedQueryDebug { - protected $query; + protected $query, $explain_query = false; public function __construct($query) { - global $pdo; + global $pdo, $config; $query = preg_replace("/[\n\t]+/", ' ', $query); $this->query = $pdo->prepare($query); + if ($config['debug'] && $config['debug_explain'] && preg_match('/^(SELECT|INSERT|UPDATE|DELETE) /', $query)) + $this->explain_query = $pdo->prepare("EXPLAIN $query"); } public function __call($function, $args) { global $config, $debug; if ($config['debug'] && $function == 'execute') { + if ($this->explain_query) { + $this->explain_query->execute() or error(db_error($explain_query)); + } $start = microtime(true); } + if ($this->explain_query && $function == 'bindValue') + call_user_func_array(array($this->explain_query, $function), $args); + $return = call_user_func_array(array($this->query, $function), $args); if ($config['debug'] && $function == 'execute') { @@ -29,6 +37,7 @@ class PreparedQueryDebug { $debug['sql'][] = array( 'query' => $this->query->queryString, 'rows' => $this->query->rowCount(), + 'explain' => $this->explain_query ? $this->explain_query->fetchAll(PDO::FETCH_ASSOC) : null, 'time' => '~' . round($time * 1000, 2) . 'ms' ); $debug['time']['db_queries'] += $time; @@ -118,6 +127,9 @@ function query($query) { sql_open(); if ($config['debug']) { + if ($config['debug_explain'] && preg_match('/^(SELECT|INSERT|UPDATE|DELETE) /', $query)) { + $explain = $pdo->query("EXPLAIN $query") or error(db_error()); + } $start = microtime(true); $query = $pdo->query($query); if (!$query) @@ -126,6 +138,7 @@ function query($query) { $debug['sql'][] = array( 'query' => $query->queryString, 'rows' => $query->rowCount(), + 'explain' => isset($explain) ? $explain->fetchAll(PDO::FETCH_ASSOC) : null, 'time' => '~' . round($time * 1000, 2) . 'ms' ); $debug['time']['db_queries'] += $time;