diff --git a/build/media_source/plg_system_debug/widgets/sqlqueries/widget.es5.js b/build/media_source/plg_system_debug/widgets/sqlqueries/widget.es5.js index f0af1cfdf75db..16fbbd8be3593 100644 --- a/build/media_source/plg_system_debug/widgets/sqlqueries/widget.es5.js +++ b/build/media_source/plg_system_debug/widgets/sqlqueries/widget.es5.js @@ -124,30 +124,50 @@ }) } - var tableExplain + var tableExplain; + + function showTableExplain() { + if (tableExplain) { + tableExplain.show(); + return; + } + + // Render table + tableExplain = $('').addClass(csscls('callstack')).appendTo(li); + tableExplain.append(''); + + var i, entry, cols; + for (i in stmt.explain) { + cols = [] + entry = stmt.explain[i]; + + stmt.explain_col.forEach(function (key){ + cols.push(entry[key]); + }); + + tableExplain.append(''); + } + + tableExplain.show(); + } if (stmt.explain && !$.isEmptyObject(stmt.explain)) { var btnExplain = $('') - .text('Explain') - .addClass(csscls('eye')) - .css('cursor', 'pointer') - .on('click', function () { - if (tableExplain.is(':visible')) { - tableExplain.hide() - btnExplain.addClass(csscls('eye')) - btnExplain.removeClass(csscls('eye-dash')) - } else { - tableExplain.show() - btnExplain.addClass(csscls('eye-dash')) - btnExplain.removeClass(csscls('eye')) - } - }) - .appendTo(li) - - tableExplain = $('
' + stmt.explain_col.join('') + '
' + cols.join('') + '
' - + '' - + '' - + '
Explain
IdSelect TypeTableTypePossible KeysKeyKey LenRefRowsExtra
').addClass(csscls('callstack')) + .text('Explain') + .addClass(csscls('eye')) + .css('cursor', 'pointer') + .on('click', function () { + if (tableExplain && tableExplain.is(':visible')) { + tableExplain.hide() + btnExplain.addClass(csscls('eye')) + btnExplain.removeClass(csscls('eye-dash')) + } else { + showTableExplain(); + btnExplain.addClass(csscls('eye-dash')) + btnExplain.removeClass(csscls('eye')) + } + }) + .appendTo(li) } var tableStack @@ -214,19 +234,6 @@ } } - if (tableExplain) { - tableExplain.appendTo(li) - for (i in stmt.explain) { - var entry = stmt.explain[i] - tableExplain.append('' - + '' + entry.id + '' + entry.select_type + '' + entry.table + '' - + '' + entry.type + '' + entry.possible_keys + '' + entry.key + '' - + '' + entry.key_len + '' + entry.ref + '' + entry.rows + '' - + '' + entry.Extra + '' - + '') - } - } - li.attr('dupeindex', 'dupe-0') } }) diff --git a/composer.lock b/composer.lock index d1a72c9d3fb56..696d9faad8829 100644 --- a/composer.lock +++ b/composer.lock @@ -910,16 +910,16 @@ }, { "name": "joomla/database", - "version": "2.0.0-beta", + "version": "2.0.0-beta2", "source": { "type": "git", "url": "https://github.com/joomla-framework/database.git", - "reference": "1332ca4c1ed8411d58898c5c68c1a818ff95bb21" + "reference": "1eef40d30cca0661b5cfb5c60c8600ed0d09b42d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/database/zipball/1332ca4c1ed8411d58898c5c68c1a818ff95bb21", - "reference": "1332ca4c1ed8411d58898c5c68c1a818ff95bb21", + "url": "https://api.github.com/repos/joomla-framework/database/zipball/1eef40d30cca0661b5cfb5c60c8600ed0d09b42d", + "reference": "1eef40d30cca0661b5cfb5c60c8600ed0d09b42d", "shasum": "" }, "require": { @@ -936,6 +936,7 @@ "joomla/test": "^2.0", "phpunit/phpunit": "^8.5|^9.0", "psr/log": "^1.1", + "symfony/deprecation-contracts": "^2.1", "symfony/phpunit-bridge": "^4.4|^5.0" }, "suggest": { @@ -971,7 +972,7 @@ "framework", "joomla" ], - "time": "2020-06-05T11:27:58+00:00" + "time": "2020-09-01T07:19:19+00:00" }, { "name": "joomla/di", @@ -6806,6 +6807,7 @@ "keywords": [ "tokenizer" ], + "abandoned": true, "time": "2019-09-17T06:23:10+00:00" }, { diff --git a/plugins/system/debug/debug.php b/plugins/system/debug/debug.php index 2e44410d4ce8b..2c13d631871fe 100644 --- a/plugins/system/debug/debug.php +++ b/plugins/system/debug/debug.php @@ -508,7 +508,8 @@ public function onAfterDisconnect(ConnectionEvent $event) if ($this->params->get('query_explains') && in_array($db->getServerType(), ['mysql', 'postgresql'], true)) { - $logs = $this->queryMonitor->getLogs(); + $logs = $this->queryMonitor->getLogs(); + $boundParams = $this->queryMonitor->getBoundParams(); foreach ($logs as $k => $query) { @@ -524,12 +525,22 @@ public function onAfterDisconnect(ConnectionEvent $event) { try { - $db->setQuery('EXPLAIN ' . ($dbVersion56 ? 'EXTENDED ' : '') . $query); - $this->explains[$k] = $db->loadAssocList(); + $queryInstance = $db->getQuery(true); + $queryInstance->setQuery('EXPLAIN ' . ($dbVersion56 ? 'EXTENDED ' : '') . $query); + + if ($boundParams[$k]) + { + foreach ($boundParams[$k] as $key => $obj) + { + $queryInstance->bind($key, $obj->value, $obj->dataType, $obj->length, $obj->driverOptions); + } + } + + $this->explains[$k] = $db->setQuery($queryInstance)->loadAssocList(); } catch (Exception $e) { - $this->explains[$k] = [['Error' => $e->getMessage()]]; + $this->explains[$k] = [['error' => $e->getMessage()]]; } } } diff --git a/plugins/system/debug/src/DataCollector/QueryCollector.php b/plugins/system/debug/src/DataCollector/QueryCollector.php index bedd048a00d3c..445ebb0ec5724 100644 --- a/plugins/system/debug/src/DataCollector/QueryCollector.php +++ b/plugins/system/debug/src/DataCollector/QueryCollector.php @@ -233,13 +233,23 @@ private function getStatements(): array } } + $explain = $this->explains[$id] ?? []; + $explainColumns = []; + + // Extract column labels for Explain table + if ($explain) + { + $explainColumns = array_keys(reset($explain)); + } + $statements[] = [ 'sql' => $item, 'duration_str' => $this->getDataFormatter()->formatDuration($queryTime), 'memory_str' => $this->getDataFormatter()->formatBytes($queryMemory), 'caller' => $callerLocation, 'callstack' => $trace, - 'explain' => $this->explains[$id] ?? [], + 'explain' => $explain, + 'explain_col' => $explainColumns, 'profile' => $this->profiles[$id] ?? [], ]; }