Show more granular timing info in the query tool history panel. Fixes #3244

This commit is contained in:
Joao Pedro De Almeida Pereira 2018-04-03 14:11:11 +01:00 committed by Dave Page
parent 61eb94a23c
commit 94e1e46201
7 changed files with 382 additions and 53 deletions

View File

@ -84,6 +84,7 @@
"slickgrid": "git+https://github.com/6pac/SlickGrid.git#2.3.7",
"snapsvg": "^0.5.1",
"spectrum-colorpicker": "^1.8.0",
"sprintf-js": "^1.1.1",
"underscore": "^1.8.3",
"underscore.string": "^3.3.4",
"watchify": "~3.9.0",

View File

@ -0,0 +1,33 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import moment from 'moment';
export function calculateQueryRunTime(startTime, endTime) {
const tempEndDate = moment(endTime);
let miliseconds = tempEndDate.diff(startTime);
let seconds = tempEndDate.diff(startTime, 'seconds');
const minutes = tempEndDate.diff(startTime, 'minutes');
let result = '';
if (minutes > 0) {
result += minutes + ' min ';
seconds -= minutes * 60;
}
if (seconds > 0) {
result += seconds + ' secs ';
miliseconds -= seconds * 1000;
}
if(minutes <= 0) {
result += miliseconds + ' msec';
}
return result.trim();
}

View File

@ -0,0 +1,52 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import {calculateQueryRunTime} from './calculate_query_run_time';
import gettext from '../gettext';
import {sprintf} from 'sprintf-js';
function hasResultsToDisplay(res) {
return res.colinfo != null;
}
function isQueryTool(sqlEditor) {
return sqlEditor.is_query_tool;
}
function isNotificationEnabled(sqlEditor) {
return sqlEditor.info_notifier_timeout >= 0;
}
export function callRenderAfterPoll(sqlEditor, alertify, res) {
sqlEditor.query_end_time = new Date();
sqlEditor.rows_affected = res.rows_affected;
sqlEditor.has_more_rows = res.has_more_rows;
if (hasResultsToDisplay(res)) {
sqlEditor._render(res);
} else {
sqlEditor.total_time = calculateQueryRunTime(
sqlEditor.query_start_time,
sqlEditor.query_end_time);
const msg = sprintf(
gettext('Query returned successfully in %s.'), sqlEditor.total_time);
res.result += '\n\n' + msg;
sqlEditor.update_msg_history(true, res.result, false);
if (isNotificationEnabled(sqlEditor)) {
alertify.success(msg, sqlEditor.info_notifier_timeout);
}
}
if (isQueryTool(sqlEditor)) {
sqlEditor.disable_tool_buttons(false);
}
sqlEditor.setIsQueryRunning(false);
sqlEditor.trigger('pgadmin-sqleditor:loading-icon:hide');
}

View File

@ -20,6 +20,8 @@ define('tools.querytool', [
'sources/keyboard_shortcuts',
'sources/sqleditor/query_tool_actions',
'pgadmin.datagrid',
'sources/sqleditor/calculate_query_run_time',
'sources/sqleditor/call_render_after_poll',
'sources/../bundle/slickgrid',
'pgadmin.file_manager',
'backgrid.sizeable.columns',
@ -32,7 +34,8 @@ define('tools.querytool', [
pgExplain, GridSelector, ActiveCellCapture, clipboard, copyData, RangeSelectionHelper, handleQueryOutputKeyboardEvent,
XCellSelectionModel, setStagedRows, SqlEditorUtils, ExecuteQuery, transaction,
HistoryBundle, queryHistory, React, ReactDOM,
keyboardShortcuts, queryToolActions, Datagrid) {
keyboardShortcuts, queryToolActions, Datagrid,
calculateQueryRunTime, callRenderAfterPoll) {
/* Return back, this has been called more than once */
if (pgAdmin.SqlEditor)
return pgAdmin.SqlEditor;
@ -2224,37 +2227,8 @@ define('tools.querytool', [
// This is a wrapper to call_render function
// We need this because we have separated columns route & result route
// We need to combine both result here in wrapper before rendering grid
call_render_after_poll: function(res) {
var self = this;
self.query_end_time = new Date();
self.rows_affected = res.rows_affected;
self.has_more_rows = res.has_more_rows;
/* If no column information is available it means query
runs successfully with no result to display. In this
case no need to call render function.
*/
if (res.colinfo != null)
self._render(res);
else {
// Show message in message and history tab in case of query tool
self.total_time = self.get_query_run_time(self.query_start_time, self.query_end_time);
var msg = S(gettext('Query returned successfully in %s.')).sprintf(self.total_time).value();
res.result += '\n\n' + msg;
self.update_msg_history(true, res.result, false);
// Display the notifier if the timeout is set to >= 0
if (self.info_notifier_timeout >= 0) {
alertify.success(msg, self.info_notifier_timeout);
}
}
// Enable/Disable query tool button only if is_query_tool is true.
if (self.is_query_tool) {
self.disable_tool_buttons(false);
$('#btn-cancel-query').prop('disabled', true);
}
is_query_running = false;
self.trigger('pgadmin-sqleditor:loading-icon:hide');
call_render_after_poll: function(queryResult) {
callRenderAfterPoll.callRenderAfterPoll(this,alertify,queryResult);
},
@ -2329,7 +2303,10 @@ define('tools.querytool', [
);
// Show message in message and history tab in case of query tool
self.total_time = self.get_query_run_time(self.query_start_time, self.query_end_time);
self.total_time = calculateQueryRunTime.calculateQueryRunTime(
self.query_start_time,
self.query_end_time
);
var msg1 = S(gettext('Successfully run. Total query runtime: %s.')).sprintf(self.total_time).value();
var msg2 = S(gettext('%s rows affected.')).sprintf(self.rows_affected).value();
@ -2570,25 +2547,6 @@ define('tools.querytool', [
}
},
// This function will return the total query execution Time.
get_query_run_time: function(start_time, end_time) {
// Calculate the difference in milliseconds
var difference_ms, miliseconds;
difference_ms = miliseconds = end_time.getTime() - start_time.getTime();
//take out milliseconds
difference_ms = difference_ms / 1000;
var seconds = Math.floor(difference_ms % 60);
difference_ms = difference_ms / 60;
var minutes = Math.floor(difference_ms % 60);
if (minutes > 0)
return minutes + ' min';
else if (seconds > 0) {
return seconds + ' secs';
} else
return miliseconds + ' msec';
},
/* This function is used to check whether cell
* is editable or not depending on primary keys
* and staged_rows flag

View File

@ -0,0 +1,82 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import moment from 'moment';
import {calculateQueryRunTime} from '../../../pgadmin/static/js/sqleditor/calculate_query_run_time';
describe('#calculateQueryRunTime', () => {
describe('time difference is smaller then 1 second', () => {
it('displays milliseconds', () => {
let startDate = moment({
years:2018,
months:4,
date:2,
hours:10,
minutes:30,
seconds:20,
milliseconds:123}).toDate();
let endDate = moment({
years:2018,
months:4,
date:2,
hours:10,
minutes:30,
seconds:21,
milliseconds:70}).toDate();
expect(calculateQueryRunTime(startDate, endDate))
.toEqual('947 msec');
});
});
describe('time difference is smaller then 1 minute', () => {
it('displays milliseconds', () => {
let startDate = moment({
years:2018,
months:4,
date:2,
hours:10,
minutes:30,
seconds:20,
milliseconds:123}).toDate();
let endDate = moment({
years:2018,
months:4,
date:2,
hours:10,
minutes:31,
seconds:15,
milliseconds:70}).toDate();
expect(calculateQueryRunTime(startDate, endDate))
.toEqual('54 secs 947 msec');
});
});
describe('time difference is bigger then 1 minute', () => {
it('displays milliseconds', () => {
let startDate = moment({
years:2018,
months:4,
date:2,
hours:10,
minutes:30,
seconds:20,
milliseconds:123}).toDate();
let endDate = moment({
years:2018,
months:4,
date:2,
hours:10,
minutes:40,
seconds:15,
milliseconds:70}).toDate();
expect(calculateQueryRunTime(startDate, endDate))
.toEqual('9 min 54 secs');
});
});
});

View File

@ -0,0 +1,203 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import {callRenderAfterPoll} from '../../../pgadmin/static/js/sqleditor/call_render_after_poll';
import moment from 'moment';
describe('#callRenderAfterPoll', () => {
let sqlEditorSpy, queryResult, alertify;
beforeEach(() => {
let today = moment('2018-01-01 10:12:31').toDate();
jasmine.clock().install();
jasmine.clock().mockDate(today);
sqlEditorSpy = {
_render: jasmine.createSpy('SQLEditor._render'),
setIsQueryRunning: jasmine.createSpy('SQLEditor.setIsQueryRunning'),
trigger: jasmine.createSpy('SQLEditor.trigger'),
update_msg_history: jasmine.createSpy('SQLEditor.update_msg_history'),
disable_tool_buttons: jasmine.createSpy('SQLEditor.disable_tool_buttons'),
query_start_time: new Date(),
};
alertify = jasmine.createSpyObj('alertify', ['success']);
});
afterEach(function () {
jasmine.clock().uninstall();
});
describe('it is not a query tool', () => {
beforeEach(() => {
sqlEditorSpy.is_query_tool = false;
});
describe('query was successful but had no result to display', () => {
beforeEach(() => {
queryResult = {
rows_affected: 10,
has_more_rows: false,
colinfo: {},
};
});
it('renders the the editor', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy._render).toHaveBeenCalledWith(queryResult);
});
it('inform sqleditor that the query stopped running', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.setIsQueryRunning).toHaveBeenCalledWith(false);
});
it('hides the loading icon', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.trigger).toHaveBeenCalledWith('pgadmin-sqleditor:loading-icon:hide');
});
});
describe('query was successful and have results', () => {
beforeEach(() => {
queryResult = {
rows_affected: 10,
has_more_rows: false,
colinfo: undefined,
result: 'Some result',
};
});
it('saves execution information in the history', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.update_msg_history).toHaveBeenCalledWith(
true,
'Some result\n\nQuery returned successfully in 0 msec.',
false
);
});
it('inform sqleditor that the query stopped running', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.setIsQueryRunning).toHaveBeenCalledWith(false);
});
it('hides the loading icon', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.trigger).toHaveBeenCalledWith('pgadmin-sqleditor:loading-icon:hide');
});
describe('notifications are enabled', () => {
it('display notification', () => {
sqlEditorSpy.info_notifier_timeout = 10;
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(alertify.success).toHaveBeenCalledWith(
'Query returned successfully in 0 msec.',
10
);
});
});
});
});
describe('it is a query tool', () => {
beforeEach(() => {
sqlEditorSpy.is_query_tool = true;
});
describe('query was successful but had no result to display', () => {
beforeEach(() => {
queryResult = {
rows_affected: 10,
has_more_rows: false,
colinfo: {},
};
});
it('renders the the editor', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy._render).toHaveBeenCalledWith(queryResult);
});
it('inform sqleditor that the query stopped running', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.setIsQueryRunning).toHaveBeenCalledWith(false);
});
it('hides the loading icon', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.trigger).toHaveBeenCalledWith('pgadmin-sqleditor:loading-icon:hide');
});
it('enables sqleditor tools buttons', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.disable_tool_buttons).toHaveBeenCalledWith(false);
});
});
describe('query was successful and have results', () => {
beforeEach(() => {
queryResult = {
rows_affected: 10,
has_more_rows: false,
colinfo: undefined,
result: 'Some result',
};
});
it('saves execution information in the history', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.update_msg_history).toHaveBeenCalledWith(
true,
'Some result\n\nQuery returned successfully in 0 msec.',
false
);
});
it('inform sqleditor that the query stopped running', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.setIsQueryRunning).toHaveBeenCalledWith(false);
});
it('hides the loading icon', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.trigger).toHaveBeenCalledWith('pgadmin-sqleditor:loading-icon:hide');
});
it('enables sqleditor tools buttons', () => {
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(sqlEditorSpy.disable_tool_buttons).toHaveBeenCalledWith(false);
});
describe('notifications are enabled', () => {
it('display notification', () => {
sqlEditorSpy.info_notifier_timeout = 10;
callRenderAfterPoll(sqlEditorSpy, alertify, queryResult);
expect(alertify.success).toHaveBeenCalledWith(
'Query returned successfully in 0 msec.',
10
);
});
});
});
});
});

View File

@ -7422,7 +7422,7 @@ sprintf-js@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.0.tgz#cffcaf702daf65ea39bb4e0fa2b299cec1a1be46"
sprintf-js@^1.0.3:
sprintf-js@^1.0.3, sprintf-js@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c"