mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-25 18:20:20 -06:00
Show more granular timing info in the query tool history panel. Fixes #3244
This commit is contained in:
parent
61eb94a23c
commit
94e1e46201
@ -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",
|
||||
|
33
web/pgadmin/static/js/sqleditor/calculate_query_run_time.js
Normal file
33
web/pgadmin/static/js/sqleditor/calculate_query_run_time.js
Normal 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();
|
||||
}
|
52
web/pgadmin/static/js/sqleditor/call_render_after_poll.js
Normal file
52
web/pgadmin/static/js/sqleditor/call_render_after_poll.js
Normal 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');
|
||||
}
|
@ -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
|
||||
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
@ -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
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -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"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user