Query Analyzer Dialog v0.1

This commit is contained in:
Tyron Madlener 2011-07-21 13:38:51 +03:00
parent 5022829ae6
commit c30d209146
8 changed files with 382 additions and 166 deletions

View File

@ -140,8 +140,8 @@ function PMA_addDatepicker($this_element, options) {
if ($this_element.is('.datetimefield')) {
showTimeOption = true;
}
var defaultOptions = {
var defaultOptions = {
showOn: 'button',
buttonImage: themeCalendarImage, // defined in js/messages.php
buttonImageOnly: true,
@ -163,7 +163,7 @@ function PMA_addDatepicker($this_element, options) {
},0);
},
constrainInput: false
};
};
$this_element.datepicker($.extend(defaultOptions, options));
}
@ -1455,12 +1455,13 @@ function PMA_createTableDialog( div, url , target) {
* - the current response value of the GET request, JSON parsed
* - the previous response value of the GET request, JSON parsed
* - the number of added points
* }
*
* @return object The created highcharts instance
*/
function PMA_createChart(passedSettings) {
var container = passedSettings.chart.renderTo;
var settings = {
chart: {
type: 'spline',
@ -1576,6 +1577,53 @@ function PMA_createChart(passedSettings) {
return new Highcharts.Chart(settings);
}
/*
* Creates a Profiling Chart. Used in sql.php and server_status.js
*/
function PMA_createProfilingChart(data, options) {
return PMA_createChart($.extend(true, {
chart: {
renderTo: 'profilingchart',
type: 'pie'
},
title: { text:'', margin:0 },
series: [{
type: 'pie',
name: PMA_messages['strQueryExecutionTime'],
data: data
}],
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
distance: 35,
formatter: function() {
return '<b>'+ this.point.name +'</b><br/>'+ Highcharts.numberFormat(this.percentage, 2) +' %';
}
}
}
},
tooltip: {
formatter: function() {
return '<b>'+ this.point.name +'</b><br/>'+PMA_prettyProfilingNum(this.y)+'<br/>('+Highcharts.numberFormat(this.percentage, 2) +' %)';
}
}
},options));
}
// Formats a profiling duration nicely. Used in PMA_createProfilingChart() and server_status.js
function PMA_prettyProfilingNum(num, acc) {
if(!acc) acc = 1;
acc = Math.pow(10,acc);
if(num*1000 < 0.1) num = Math.round(acc*(num*1000*1000))/acc + 'µ'
else if(num < 0.1) num = Math.round(acc*(num*1000))/acc + 'm'
return num + 's';
}
/**
* jQuery function that uses jQueryUI's dialogs to confirm with user. Does not
* return a jQuery object yet and hence cannot be chained
@ -2455,65 +2503,65 @@ var toggleButton = function ($obj) {
} else {
var right = 'left';
}
/**
* var h Height of the button, used to scale the
* background image and position the layers
*/
var h = $obj.height();
$('img', $obj).height(h);
$('table', $obj).css('bottom', h-1);
/**
* var on Width of the "ON" part of the toggle switch
* var off Width of the "OFF" part of the toggle switch
*/
var on = $('.toggleOn', $obj).width();
var off = $('.toggleOff', $obj).width();
// Make the "ON" and "OFF" parts of the switch the same size
$('.toggleOn > div', $obj).width(Math.max(on, off));
$('.toggleOff > div', $obj).width(Math.max(on, off));
/**
* var w Width of the central part of the switch
*/
var w = parseInt(($('img', $obj).height() / 16) * 22, 10);
// Resize the central part of the switch on the top
// layer to match the background
$('table td:nth-child(2) > div', $obj).width(w);
/**
* var imgw Width of the background image
* var tblw Width of the foreground layer
* var offset By how many pixels to move the background
* image, so that it matches the top layer
*/
var imgw = $('img', $obj).width();
var tblw = $('table', $obj).width();
var offset = parseInt(((imgw - tblw) / 2), 10);
// Move the background to match the layout of the top layer
$obj.find('img').css(right, offset);
/**
* var offw Outer width of the "ON" part of the toggle switch
* var btnw Outer width of the central part of the switch
*/
var offw = $('.toggleOff', $obj).outerWidth();
var btnw = $('table td:nth-child(2)', $obj).outerWidth();
// Resize the main div so that exactly one side of
// the switch plus the central part fit into it.
$obj.width(offw + btnw + 2);
/**
* var move How many pixels to move the
* switch by when toggling
*/
var move = $('.toggleOff', $obj).outerWidth();
// If the switch is initialized to the
// OFF state we need to move it now.
if ($('.container', $obj).hasClass('off')) {
/**
* var h Height of the button, used to scale the
* background image and position the layers
*/
var h = $obj.height();
$('img', $obj).height(h);
$('table', $obj).css('bottom', h-1);
/**
* var on Width of the "ON" part of the toggle switch
* var off Width of the "OFF" part of the toggle switch
*/
var on = $('.toggleOn', $obj).width();
var off = $('.toggleOff', $obj).width();
// Make the "ON" and "OFF" parts of the switch the same size
$('.toggleOn > div', $obj).width(Math.max(on, off));
$('.toggleOff > div', $obj).width(Math.max(on, off));
/**
* var w Width of the central part of the switch
*/
var w = parseInt(($('img', $obj).height() / 16) * 22, 10);
// Resize the central part of the switch on the top
// layer to match the background
$('table td:nth-child(2) > div', $obj).width(w);
/**
* var imgw Width of the background image
* var tblw Width of the foreground layer
* var offset By how many pixels to move the background
* image, so that it matches the top layer
*/
var imgw = $('img', $obj).width();
var tblw = $('table', $obj).width();
var offset = parseInt(((imgw - tblw) / 2), 10);
// Move the background to match the layout of the top layer
$obj.find('img').css(right, offset);
/**
* var offw Outer width of the "ON" part of the toggle switch
* var btnw Outer width of the central part of the switch
*/
var offw = $('.toggleOff', $obj).outerWidth();
var btnw = $('table td:nth-child(2)', $obj).outerWidth();
// Resize the main div so that exactly one side of
// the switch plus the central part fit into it.
$obj.width(offw + btnw + 2);
/**
* var move How many pixels to move the
* switch by when toggling
*/
var move = $('.toggleOff', $obj).outerWidth();
// If the switch is initialized to the
// OFF state we need to move it now.
if ($('.container', $obj).hasClass('off')) {
if (right == 'right') {
$('table, img', $obj).animate({'left': '-=' + move + 'px'}, 0);
$('table, img', $obj).animate({'left': '-=' + move + 'px'}, 0);
} else {
$('table, img', $obj).animate({'left': '+=' + move + 'px'}, 0);
$('table, img', $obj).animate({'left': '+=' + move + 'px'}, 0);
}
}
// Attach an 'onclick' event to the switch
$('.container', $obj).click(function () {
}
// Attach an 'onclick' event to the switch
$('.container', $obj).click(function () {
if ($(this).hasClass('isActive')) {
return false;
} else {
@ -2522,8 +2570,8 @@ var toggleButton = function ($obj) {
var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']);
var $container = $(this);
var callback = $('.callback', this).text();
// Perform the actual toggle
if ($(this).hasClass('on')) {
// Perform the actual toggle
if ($(this).hasClass('on')) {
if (right == 'right') {
var operator = '-=';
} else {
@ -2532,7 +2580,7 @@ var toggleButton = function ($obj) {
var url = $(this).find('.toggleOff > span').text();
var removeClass = 'on';
var addClass = 'off';
} else {
} else {
if (right == 'right') {
var operator = '+=';
} else {
@ -2545,10 +2593,10 @@ var toggleButton = function ($obj) {
$.post(url, {'ajax_request': true}, function(data) {
if(data.success == true) {
PMA_ajaxRemoveMessage($msg);
$container
.removeClass(removeClass)
.addClass(addClass)
.animate({'left': operator + move + 'px'}, function () {
$container
.removeClass(removeClass)
.addClass(addClass)
.animate({'left': operator + move + 'px'}, function () {
$container.removeClass('isActive');
});
eval(callback);
@ -2557,7 +2605,7 @@ var toggleButton = function ($obj) {
$container.removeClass('isActive');
}
});
});
});
};
/**
@ -2568,8 +2616,8 @@ $(window).load(function () {
$(this)
.show()
.find('.toggleButton')
toggleButton($(this));
});
toggleButton($(this));
});
});
/**

View File

@ -10,21 +10,31 @@
*/
/* Options:
$('table').sortableTable({
ignoreRect: { top, left, width, height } - relative coordinates on each element. If the user clicks
in this area, it is not seen as a drag&drop request. Useful for toolbars etc.
events: {
start: callback function when the user starts dragging
drop: callback function after an element has been dropped
}
})
$('table').sortableTable({
ignoreRect: { top, left, width, height } - relative coordinates on each element. If the user clicks
in this area, it is not seen as a drag&drop request. Useful for toolbars etc.
events: {
start: callback function when the user starts dragging
drop: callback function after an element has been dropped
}
})
*/
/* Commands:
$('table').sortableTable('init') - equivalent to $('table').sortableTable()
$('table').sortableTable('refresh') - if the table has been changed, refresh correctly assigns all events again
$('table').sortableTable('destroy') - removes all events from the table
$('table').sortableTable('init') - equivalent to $('table').sortableTable()
$('table').sortableTable('refresh') - if the table has been changed, refresh correctly assigns all events again
$('table').sortableTable('destroy') - removes all events from the table
*/
/* Setup:
Can be applied on any table, there is just one convention.
Each cell (<td>) has to contain one and only one element (preferably div or span)
which is the actually draggable element.
*/
(function($) {
jQuery.fn.sortableTable = function(method) {

View File

@ -203,6 +203,7 @@ $js_messages['strSave'] = __('Save');
$js_messages['strHide'] = __('Hide');
$js_messages['strNoRowSelected'] = __('No rows selected');
$js_messages['strChangeTbl'] = __('Change');
$js_messages['strQueryExecutionTime'] = __('Query execution time');
/* For tbl_select.js */
$js_messages['strHideSearchCriteria'] = __('Hide search criteria');

View File

@ -1500,21 +1500,21 @@ $(function() {
limitTypes: opts.limitTypes
},
function(data) {
runtime.logData = $.parseJSON(data);
var logData = $.parseJSON(data);
if(runtime.logData.rows.length != 0) {
runtime.logDataCols = buildLogTable(runtime.logData);
if(logData.rows.length != 0) {
runtime.logDataCols = buildLogTable(logData);
/* Show some stats in the dialog */
$('#loadingLogsDialog').html('<p>' + PMA_messages['strLogDataLoaded'] + '</p>');
$.each(runtime.logData.sum, function(key, value) {
$.each(logData.sum, function(key, value) {
key = key.charAt(0).toUpperCase() + key.slice(1).toLowerCase();
if(key == 'Total') key = '<b>' + key + '</b>';
$('#loadingLogsDialog').append(key + ': ' + value + '<br/>');
});
/* Add filter options if more than a bunch of rows there to filter */
if(runtime.logData.numRows > 12) {
if(logData.numRows > 12) {
$('div#logTable').prepend(
'<fieldset id="logDataFilter">' +
' <legend>' + PMA_messages['strFilters'] + '</legend>' +
@ -1522,7 +1522,7 @@ $(function() {
' <label for="filterQueryText">' + PMA_messages['strFilterByWordRegexp'] + '</label>' +
' <input name="filterQueryText" type="text" id="filterQueryText" style="vertical-align: baseline;" />' +
' </div>' +
((runtime.logData.numRows > 250) ? ' <div class="formelement"><button name="startFilterQueryText" id="startFilterQueryText">' + PMA_messages['strFilter'] + '</button></div>' : '') +
((logData.numRows > 250) ? ' <div class="formelement"><button name="startFilterQueryText" id="startFilterQueryText">' + PMA_messages['strFilter'] + '</button></div>' : '') +
' <div class="formelement">' +
' <input type="checkbox" id="noWHEREData" name="noWHEREData" value="1" /> ' +
' <label for="noWHEREData"> ' + PMA_messages['strIgnoreWhereAndGroup'] + '</label>' +
@ -1536,7 +1536,7 @@ $(function() {
//preg_replace('/\s+([^=]+)=(\d+|((\'|"|)(?U)(.+)(?<!\\\)\4(\s+|$)))/i',' $1={} ',$str);
if(runtime.logData.numRows > 250) {
if(logData.numRows > 250) {
$('div#logTable button#startFilterQueryText').click(filterQueries);
} else {
$('div#logTable input#filterQueryText').keyup(filterQueries);
@ -1604,8 +1604,8 @@ $(function() {
}
} else {
$(this).text(runtime.logData.rows[i][queryColumnName]);
$(this).next().text('' + runtime.logData.rows[i][sumColumnName]);
$(this).text($(this).parent().data('query')[queryColumnName]);
$(this).next().text($(this).parent().data('query')[sumColumnName]);
}
}
@ -1658,11 +1658,21 @@ $(function() {
}
}
loadLogStatistics({
src: 'general',
start:1311076210*1000,
end:1311162689*1000,
removeVariables: true,
limitTypes: true
});
function buildLogTable(data) {
var rows = data.rows;
var cols = new Array();
var $table = $('<table border="0" class="sortable"></table>');
var $tBody, $tRow, $tCell;
var tableStr = '<table border="0" class="sortable">';
$('#logTable').html($table);
var formatValue = function(name, value) {
switch(name) {
@ -1674,27 +1684,152 @@ $(function() {
for(var i=0; i < rows.length; i++) {
if(i == 0) {
tableStr += '<thead>';
$.each(rows[0],function(key, value) {
cols.push(key);
});
tableStr += '<tr><th class="nowrap">' + cols.join('</th><th class="nowrap">') + '</th></tr>';
tableStr += '</thead><tbody>';
$table.append( '<thead>' +
'<tr><th class="nowrap">' + cols.join('</th><th class="nowrap">') + '</th></tr>' +
'</thead>');
$table.append($tBody = $('<tbody></tbody>'));
}
tableStr += '<tr>';
for(var j=0; j < cols.length; j++)
tableStr += '<td>' + formatValue(cols[j], rows[i][cols[j]]) + '</td>';
tableStr += '</tr>';
$tBody.append($tRow = $('<tr class="noclick"></tr>'));
var cl=''
for(var j=0; j < cols.length; j++) {
// Assuming the query column is the second last
if(j == cols.length - 2 && rows[i][cols[j]].match(/^SELECT/i)) {
$tRow.append($tCell=$('<td class="analyzableQuery">' + formatValue(cols[j], rows[i][cols[j]]) + '</td>'));
$tCell.click(queryAnalyzer);
} else
$tRow.append('<td>' + formatValue(cols[j], rows[i][cols[j]]) + '</td>');
$tRow.data('query',rows[i]);
}
}
tableStr += '</tbody><tfoot>';
tableStr += '<tr><th colspan="' + (cols.length - 1) + '">' + PMA_messages['strSumRows'] +
$table.append('<tfoot>' +
'<tr><th colspan="' + (cols.length - 1) + '">' + PMA_messages['strSumRows'] +
' '+ data.numRows +'<span style="float:right">' + PMA_messages['strTotal'] +
'</span></th><th align="right">' + data.sum.TOTAL + '</th></tr>';
tableStr += '</tfoot></table>';
'</span></th><th align="right">' + data.sum.TOTAL + '</th></tr></tfoot>');
$('#logTable').html(tableStr);
function queryAnalyzer() {
var query = $(this).parent().data('query')[cols[cols.length-2]];
/* A very basic SQL Formatter. Totally fails in the cases of
- Any string appearance containing a MySQL Keyword, surrounded by whitespaces
- Subqueries too probably
*/
var sLists = query.match(/SELECT\s+[^]+\s+FROM\s+/gi);
if(sLists) {
for(var i=0; i < sLists.length; i++) {
query = query.replace(sLists[i],sLists[i].replace(/\s*((`|'|"|).*?\1,)\s*/gi,'$1\n\t'));
}
query = query
.replace(/(\s+|^)(SELECT|FROM|WHERE|GROUP BY|HAVING|ORDER BY|LIMIT)(\s+|$)/gi,'\n$2\n\t')
.replace(/\s+UNION\s+/gi,'\n\nUNION\n\n')
.replace(/\s+(AND)\s+/gi,' $1\n\t')
.trim();
}
codemirror_editor.setValue(query);
var profilingChart = null;
$('div#queryAnalyzerDialog').dialog({
width: 'auto',
height: 'auto',
resizable: false,
buttons: {
'Analyse Query' : function() {
$('div#queryAnalyzerDialog div.placeHolder').html('Analyzing... ' + '<img class="ajaxIcon" src="' + pmaThemeImage + 'ajax_clock_small.gif" alt="">');
$.post('server_status.php?'+url_query, {
ajax_request: true,
query_analyzer: true,
query: codemirror_editor.getValue()
}, function(data) {
data = $.parseJSON(data);
var totalTime = 0;
if(data.error) {
$('div#queryAnalyzerDialog div.placeHolder').html('<div class="error">' + data.error + '</div>');
return;
}
// Float sux, I'll use table :(
$('div#queryAnalyzerDialog div.placeHolder')
.html('<table width="100%" border="0"><tr><td class="explain"></td><td class="chart"></td></tr></table>');
var explain = '<b>Explain output</b><p></p>';
$.each(data.explain, function(key,value) {
value = (value==null)?'null':value;
explain += key+': ' + value + '<br />';
});
$('div#queryAnalyzerDialog div.placeHolder td.explain').append(explain);
if(data.profiling) {
var chartData = [];
var numberTable = '<table class="queryNums"><thead><tr><th>Status</th><th>Time</th></tr></thead><tbody>';
var duration;
for(var i=0; i < data.profiling.length; i++) {
duration = parseFloat(data.profiling[i].duration);
chartData.push([data.profiling[i].state, duration]);
totalTime+=duration;
numberTable += '<tr><td>' + data.profiling[i].state + ' </td><td> ' + PMA_prettyProfilingNum(duration,2) + '</td></tr>';
}
numberTable += '<tr><td><b>Total time:</b></td><td>' + PMA_prettyProfilingNum(totalTime,2) + '</td></tr>';
numberTable += '</tbody></table>';
$('div#queryAnalyzerDialog div.placeHolder td.chart').append('<b>Profiling results</b> (<a href="#showNums">Table</a> | <a href="#showChart">Chart</a>)<br/>' + numberTable + ' <div id="queryProfiling"></div>');
$('div#queryAnalyzerDialog div.placeHolder a[href="#showNums"]').click(function() {
$('div#queryAnalyzerDialog div#queryProfiling').hide();
$('div#queryAnalyzerDialog table.queryNums').show();
return false;
});
$('div#queryAnalyzerDialog div.placeHolder a[href="#showChart"]').click(function() {
$('div#queryAnalyzerDialog div#queryProfiling').show();
$('div#queryAnalyzerDialog table.queryNums').hide();
return false;
});
profilingChart = PMA_createProfilingChart(chartData, {
chart: {
renderTo: 'queryProfiling'
},
plotOptions: {
pie: {
size: '50%'
}
}
});
$('div#queryProfiling').resizable();
}
});
},
'Close' : function() {
if(profilingChart != null) {
profilingChart.destroy();
}
$('div#queryAnalyzerDialog div.placeHolder').html('');
codemirror_editor.setValue('');
$(this).dialog("close");
}
}
});
}
// Append a tooltip to the count column, if there exist one
if($('#logTable th:last').html() == '#') {
@ -1715,7 +1850,7 @@ $(function() {
hide: { delay: 1000 }
})
}
$('div#logTable table').tablesorter({
sortList: [[cols.length - 1,1]],
widgets: ['zebra']

View File

@ -1227,45 +1227,18 @@ $(document).ready(function() {
/*
* Profiling Chart
*/
function createProfilingChart() {
function makeProfilingChart() {
if($('#profilingchart').length==0) return;
var cdata = new Array();
var data = new Array();
$.each(jQuery.parseJSON($('#profilingchart').html()),function(key,value) {
cdata.push([key,parseFloat(value)]);
data.push([key,parseFloat(value)]);
});
// Prevent the user from seeing the JSON code
$('div#profilingchart').html('').show();
PMA_createChart({
chart: {
renderTo: 'profilingchart',
backgroundColor: $('#sqlqueryresults fieldset').css('background-color')
},
title: { text:'', margin:0 },
series: [{
type:'pie',
name: 'Query execution time',
data: cdata
}],
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
distance: 35,
formatter: function() {
return '<b>'+ this.point.name +'</b><br/>'+ Highcharts.numberFormat(this.percentage, 2) +' %';
}
}
}
},
tooltip: {
formatter: function() { return '<b>'+ this.point.name +'</b><br/>'+this.y+'s<br/>('+Highcharts.numberFormat(this.percentage, 2) +' %)'; }
}
});
PMA_createProfilingChart(data);
}

View File

@ -20,21 +20,6 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true)
require_once './libraries/common.inc.php';
/**
* Function to output refresh rate selection.
*/
function PMA_choose_refresh_rate() {
echo '<option value="5">' . __('Refresh rate') . '</option>';
foreach (array(1, 2, 5, 20, 40, 60, 120, 300, 600) as $rate) {
if ($rate % 60 == 0) {
$minrate = $rate / 60;
echo '<option value="' . $rate . '">' . sprintf(_ngettext('%d minute', '%d minutes', $minrate), $minrate) . '</option>';
} else {
echo '<option value="' . $rate . '">' . sprintf(_ngettext('%d second', '%d seconds', $rate), $rate) . '</option>';
}
}
}
/**
* Ajax request
*/
@ -43,20 +28,6 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) {
// Send with correct charset
header('Content-Type: text/html; charset=UTF-8');
if (isset($_REQUEST['logging_vars'])) {
if(isset($_REQUEST['varName']) && isset($_REQUEST['varValue'])) {
$value = PMA_sqlAddslashes($_REQUEST['varValue']);
if(!is_numeric($value)) $value="'".$value."'";
if(! preg_match("/[^a-zA-Z0-9_]+/",$_REQUEST['varName']))
PMA_DBI_query('SET GLOBAL '.$_REQUEST['varName'].' = '.$value);
}
$loggingVars = PMA_DBI_fetch_result('SHOW GLOBAL VARIABLES WHERE Variable_name IN ("general_log","slow_query_log","long_query_time","log_output")', 0, 1);
exit(json_encode($loggingVars));
}
// real-time charting data
if (isset($_REQUEST['chart_data'])) {
switch($_REQUEST['type']) {
@ -261,6 +232,49 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) {
exit(json_encode($return));
}
}
if (isset($_REQUEST['logging_vars'])) {
if(isset($_REQUEST['varName']) && isset($_REQUEST['varValue'])) {
$value = PMA_sqlAddslashes($_REQUEST['varValue']);
if(!is_numeric($value)) $value="'".$value."'";
if(! preg_match("/[^a-zA-Z0-9_]+/",$_REQUEST['varName']))
PMA_DBI_query('SET GLOBAL '.$_REQUEST['varName'].' = '.$value);
}
$loggingVars = PMA_DBI_fetch_result('SHOW GLOBAL VARIABLES WHERE Variable_name IN ("general_log","slow_query_log","long_query_time","log_output")', 0, 1);
exit(json_encode($loggingVars));
}
if(isset($_REQUEST['query_analyzer'])) {
$return = array();
if ($profiling = PMA_profilingSupported())
PMA_DBI_query('SET PROFILING=1;');
// Do not cache query
$query = preg_replace('/^(\s*SELECT)/i','\\1 SQL_NO_CACHE',$_REQUEST['query']);
$result = PMA_DBI_try_query('EXPLAIN ' . $query);
$return['explain'] = PMA_DBI_fetch_assoc($result);
// In case an error happened
$return['error'] = PMA_DBI_getError();
PMA_DBI_free_result($result);
if($profiling) {
$return['profiling'] = array();
$result = PMA_DBI_try_query('SELECT seq,state,duration FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID=1 ORDER BY seq');
while ($row = PMA_DBI_fetch_assoc($result)) {
$return['profiling'][]= $row;
}
PMA_DBI_free_result($result);
}
exit(json_encode($return));
}
}
@ -1446,6 +1460,12 @@ function printMonitor() {
<?php echo __('<p>Choose from which log you want the statistics to be generated from.</p> Results are grouped by query text.'); ?>
</div>
<div id="queryAnalyzerDialog" title="<?php echo __('Query analyzer'); ?>" style="display:none;">
<textarea id="sqlquery"> </textarea>
<p></p>
<div class="placeHolder"></div>
</div>
<table border="0" class="clearfloat" id="chartGrid">
</table>

View File

@ -932,7 +932,7 @@ else {
<script type="text/javascript">
pma_token = '<?php echo $_SESSION[' PMA_token ']; ?>';
url_query = '<?php echo isset($url_query)?$url_query:PMA_generate_common_url($db);?>';
$(document).ready(createProfilingChart);
$(document).ready(makeProfilingChart);
</script>
<?php
echo '<fieldset><legend>' . __('Profiling') . '</legend>' . "\n";

View File

@ -1308,6 +1308,12 @@ div#tablestatistics table {
/* serverstatus */
div#logTable table td.analyzableQuery:hover {
text-decoration: underline;
color: #235a81;
cursor: pointer;
}
h3#serverstatusqueries span {
font-size:60%;
display:inline;
@ -1316,7 +1322,7 @@ h3#serverstatusqueries span {
img.sortableIcon {
float:right;
background-repeat:no-repeat;
margin:0;
margin:0;
}
.buttonlinks {
@ -1425,10 +1431,33 @@ div#logTable table {
width:100%;
}
div#queryAnalyzerDialog {
min-width: 700px;
}
div#queryAnalyzerDialog div.CodeMirror-scroll {
height:auto;
}
div#queryAnalyzerDialog div#queryProfiling {
height: 250px;
}
div#queryAnalyzerDialog td.explain {
width: 250px;
}
div#queryAnalyzerDialog table.queryNums {
display: none;
border:0;
text-align:left;
}
.smallIndent {
padding-left: 7px;
}
/* end serverstatus */
/* server variables */