Merge remote-tracking branch 'tyron/master'

Conflicts:
	js/functions.js
	js/server_status.js
	js/sql.js
	libraries/common.lib.php
	server_status.php
	themes/pmahomme/css/theme_left.css.php
This commit is contained in:
Michal Čihař 2011-07-25 11:29:17 +02:00
commit f34dfda0fe
17 changed files with 3175 additions and 750 deletions

View File

@ -210,7 +210,13 @@ function confirmLink(theLink, theSqlQuery)
var is_confirmed = confirm(PMA_messages['strDoYouReally'] + ' :\n' + theSqlQuery);
if (is_confirmed) {
if ( typeof(theLink.href) != 'undefined' ) {
if ( $(theLink).hasClass('formLinkSubmit') ) {
var name = 'is_js_confirmed';
if($(theLink).attr('href').indexOf('usesubform') != -1)
name = 'subform[' + $(theLink).attr('href').substr('#').match(/usesubform\[(\d+)\]/i)[1] + '][is_js_confirmed]';
$(theLink).parents('form').append('<input type="hidden" name="' + name + '" value="1" />');
} else if ( typeof(theLink.href) != 'undefined' ) {
theLink.href += '&is_js_confirmed=1';
} else if ( typeof(theLink.form) != 'undefined' ) {
theLink.form.action += '?is_js_confirmed=1';
@ -265,59 +271,51 @@ function confirmQuery(theForm1, sqlQuery1)
return true;
}
// The replace function (js1.2) isn't supported
else if (typeof(sqlQuery1.value.replace) == 'undefined') {
return true;
}
// js1.2+ -> validation with regular expressions
else {
// "DROP DATABASE" statement isn't allowed
if (PMA_messages['strNoDropDatabases'] != '') {
var drop_re = new RegExp('(^|;)\\s*DROP\\s+(IF EXISTS\\s+)?DATABASE\\s', 'i');
if (drop_re.test(sqlQuery1.value)) {
alert(PMA_messages['strNoDropDatabases']);
theForm1.reset();
sqlQuery1.focus();
return false;
} // end if
// "DROP DATABASE" statement isn't allowed
if (PMA_messages['strNoDropDatabases'] != '') {
var drop_re = new RegExp('(^|;)\\s*DROP\\s+(IF EXISTS\\s+)?DATABASE\\s', 'i');
if (drop_re.test(sqlQuery1.value)) {
alert(PMA_messages['strNoDropDatabases']);
theForm1.reset();
sqlQuery1.focus();
return false;
} // end if
} // end if
// Confirms a "DROP/DELETE/ALTER/TRUNCATE" statement
//
// TODO: find a way (if possible) to use the parser-analyser
// for this kind of verification
// For now, I just added a ^ to check for the statement at
// beginning of expression
// Confirms a "DROP/DELETE/ALTER/TRUNCATE" statement
//
// TODO: find a way (if possible) to use the parser-analyser
// for this kind of verification
// For now, I just added a ^ to check for the statement at
// beginning of expression
var do_confirm_re_0 = new RegExp('^\\s*DROP\\s+(IF EXISTS\\s+)?(TABLE|DATABASE|PROCEDURE)\\s', 'i');
var do_confirm_re_1 = new RegExp('^\\s*ALTER\\s+TABLE\\s+((`[^`]+`)|([A-Za-z0-9_$]+))\\s+DROP\\s', 'i');
var do_confirm_re_2 = new RegExp('^\\s*DELETE\\s+FROM\\s', 'i');
var do_confirm_re_3 = new RegExp('^\\s*TRUNCATE\\s', 'i');
var do_confirm_re_0 = new RegExp('^\\s*DROP\\s+(IF EXISTS\\s+)?(TABLE|DATABASE|PROCEDURE)\\s', 'i');
var do_confirm_re_1 = new RegExp('^\\s*ALTER\\s+TABLE\\s+((`[^`]+`)|([A-Za-z0-9_$]+))\\s+DROP\\s', 'i');
var do_confirm_re_2 = new RegExp('^\\s*DELETE\\s+FROM\\s', 'i');
var do_confirm_re_3 = new RegExp('^\\s*TRUNCATE\\s', 'i');
if (do_confirm_re_0.test(sqlQuery1.value)
|| do_confirm_re_1.test(sqlQuery1.value)
|| do_confirm_re_2.test(sqlQuery1.value)
|| do_confirm_re_3.test(sqlQuery1.value)) {
var message = (sqlQuery1.value.length > 100)
? sqlQuery1.value.substr(0, 100) + '\n ...'
: sqlQuery1.value;
var is_confirmed = confirm(PMA_messages['strDoYouReally'] + ' :\n' + message);
// statement is confirmed -> update the
// "is_js_confirmed" form field so the confirm test won't be
// run on the server side and allows to submit the form
if (is_confirmed) {
theForm1.elements['is_js_confirmed'].value = 1;
return true;
}
// statement is rejected -> do not submit the form
else {
window.focus();
sqlQuery1.focus();
return false;
} // end if (handle confirm box result)
} // end if (display confirm box)
} // end confirmation stuff
if (do_confirm_re_0.test(sqlQuery1.value)
|| do_confirm_re_1.test(sqlQuery1.value)
|| do_confirm_re_2.test(sqlQuery1.value)
|| do_confirm_re_3.test(sqlQuery1.value)) {
var message = (sqlQuery1.value.length > 100)
? sqlQuery1.value.substr(0, 100) + '\n ...'
: sqlQuery1.value;
var is_confirmed = confirm(PMA_messages['strDoYouReally'] + ' :\n' + message);
// statement is confirmed -> update the
// "is_js_confirmed" form field so the confirm test won't be
// run on the server side and allows to submit the form
if (is_confirmed) {
theForm1.elements['is_js_confirmed'].value = 1;
return true;
}
// statement is rejected -> do not submit the form
else {
window.focus();
sqlQuery1.focus();
return false;
} // end if (handle confirm box result)
} // end if (display confirm box)
return true;
} // end of the 'confirmQuery()' function
@ -360,47 +358,31 @@ function checkSqlQuery(theForm)
var sqlQuery = theForm.elements['sql_query'];
var isEmpty = 1;
// The replace function (js1.2) isn't supported -> basic tests
if (typeof(sqlQuery.value.replace) == 'undefined') {
isEmpty = (sqlQuery.value == '') ? 1 : 0;
if (isEmpty && typeof(theForm.elements['sql_file']) != 'undefined') {
isEmpty = (theForm.elements['sql_file'].value == '') ? 1 : 0;
}
if (isEmpty && typeof(theForm.elements['sql_localfile']) != 'undefined') {
isEmpty = (theForm.elements['sql_localfile'].value == '') ? 1 : 0;
}
if (isEmpty && typeof(theForm.elements['id_bookmark']) != 'undefined') {
isEmpty = (theForm.elements['id_bookmark'].value == null || theForm.elements['id_bookmark'].value == '');
var space_re = new RegExp('\\s+');
if (typeof(theForm.elements['sql_file']) != 'undefined' &&
theForm.elements['sql_file'].value.replace(space_re, '') != '') {
return true;
}
if (typeof(theForm.elements['sql_localfile']) != 'undefined' &&
theForm.elements['sql_localfile'].value.replace(space_re, '') != '') {
return true;
}
if (isEmpty && typeof(theForm.elements['id_bookmark']) != 'undefined' &&
(theForm.elements['id_bookmark'].value != null || theForm.elements['id_bookmark'].value != '') &&
theForm.elements['id_bookmark'].selectedIndex != 0
) {
return true;
}
// Checks for "DROP/DELETE/ALTER" statements
if (sqlQuery.value.replace(space_re, '') != '') {
if (confirmQuery(theForm, sqlQuery)) {
return true;
} else {
return false;
}
}
// js1.2+ -> validation with regular expressions
else {
var space_re = new RegExp('\\s+');
if (typeof(theForm.elements['sql_file']) != 'undefined' &&
theForm.elements['sql_file'].value.replace(space_re, '') != '') {
return true;
}
if (typeof(theForm.elements['sql_localfile']) != 'undefined' &&
theForm.elements['sql_localfile'].value.replace(space_re, '') != '') {
return true;
}
if (isEmpty && typeof(theForm.elements['id_bookmark']) != 'undefined' &&
(theForm.elements['id_bookmark'].value != null || theForm.elements['id_bookmark'].value != '') &&
theForm.elements['id_bookmark'].selectedIndex != 0
) {
return true;
}
// Checks for "DROP/DELETE/ALTER" statements
if (sqlQuery.value.replace(space_re, '') != '') {
if (confirmQuery(theForm, sqlQuery)) {
return true;
} else {
return false;
}
}
theForm.reset();
isEmpty = 1;
}
theForm.reset();
isEmpty = 1;
if (isEmpty) {
sqlQuery.select();
@ -423,19 +405,9 @@ function checkSqlQuery(theForm)
*/
function emptyCheckTheField(theForm, theFieldName)
{
var isEmpty = 1;
var theField = theForm.elements[theFieldName];
// Whether the replace function (js1.2) is supported or not
var isRegExp = (typeof(theField.value.replace) != 'undefined');
if (!isRegExp) {
isEmpty = (theField.value == '') ? 1 : 0;
} else {
var space_re = new RegExp('\\s+');
isEmpty = (theField.value.replace(space_re, '') == '') ? 1 : 0;
}
return isEmpty;
var space_re = new RegExp('\\s+');
return (theField.value.replace(space_re, '') == '') ? 1 : 0;
} // end of the 'emptyCheckTheField()' function
@ -1457,6 +1429,8 @@ 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
* error: Callback function when the get request fails. TODO: Apply callback on timeouts aswell
* }
*
* @return object The created highcharts instance
*/
@ -1467,7 +1441,7 @@ function PMA_createChart(passedSettings) {
chart: {
type: 'spline',
marginRight: 10,
backgroundColor: 'transparent',
backgroundColor: 'none',
events: {
/* Live charting support */
load: function() {
@ -1488,7 +1462,13 @@ function PMA_createChart(passedSettings) {
thisChart.options.realtime.url,
thisChart.options.realtime.postData,
function(data) {
curValue = jQuery.parseJSON(data);
try {
curValue = jQuery.parseJSON(data);
} catch (err) {
if(thisChart.options.realtime.error)
thisChart.options.realtime.error(err);
return;
}
if(lastValue==null) diff = curValue.x - thisChart.xAxis[0].getExtremes().max;
else diff = parseInt(curValue.x - lastValue.x);
@ -1578,6 +1558,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
@ -2710,22 +2737,15 @@ $(document).ready(function() {
/**
* Enables the text generated by PMA_linkOrButton() to be clickable
*/
$('.clickprevimage')
.css('color', function(index) {
return $('a').css('color');
})
.css('cursor', function(index) {
return $('a').css('cursor');
}) //todo: hover effect
.live('click',function(e) {
$this_span = $(this);
if ($this_span.closest('td').is('.inline_edit_anchor')) {
// this would bind a second click event to the inline edit
// anchor and would disturb its behavior
} else {
$this_span.parent().find('input:image').click();
}
});
$('a[class~="formLinkSubmit"]').live('click',function(e) {
if($(this).attr('href').indexOf('=') != -1) {
var data = $(this).attr('href').substr($(this).attr('href').indexOf('#')+1).split('=',2);
$(this).parents('form').append('<input type="hidden" name="' + data[0] + '" value="' + data[1] + '"/>');
}
$(this).parents('form').submit();
return false;
});
$('#update_recent_tables').ready(function() {
if (window.parent.frame_navigation != undefined

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

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

@ -137,9 +137,6 @@ $js_messages['strChartTitle'] = __('Chart Title');
$js_messages['strDifferential'] = __('Differential');
$js_messages['strDividedBy'] = __('Divided by %s:');
$js_messages['strSelectedTimeRange'] = __('Selected time range:');
$js_messages['strGroupInserts'] = __('Group together INSERTs into same table');
$js_messages['strLogAnalyseInfo'] = __('<p>Choose from which log you want the statistics to be generated from.</p> Results are grouped by query text.');
$js_messages['strFromSlowLog'] = __('From slow log');
$js_messages['strFromGeneralLog'] = __('From general log');
$js_messages['strAnalysingLogs'] = __('Analysing & loading logs. This may take a while.');
@ -150,6 +147,15 @@ $js_messages['strLogDataLoaded'] = __('Log data loaded. Queries executed in this
$js_messages['strJumpToTable'] = __('Jump to Log table');
$js_messages['strNoDataFound'] = __('Log analysed, but not data found in this time span.');
/* l10n: A collection of available filters */
$js_messages['strFilters'] = __('Filters');
/* l10n: Filter as in "Start Filtering" */
$js_messages['strFilter'] = __('Filter');
$js_messages['strFilterByWordRegexp'] = __('Filter queries by word/regexp:');
$js_messages['strIgnoreWhereAndGroup'] = __('Group queries, ignoring variable data in WHERE statements');
$js_messages['strSumRows'] = __('Sum of grouped rows:');
$js_messages['strTotal'] = __('Total:');
/* For inline query editing */
$js_messages['strGo'] = __('Go');
$js_messages['strCancel'] = __('Cancel');
@ -199,6 +205,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');

File diff suppressed because it is too large Load Diff

View File

@ -55,6 +55,7 @@ function getFieldName($this_field) {
function appendInlineAnchor() {
// TODO: remove two lines below if vertical display mode has been completely removed
var disp_mode = $("#top_direction_dropdown").val();
if (disp_mode != 'vertical') {
$('.edit_row_anchor').each(function() {
@ -65,8 +66,9 @@ function appendInlineAnchor() {
var $img_object = $cloned_anchor.find('img').attr('title', PMA_messages['strInlineEdit']);
if ($img_object.length != 0) {
var img_class = $img_object.attr('class').replace(/b_edit/,'b_inline_edit');
$img_object.attr('class', img_class);
$img_object.removeClass('ic_b_edit');
$img_object.addClass('ic_b_inline_edit');
$cloned_anchor.find('a').attr('href', '#');
var $edit_span = $cloned_anchor.find('span:contains("' + PMA_messages['strEdit'] + '")');
var $span = $cloned_anchor.find('a').find('span');
@ -85,8 +87,8 @@ function appendInlineAnchor() {
// the link was too big so <input type="image"> is there
$img_object = $cloned_anchor.find('input:image').attr('title', PMA_messages['strInlineEdit']);
if ($img_object.length > 0) {
var img_class = $img_object.attr('class').replace(/b_edit/,'b_inline_edit');
$img_object.attr('class', img_class);
$img_object.removeClass('ic_b_edit');
$img_object.addClass('ic_b_inline_edit');
}
$cloned_anchor
.find('.clickprevimage')
@ -445,8 +447,8 @@ $(document).ready(function() {
// If icons are displayed. See $cfg['PropertiesIconic']
if ($img_object.length > 0) {
$img_object.attr('title', PMA_messages['strSave']);
var img_class = $img_object.attr('class').replace(/b_inline_edit/,'b_save');
$img_object.attr('class', img_class);
$img_object.removeClass('ic_b_inline_edit');
$img_object.addClass('ic_b_save');
$this_children.prepend($img_object);
}
@ -465,8 +467,8 @@ $(document).ready(function() {
// If icons are displayed. See $cfg['PropertiesIconic']
if ($img_object.length > 0) {
$img_object.attr('title', PMA_messages['strHide']);
var img_class = $img_object.attr('class').replace(/b_save/,'b_close');
$img_object.attr('class', img_class);
$img_object.removeClass('ic_b_save');
$img_object.addClass('ic_b_close');
$hide_span.prepend($img_object);
}
@ -1230,47 +1232,20 @@ $(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

@ -66,9 +66,10 @@ function PMA_pow($base, $exp, $use_function = false)
* @param string $alternate alternate text
* @param boolean $container include in container
* @param boolean $force_text whether to force alternate text to be displayed
* @param boolean $noSprite If true, the image source will be not replaced with a CSS Sprite
* @return html img tag
*/
function PMA_getIcon($icon, $alternate = '', $container = false, $force_text = false)
function PMA_getIcon($icon, $alternate = '', $container = false, $force_text = false, $noSprite = false)
{
$include_icon = false;
$include_text = false;
@ -80,9 +81,7 @@ function PMA_getIcon($icon, $alternate = '', $container = false, $force_text = f
$include_icon = true;
}
if ($force_text
|| ! (true === $GLOBALS['cfg']['PropertiesIconic'])
|| ! $include_icon) {
if ($force_text || true !== $GLOBALS['cfg']['PropertiesIconic']) {
// $cfg['PropertiesIconic'] is false or both
// OR we have no $include_icon
$include_text = true;
@ -97,9 +96,14 @@ function PMA_getIcon($icon, $alternate = '', $container = false, $force_text = f
$button .= '<span class="nowrap">';
if ($include_icon) {
$button .= '<img src="themes/dot.gif"'
. ' title="' . $alternate . '" alt="' . $alternate . '"'
. ' class="icon ic_' . str_replace('.png','',$icon) . '" />';
if($noSprite) {
$button .= '<img src="' . $GLOBALS['pmaThemeImage'] . $icon . '"'
. ' class="icon" width="16" height="16" />';
} else {
$button .= '<img src="themes/dot.gif"'
. ' title="' . $alternate . '" alt="' . $alternate . '"'
. ' class="icon ic_' . str_replace(array('.gif','.png'),array('',''),$icon) . '" />';
}
}
if ($include_icon && $include_text) {
@ -474,7 +478,7 @@ function PMA_showHint($message, $bbcode = false, $type = 'notice')
// footnotemarker used in js/tooltip.js
return '<sup class="footnotemarker">' . $nr . '</sup>' .
'<img class="footnotemarker ic_b_help footnote_' . $nr . '" src="themes/dot.gif" alt="" />';
'<img class="footnotemarker footnote_' . $nr . ' ic_b_help" src="themes/dot.gif" alt="" />';
}
/**
@ -1648,6 +1652,7 @@ function PMA_linkOrButton($url, $message, $tag_params = array(),
return '';
}
if (! is_array($tag_params)) {
$tmp = $tag_params;
$tag_params = array();
@ -1669,11 +1674,17 @@ function PMA_linkOrButton($url, $message, $tag_params = array(),
$tag_params_strings[] = $par_name . '="' . $par_value . '"';
}
$displayed_message = '';
// Add text if not already added
if (stristr($message, '<img') && (!$strip_img || $GLOBALS['cfg']['PropertiesIconic'] === true) && strip_tags($message)==$message) {
$displayed_message = '<span>' . htmlspecialchars(preg_replace('/^.*\salt="([^"]*)".*$/si', '\1', $message)) . '</span>';
}
if ($url_length <= $GLOBALS['cfg']['LinkLengthLimit']) {
// no whitespace within an <a> else Safari will make it part of the link
$ret = "\n" . '<a href="' . $url . '" '
. implode(' ', $tag_params_strings) . '>'
. $message . '</a>' . "\n";
. $message . $displayed_message . '</a>' . "\n";
} else {
// no spaces (linebreaks) at all
// or after the hidden fields
@ -1702,7 +1713,7 @@ function PMA_linkOrButton($url, $message, $tag_params = array(),
. ' method="post"' . $target . ' style="display: inline;">';
$subname_open = '';
$subname_close = '';
$submit_name = '';
$submit_link = '#';
} else {
$query_parts[] = 'redirect=' . $url_parts['path'];
if (empty($GLOBALS['subform_counter'])) {
@ -1712,7 +1723,7 @@ function PMA_linkOrButton($url, $message, $tag_params = array(),
$ret = '';
$subname_open = 'subform[' . $GLOBALS['subform_counter'] . '][';
$subname_close = ']';
$submit_name = ' name="usesubform[' . $GLOBALS['subform_counter'] . ']"';
$submit_link = '#usesubform[' . $GLOBALS['subform_counter'] . ']=1';
}
foreach ($query_parts as $query_pair) {
list($eachvar, $eachval) = explode('=', $query_pair);
@ -1721,35 +1732,10 @@ function PMA_linkOrButton($url, $message, $tag_params = array(),
. htmlspecialchars(urldecode($eachval)) . '" />';
} // end while
if (stristr($message, '<img')) {
if ($strip_img) {
$message = trim(strip_tags($message));
$ret .= '<input type="submit"' . $submit_name . ' '
. implode(' ', $tag_params_strings)
. ' value="' . htmlspecialchars($message) . '" />';
} else {
$displayed_message = htmlspecialchars(
preg_replace('/^.*\salt="([^"]*)".*$/si', '\1',
$message));
$ret .= '<input type="image"' . $submit_name . ' '
. implode(' ', $tag_params_strings)
. ' src="' . preg_replace(
'/^.*\ssrc="([^"]*)".*$/si', '\1', $message) . '"'
. ' value="' . $displayed_message . '" title="' . $displayed_message . '" />';
// Here we cannot obey PropertiesIconic completely as a
// generated link would have a length over LinkLengthLimit
// but we can at least show the message.
// If PropertiesIconic is false or 'both'
if ($GLOBALS['cfg']['PropertiesIconic'] !== true) {
$ret .= ' <span class="clickprevimage">' . $displayed_message . '</span>';
}
}
} else {
$message = trim(strip_tags($message));
$ret .= '<input type="submit"' . $submit_name . ' '
. implode(' ', $tag_params_strings)
. ' value="' . htmlspecialchars($message) . '" />';
}
$ret .= "\n" . '<a href="' . $submit_link . '" class="formLinkSubmit" '
. implode(' ', $tag_params_strings) . '>'
. $message . ' ' . $displayed_message . '</a>' . "\n";
if ($new_form) {
$ret .= '</form>';
}

View File

@ -33,7 +33,7 @@ if (! isset($page_title)) {
$is_superuser = function_exists('PMA_isSuperuser') && PMA_isSuperuser();
$GLOBALS['js_include'][] = 'functions.js';
$GLOBALS['js_include'][] = 'jquery/jquery.qtip-1.0.0.min.js';
$GLOBALS['js_include'][] = 'jquery/jquery.qtip-1.0.0-rc3.js';
$params = array('lang' => $GLOBALS['lang']);
if (isset($GLOBALS['db'])) {
$params['db'] = $GLOBALS['db'];

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,22 +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']) {
@ -203,10 +172,14 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) {
exit(json_encode($return));
}
if ($_REQUEST['type'] == 'general') {
$q = 'SELECT TIME(event_time) as event_time, user_host, thread_id, server_id, argument, count(argument) as \'#\' FROM `mysql`.`general_log` WHERE command_type=\'Query\' '.
if($_REQUEST['type'] == 'general') {
$limitTypes = (isset($_REQUEST['limitTypes']) && $_REQUEST['limitTypes'])
? 'AND argument REGEXP \'^(INSERT|SELECT|UPDATE|DELETE)\' ' : '';
$q = 'SELECT TIME(event_time) as event_time, user_host, thread_id, server_id, argument, count(argument) as \'#\' '.
'FROM `mysql`.`general_log` WHERE command_type=\'Query\' '.
'AND event_time > FROM_UNIXTIME('.$start.') AND event_time < FROM_UNIXTIME('.$end.') '.
'AND argument REGEXP \'^(INSERT|SELECT|UPDATE|DELETE)\' GROUP by argument'; // HAVING count > 1';
$limitTypes . 'GROUP by argument'; // HAVING count > 1';
$result = PMA_DBI_try_query($q);
@ -215,38 +188,47 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) {
$insertTables = array();
$insertTablesFirst = -1;
$i = 0;
$removeVars = isset($_REQUEST['removeVariables']) && $_REQUEST['removeVariables'];
while ($row = PMA_DBI_fetch_assoc($result)) {
preg_match('/^(\w+)\s/',$row['argument'],$match);
$type = strtolower($match[1]);
// Ignore undefined index warning, just increase counter by one
@$return['sum'][$type] += $row['#'];
if ($type=='insert' || $type=='update') {
// Group inserts if selected
if ($type=='insert' && isset($_REQUEST['groupInserts']) && $_REQUEST['groupInserts'] && preg_match('/^INSERT INTO (`|\'|"|)([^\s\\1]+)\\1/i',$row['argument'],$matches)) {
$insertTables[$matches[2]]++;
if ($insertTables[$matches[2]] > 1) {
$return['rows'][$insertTablesFirst]['#'] = $insertTables[$matches[2]];
if(!isset($return['sum'][$type])) $return['sum'][$type] = 0;
$return['sum'][$type] += $row['#'];
// Add a ... to the end of this query to indicate that there's been other queries
if ($return['rows'][$insertTablesFirst]['argument'][strlen($return['rows'][$insertTablesFirst]['argument'])-1] != '.')
$return['rows'][$insertTablesFirst]['argument'] .= '<br/>...';
switch($type) {
case 'insert':
// Group inserts if selected
if($removeVars && preg_match('/^INSERT INTO (`|\'|"|)([^\s\\1]+)\\1/i',$row['argument'],$matches)) {
$insertTables[$matches[2]]++;
if ($insertTables[$matches[2]] > 1) {
$return['rows'][$insertTablesFirst]['#'] = $insertTables[$matches[2]];
// Group this value, thus do not add to the result list
continue;
} else {
$insertTablesFirst = $i;
$insertTables[$matches[2]] += $row['#'] - 1;
// Add a ... to the end of this query to indicate that there's been other queries
if($return['rows'][$insertTablesFirst]['argument'][strlen($return['rows'][$insertTablesFirst]['argument'])-1] != '.')
$return['rows'][$insertTablesFirst]['argument'] .= '<br/>...';
// Group this value, thus do not add to the result list
continue 2;
} else {
$insertTablesFirst = $i;
$insertTables[$matches[2]] += $row['#'] - 1;
}
}
}
// No break here
// Cut off big selects, but append byte count therefor
if (strlen($row['argument']) > 180) {
$row['argument'] = substr($row['argument'],0,160) . '... [' .
PMA_formatByteDown(strlen($row['argument']), 2).']';
}
case 'update':
// Cut off big inserts and updates, but append byte count therefor
if(strlen($row['argument']) > 180)
$row['argument'] = substr($row['argument'],0,160) . '... [' .
PMA_formatByteDown(strlen($row['argument']), 2).']';
break;
default: break;
}
$return['rows'][] = $row;
$i++;
}
@ -259,6 +241,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));
}
}
@ -287,6 +312,8 @@ $GLOBALS['js_include'][] = 'highcharts/exporting.js';
$GLOBALS['js_include'][] = 'canvg/flashcanvas.js';
$GLOBALS['js_include'][] = 'canvg/canvg.js';
$GLOBALS['js_include'][] = 'canvg/rgbcolor.js';
$GLOBALS['js_include'][] = 'codemirror/lib/codemirror.js';
$GLOBALS['js_include'][] = 'codemirror/mode/mysql/mysql.js';
/**
* flush status variables if requested
@ -1429,8 +1456,27 @@ function printMonitor() {
<div id="loadingLogsDialog" title="<?php echo __('Loading logs'); ?>" style="display:none;">
</div>
<div id="logAnalyseDialog" title="<?php echo __('Log statistics'); ?>">
<div id="logAnalyseDialog" title="<?php echo __('Log statistics'); ?>" style="display:none;">
<p> <?php echo __('Selected time range:'); ?>
<input type="text" name="dateStart" class="datetimefield" value="" /> -
<input type="text" name="dateEnd" class="datetimefield" value="" /></p>
<input type="checkbox" id="limitTypes" value="1" checked="checked" />
<label for="limitTypes">
<?php echo __('Only retrieve SELECT,INSERT,UPDATE and DELETE Statements'); ?>
</label>
<br/>
<input type="checkbox" id="removeVariables" value="1" checked="checked" />
<label for="removeVariables">
<?php echo __('Remove variable data in INSERT statements for better grouping'); ?>
</label>
<?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">

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

@ -87,6 +87,8 @@ button {
.ic_b_browse { background-position: 0 -18px; }
.ic_b_sbrowse { background-position: 0 -660px; width: 10px; height: 10px; }
.ic_b_view { background-position: 0 -1044px; }
.ic_b_minus { background-position: 0 -440px; width: 9px; height: 9px; }
.ic_b_plus { background-position: 0 -523px; width: 9px; height: 9px; }
/******************************************************************************/
/* classes */

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

View File

@ -92,6 +92,10 @@ button {
.ic_s_loggoff { background-position: -1698px 0; }
.ic_b_browse, .ic_b_sbrowse { background-position: -34px 0; }
.ic_b_view { background-position: -1077px 0; }
.ic_b_plus { background-position: -573px 0; }
.ic_b_minus { background-position: -471px 0; }
.ic_b_views, .ic_s_views { background-position: -1094px 0; }
/******************************************************************************/
/* classes */

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;
@ -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 */

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 B