From 5f1e55e3f496795541fd169cccc3418651895a4a Mon Sep 17 00:00:00 2001 From: camer0n Date: Tue, 6 May 2025 15:43:04 -0700 Subject: [PATCH] Fixes #5490 debug SQL queries --- e107_handlers/db_debug_class.php | 259 +++++++++++--------- e107_handlers/e_db_pdo_class.php | 7 +- e107_tests/tests/unit/e107_db_debugTest.php | 53 +++- 3 files changed, 191 insertions(+), 128 deletions(-) diff --git a/e107_handlers/db_debug_class.php b/e107_handlers/db_debug_class.php index bcfc4c92b..6a79de1e4 100644 --- a/e107_handlers/db_debug_class.php +++ b/e107_handlers/db_debug_class.php @@ -80,6 +80,7 @@ class e107_db_debug } + /** * @return void */ @@ -213,8 +214,11 @@ class e107_db_debug */ function Mark_Query($query, $rli, $origQryRes, $aTrace, $mytime, $curtable) { + + if(!$this->active) { + return null; } // global $sql; @@ -245,13 +249,16 @@ class e107_db_debug else { // Don't run 'EXPLAIN' on other queries $sQryRes = $origQryRes; // Return from original query could be TRUE or a link resource if success + } // Record Basic query info $sCallingFile = varset($aTrace[2]['file']); $sCallingLine = varset($aTrace[2]['line']); - $t = &$this->aSQLdetails[$sql->db_QueryCount()]; + $dbQryCount = $sql->db_QueryCount(); + + $t = &$this->aSQLdetails[$dbQryCount]; $t['marker'] = $this->curTimeMark; $t['caller'] = "$sCallingFile($sCallingLine)"; $t['query'] = $query; @@ -260,6 +267,7 @@ class e107_db_debug $t['nFields'] = $nFields; $t['time'] = $mytime; + if($bExplained) { $bRowHeaders = false; @@ -286,6 +294,8 @@ class e107_db_debug { $this->aDBbyTable[$curtable]['DB Time'] += $mytime; $this->aDBbyTable[$curtable]['DB Count']++; + + } else { @@ -294,6 +304,7 @@ class e107_db_debug $this->aDBbyTable[$curtable]['%DB Count'] = 0; // placeholder $this->aDBbyTable[$curtable]['DB Time'] = $mytime; $this->aDBbyTable[$curtable]['DB Count'] = 1; + } return null; @@ -305,158 +316,172 @@ class e107_db_debug * @return false|string */ function Show_SQL_Details($force = false) + { + + $sql = e107::getDb(); + // + // Show stats from aSQLdetails array + // + if(!E107_DBG_SQLQUERIES && !E107_DBG_SQLDETAILS && ($force === false)) { + return false; + } - global $sql; - // - // Show stats from aSQLdetails array - // - if(!E107_DBG_SQLQUERIES && !E107_DBG_SQLDETAILS && ($force === false)) + + $text = ''; + $nQueries = $sql->db_QueryCount(); + + if(!$nQueries) + { + return $text; + } + + // + // ALWAYS summarize query errors + // + $badCount = 0; + $okCount = 0; + + $SQLdetails = $this->getSQLDetails(); + + foreach($SQLdetails as $cQuery) + { + if($cQuery['ok'] == 1) { - return false; + $okCount++; } - - - $text = ''; - $nQueries = $sql->db_QueryCount(); - - if(!$nQueries) + else { - return $text; + $badCount++; } + + } - // - // ALWAYS summarize query errors - // - $badCount = 0; - $okCount = 0; + if($badCount) + { + $text .= "\n\n"; + $text .= "\n"; + $text .= "\n"; - foreach($this->aSQLdetails as $cQuery) + foreach($SQLdetails as $idx => $cQuery) { - if($cQuery['ok'] == 1) + if(!$cQuery['ok']) { - $okCount++; - } - else - { - $badCount++; - } - } - - if($badCount) - { - $text .= "\n
$badCount Query Errors!
IndexQuery / Error
\n"; - $text .= "\n"; - $text .= "\n"; - - foreach($this->aSQLdetails as $idx => $cQuery) - { - if(!$cQuery['ok']) - { - $text .= " + $text .= "\n\n"; - } } - $text .= "\n
$badCount Query Errors!
IndexQuery / Error
{$idx} 
{$idx}  " . $cQuery['query'] . "
" . $cQuery['error'] . "

\n"; } + $text .= "\n
\n"; + } - // - // Optionally list good queries - // + // + // Optionally list good queries + // - if($okCount && E107_DBG_SQLDETAILS) - { - $text .= "\n\n"; - $text .= "\n"; - $text .= "\n + if($okCount && (E107_DBG_SQLDETAILS || $force)) + { + $text .= "\n
" . $this->countLabel($okCount) . " Good Queries
IndexQtimeQuery
\n"; + $text .= "\n"; + $text .= "\n \n "; - $count = 0; - foreach($this->aSQLdetails as $idx => $cQuery) + $count = 0; + foreach($SQLdetails as $idx => $cQuery) + { + if($count > 500) { - if($count > 500) - { - $text .= ""; // NO LAN - debug only. - break; - } - - - if($cQuery['ok']) - { - $text .= " - - \n"; - - $count++; - } + $text .= ""; // NO LAN - debug only. + break; } - $text .= "\n
" . $this->countLabel($okCount) . " Good Queries
IndexQtimeQuery
 (msec) 
Too many queries. Ending...
{$idx} " . number_format($cQuery['time'] * 1000.0, 4) . " " . $cQuery['query'] . '
[' . $cQuery['marker'] . " - " . $cQuery['caller'] . "]
Too many queries. Ending...

\n"; - } - - - // - // Optionally list query details - // - if(E107_DBG_SQLDETAILS) - { - $count = 0; - foreach($this->aSQLdetails as $idx => $cQuery) + if($cQuery['ok']) { - $text .= "\n\n"; - $text .= "\n"; - if(isset($cQuery['explain'])) - { - $text .= $cQuery['explain']; - } - if(strlen($cQuery['error'])) - { - $text .= "\n\n"; - } - - $text .= "'; - - $text .= '
" . $idx . ") Query: [" . $cQuery['marker'] . " - " . $cQuery['caller'] . "]
" . $cQuery['query'] . "
Error in query:
" . $cQuery['error'] . "
Query time: " . number_format($cQuery['time'] * 1000.0, 4) . ' (ms)

' . "\n"; - - if($count > 500) - { - $text .= "
Too many queries. Ending...
"; // NO LAN - debug only. - break; - } - + $text .= "{$idx}  + " . number_format($cQuery['time'] * 1000.0, 4) . "  + " . $cQuery['query'] . '
[' . $cQuery['marker'] . " - " . $cQuery['caller'] . "]\n"; $count++; } } - return $text; + + $text .= "\n
\n"; } + // + // Optionally list query details + // + if(E107_DBG_SQLDETAILS || $force) + { + $count = 0; + foreach($SQLdetails as $idx => $cQuery) + { + $text .= "\n\n"; + $text .= "\n"; + if(isset($cQuery['explain'])) + { + $text .= $cQuery['explain']; + } + if(strlen($cQuery['error'])) + { + $text .= "\n\n"; + } + + $text .= "'; + + $text .= '
" . $idx . ") Query: [" . $cQuery['marker'] . " - " . $cQuery['caller'] . "]
" . $cQuery['query'] . "
Error in query:
" . $cQuery['error'] . "
Query time: " . number_format($cQuery['time'] * 1000.0, 4) . ' (ms)

' . "\n"; + + if($count > 500) + { + $text .= "
Too many queries. Ending...
"; // NO LAN - debug only. + break; + } + + + $count++; + } + } + + return $text; + } + + public function getSQLDetails() + { + return $this->aSQLdetails; + } + + public function setSQLDetails($aSQLdetails) + { + $this->aSQLdetails = $aSQLdetails ?? []; + } + + /** * @param $amount * @return string */ function countLabel($amount) + { + + $inc = ''; + + if($amount < 30) { - $inc = ''; - - if($amount < 30) - { - $inc = 'label-success'; - } - elseif($amount < 50) - { - $inc = 'label-warning'; - } - elseif($amount > 49) - { - $inc = 'label-danger label-important'; - } - - return "" . $amount . ""; + $inc = 'label-success'; } + elseif($amount < 50) + { + $inc = 'label-warning'; + } + elseif($amount > 49) + { + $inc = 'label-danger label-important'; + } + + return "" . $amount . ""; + } /** @@ -1111,7 +1136,7 @@ class e107_db_debug * $db_debug->log("message"); * @param string|array $message * @param int $TraceLev - * @return bool true on success , false on error + * @return bool|null true on success , false on error */ public function log($message, $TraceLev = 1) { diff --git a/e107_handlers/e_db_pdo_class.php b/e107_handlers/e_db_pdo_class.php index 71fcc0ac3..7d24943b3 100644 --- a/e107_handlers/e_db_pdo_class.php +++ b/e107_handlers/e_db_pdo_class.php @@ -70,7 +70,7 @@ class e_db_pdo implements e_db private $debugMode = false; - private $queryCount = 0; + protected static $querycount = 0; @@ -329,7 +329,7 @@ class e_db_pdo implements e_db public function db_Query($query, $rli = NULL, $qry_from = '', $debug = false, $log_type = '', $log_remark = '') { global $db_time, $queryinfo; - $this->queryCount++; + self::$querycount++; $this->_getMySQLaccess(); $this->mySQLlastQuery = $query; @@ -601,6 +601,7 @@ class e_db_pdo implements e_db case 'single': // single field value returned. if($select && !$this->select($table, $fields, $where, $noWhere, $debug)) { + $this->mySQLcurTable = $table; return null; } elseif(!$select && !$this->gen($table, $debug)) @@ -1840,7 +1841,7 @@ class e_db_pdo implements e_db */ public function queryCount() { - return $this->queryCount; + return self::$querycount; } diff --git a/e107_tests/tests/unit/e107_db_debugTest.php b/e107_tests/tests/unit/e107_db_debugTest.php index 5b9030d7b..0a1e49b0c 100644 --- a/e107_tests/tests/unit/e107_db_debugTest.php +++ b/e107_tests/tests/unit/e107_db_debugTest.php @@ -23,10 +23,10 @@ } catch(Exception $e) { - $this->assertTrue(false, "Couldn't load e107_db_debug object"); + $this::fail("Couldn't load e107_db_debug object"); } - $this->dbg->active(true); + $this->dbg->active(false); } /* public function testShowIf() @@ -37,13 +37,13 @@ public function testShow_Log() { $result = $this->dbg->Show_Log(); - $this->assertEmpty($result); + $this::assertEmpty($result); } public function testShow_Includes() { $result = $this->dbg->Show_Includes(); - $this->assertEmpty($result); + $this::assertEmpty($result); } public function testSave() @@ -59,6 +59,7 @@ public function testLog() { + $this->dbg->active(true); $res = $this->dbg->log('hello world'); $this->assertTrue($res, 'db_debug->log() method returned false.'); @@ -71,26 +72,62 @@ public function testShow_Performance() { $result = $this->dbg->Show_Performance(); - $this->assertEmpty($result); + $this::assertEmpty($result); } public function testShow_PATH() { $result = $this->dbg->Show_PATH(); - $this->assertEmpty($result); + $this::assertEmpty($result); } public function testShow_SQL_Details() { $result = $this->dbg->Show_SQL_Details(); - $this->assertEmpty($result); + $this::assertEmpty($result); + + $this->dbg->active(true); + $this->dbg->setSQLDetails(null); + } + /* public function testGetSqlDetails() + { + $this->dbg->setSQLDetails(null); + $result = $this->dbg->getSQLDetails(); + $this::assertEmpty($result); + + $this->dbg->active(true); + $this->dbg->setSQLDetails(null); + + e107::getDb()->retrieve('SELECT * FROM #user'); + e107::getDb()->retrieve("SELECT DISTINCT dblog_eventcode,dblog_title FROM #admin_log",true); + + $result = $this->dbg->getSQLDetails(); + $this::assertNotEmpty($result); + $result = array_values($result); + + $expected = [ + 0 => 'SELECT * FROM e107_user ', + 1 => 'SELECT DISTINCT dblog_eventcode,dblog_title FROM e107_admin_log ', + + ]; + + + + foreach($expected as $i => $expected_query) + { + + $this::assertSame($expected_query, $result[$i]['query']); + } + + }*/ + public function testShow_SC_BB() { $result = $this->dbg->Show_SC_BB(); - $this->assertEmpty($result); + $this::assertEmpty($result); } /* public function testLogCode()