[pgAdmin][RM4553] Query tool UX improvement
Aditya Toshniwal <[email protected]>
| Newsgroups | gmane.comp.db.postgresql.pgadmin.devel |
|---|---|
| Message-ID | <CAM9w-_kFqLrrm74sEMB9v1F83DS5YHe4oymVzO1jJ3xTa8-shA@mail.gmail.com> |
Hi Hackers, Attached is the patch to improve user experience when opening query tool. Previously, when the query tool button was clicked, the request went to backend, the connection was created and sent back to the UI. Until then, there was no activity on the UI. For slow servers it looked like pgAdmin is slow/struck. With this change, the query tool will be opened instantaneously. Other things like opening the connection is done in parallel with query tool render, thus saving time. The query tool connection status icon will show a spinner and text will have "Obtaining connection..." until the connection is established. Test cases added/changed accordingly. Kindly review. -- Thanks and Regards, Aditya Toshniwal Software Engineer | EnterpriseDB India | Pune "Don't Complain about Heat, Plant a TREE"
RM4553.patch
(application/octet-stream, 64.8 KB)
diff --git a/web/pgadmin/browser/utils.py b/web/pgadmin/browser/utils.py
index 4c049bed..2a17b3a2 100644
--- a/web/pgadmin/browser/utils.py
+++ b/web/pgadmin/browser/utils.py
@@ -47,6 +47,30 @@ def underscore_escape(text):
return text
+def underscore_unescape(text):
+ """
+ This function mimics the behaviour of underscore js unescape function
+ The html unescape by jinja is not compatible for underscore escape
+ function
+ :param text: input html text
+ :return: unescaped text
+ """
+ html_map = {
+ "&": '&',
+ "<": '<',
+ ">": '>',
+ """: '"',
+ "`": '`',
+ "'": "'"
+ }
+
+ # always replace & first
+ for c, r in html_map.items():
+ text = text.replace(c, r)
+
+ return text
+
+
def is_version_in_range(sversion, min_ver, max_ver):
assert (max_ver is None or isinstance(max_ver, int))
assert (min_ver is None or isinstance(min_ver, int))
diff --git a/web/pgadmin/static/js/sqleditor_utils.js b/web/pgadmin/static/js/sqleditor_utils.js
index 9d14ac46..bd4356c0 100644
--- a/web/pgadmin/static/js/sqleditor_utils.js
+++ b/web/pgadmin/static/js/sqleditor_utils.js
@@ -73,6 +73,9 @@ define(['jquery', 'sources/gettext', 'sources/url_for'],
return;
}
+ if($status_el.hasClass('obtaining-conn')){
+ return;
+ }
let sqleditor_obj = target;
// Start polling..
@@ -195,22 +198,6 @@ define(['jquery', 'sources/gettext', 'sources/url_for'],
}
return '1em';
},
-
- removeSlashInTheString: (value) => {
- let locationList = [];
- let idx = 0;
- while (value && value.indexOf('/') !== -1) {
- locationList.push(value.indexOf('/') + idx);
- value = value.replace('/', '');
- // No of slashes already removed, so we need to increment the
- // index accordingly when adding into location list
- idx++;
- }
- return {
- 'slashLocations': locationList.join(','),
- 'title': encodeURIComponent(value),
- };
- },
};
return sqlEditorUtils;
});
diff --git a/web/pgadmin/static/js/utils.js b/web/pgadmin/static/js/utils.js
index fe9fd8ed..1f15858d 100644
--- a/web/pgadmin/static/js/utils.js
+++ b/web/pgadmin/static/js/utils.js
@@ -199,3 +199,9 @@ export function fully_qualify(pgBrowser, data, item) {
return quote_ident(data._label);
}
}
+
+export function getRandomInt(min, max) {
+ min = Math.ceil(min);
+ max = Math.floor(max);
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+}
diff --git a/web/pgadmin/tools/datagrid/__init__.py b/web/pgadmin/tools/datagrid/__init__.py
index e8779351..f4597fc4 100644
--- a/web/pgadmin/tools/datagrid/__init__.py
+++ b/web/pgadmin/tools/datagrid/__init__.py
@@ -30,7 +30,7 @@ from pgadmin.utils.driver import get_driver
from pgadmin.utils.exception import ConnectionLost, SSHTunnelConnectionLost
from pgadmin.utils.preferences import Preferences
from pgadmin.settings import get_setting
-from pgadmin.browser.utils import underscore_escape
+from pgadmin.browser.utils import underscore_unescape
query_tool_close_session_lock = Lock()
@@ -114,13 +114,13 @@ def show_filter():
@blueprint.route(
- '/initialize/datagrid/<int:cmd_type>/<obj_type>/<int:sgid>/<int:sid>/'
- '<int:did>/<int:obj_id>',
+ '/initialize/datagrid/<int:trans_id>/<int:cmd_type>/<obj_type>/'
+ '<int:sgid>/<int:sid>/<int:did>/<int:obj_id>',
methods=["PUT", "POST"],
endpoint="initialize_datagrid"
)
@login_required
-def initialize_datagrid(cmd_type, obj_type, sgid, sid, did, obj_id):
+def initialize_datagrid(trans_id, cmd_type, obj_type, sgid, sid, did, obj_id):
"""
This method is responsible for creating an asynchronous connection.
After creating the connection it will instantiate and initialize
@@ -183,9 +183,6 @@ def initialize_datagrid(cmd_type, obj_type, sgid, sid, did, obj_id):
app.logger.error(e)
return internal_server_error(errormsg=str(e))
- # Create a unique id for the transaction
- trans_id = str(random.randint(1, 9999999))
-
if 'gridData' not in session:
sql_grid_data = dict()
else:
@@ -193,7 +190,7 @@ def initialize_datagrid(cmd_type, obj_type, sgid, sid, did, obj_id):
# Use pickle to store the command object which will be used later by the
# sql grid module.
- sql_grid_data[trans_id] = {
+ sql_grid_data[str(trans_id)] = {
# -1 specify the highest protocol version available
'command_obj': pickle.dumps(command_obj, -1)
}
@@ -203,51 +200,34 @@ def initialize_datagrid(cmd_type, obj_type, sgid, sid, did, obj_id):
return make_json_response(
data={
- 'gridTransId': trans_id
+ 'conn_id': conn_id
}
)
@blueprint.route(
- '/panel/<int:trans_id>/<is_query_tool>/<path:editor_title>',
- methods=["GET"],
+ '/panel/<int:trans_id>',
+ methods=["POST"],
endpoint='panel'
)
-def panel(trans_id, is_query_tool, editor_title):
+def panel(trans_id):
"""
This method calls index.html to render the data grid.
Args:
trans_id: unique transaction id
- is_query_tool: True if panel calls when query tool menu is clicked.
- editor_title: Title of the editor
"""
- # Let's fetch Script type URL from request
- if request.args and request.args['query_url'] != '':
- sURL = request.args['query_url']
- else:
- sURL = None
- # Fetch server type from request
- if request.args and request.args['server_type'] != '':
- server_type = request.args['server_type']
- else:
- server_type = None
+ url_params = None
+ if request.args:
+ url_params = {k: v for k, v in request.args.items()}
- if request.args and 'server_ver' in request.args:
- server_ver = request.args['server_ver']
- else:
- server_ver = 0
-
- # If title has slash(es) in it then replace it
- if request.args and request.args['fslashes'] != '':
- try:
- fslashesList = request.args['fslashes'].split(',')
- for idx in fslashesList:
- idx = int(idx)
- editor_title = editor_title[:idx] + '/' + editor_title[idx:]
- except IndexError as e:
- app.logger.exception(e)
+ if request.form:
+ url_params['title'] = request.form['title']
+ if 'sql_filter' in request.form:
+ url_params['sql_filter'] = request.form['sql_filter']
+ if 'query_url' in request.form:
+ url_params['query_url'] = request.form['query_url']
# We need client OS information to render correct Keyboard shortcuts
user_agent = UserAgent(request.headers.get('User-Agent'))
@@ -277,64 +257,43 @@ def panel(trans_id, is_query_tool, editor_title):
# Fetch the server details
bgcolor = None
fgcolor = None
- if 'gridData' in session and str(trans_id) in session['gridData']:
- # Fetch the object for the specified transaction id.
- # Use pickle.loads function to get the command object
- session_obj = session['gridData'][str(trans_id)]
- trans_obj = pickle.loads(session_obj['command_obj'])
- s = Server.query.filter_by(id=trans_obj.sid).first()
- if s and s.bgcolor:
- # If background is set to white means we do not have to change
- # the title background else change it as per user specified
- # background
- if s.bgcolor != '#ffffff':
- bgcolor = s.bgcolor
- fgcolor = s.fgcolor or 'black'
- layout = get_setting('SQLEditor/Layout')
+ s = Server.query.filter_by(id=url_params['sid']).first()
+ if s and s.bgcolor:
+ # If background is set to white means we do not have to change
+ # the title background else change it as per user specified
+ # background
+ if s.bgcolor != '#ffffff':
+ bgcolor = s.bgcolor
+ fgcolor = s.fgcolor or 'black'
- url_params = dict()
- if is_query_tool == 'true':
- url_params['sgid'] = trans_obj.sgid
- url_params['sid'] = trans_obj.sid
- url_params['did'] = trans_obj.did
- else:
- url_params['cmd_type'] = trans_obj.cmd_type
- url_params['obj_type'] = trans_obj.object_type
- url_params['sgid'] = trans_obj.sgid
- url_params['sid'] = trans_obj.sid
- url_params['did'] = trans_obj.did
- url_params['obj_id'] = trans_obj.obj_id
+ layout = get_setting('SQLEditor/Layout')
return render_template(
"datagrid/index.html",
_=gettext,
uniqueId=trans_id,
- is_query_tool=is_query_tool,
- editor_title=underscore_escape(editor_title),
- script_type_url=sURL,
is_desktop_mode=app.PGADMIN_RUNTIME,
is_linux=is_linux_platform,
- server_type=server_type,
- server_ver=server_ver,
+ title=underscore_unescape(url_params['title']),
+ url_params=json.dumps(url_params),
client_platform=user_agent.platform,
bgcolor=bgcolor,
fgcolor=fgcolor,
- url_params=json.dumps(url_params),
layout=layout,
)
@blueprint.route(
- '/initialize/query_tool/<int:sgid>/<int:sid>/<int:did>',
+ '/initialize/query_tool/<int:trans_id>/<int:sgid>/<int:sid>/<int:did>',
methods=["POST"], endpoint='initialize_query_tool_with_did'
)
@blueprint.route(
- '/initialize/query_tool/<int:sgid>/<int:sid>',
+ '/initialize/query_tool/<int:trans_id>/<int:sgid>/<int:sid>',
methods=["POST"], endpoint='initialize_query_tool'
)
@login_required
-def initialize_query_tool(sgid, sid, did=None):
+def initialize_query_tool(trans_id, sgid, sid, did=None):
"""
This method is responsible for instantiating and initializing
the query tool object. It will also create a unique
@@ -346,16 +305,16 @@ def initialize_query_tool(sgid, sid, did=None):
did: Database Id
"""
connect = True
- reqArgs = None
# Read the data if present. Skipping read may cause connection
# reset error if data is sent from the client
if request.data:
- reqArgs = request.data
+ _ = request.data
reqArgs = request.args
if ('recreate' in reqArgs and
reqArgs['recreate'] == '1'):
connect = False
+
# Create asynchronous connection using random connection id.
conn_id = str(random.randint(1, 9999999))
@@ -389,9 +348,6 @@ def initialize_query_tool(sgid, sid, did=None):
app.logger.error(e)
return internal_server_error(errormsg=str(e))
- # Create a unique id for the transaction
- trans_id = str(random.randint(1, 9999999))
-
if 'gridData' not in session:
sql_grid_data = dict()
else:
@@ -404,7 +360,7 @@ def initialize_query_tool(sgid, sid, did=None):
# Use pickle to store the command object which will be used
# later by the sql grid module.
- sql_grid_data[trans_id] = {
+ sql_grid_data[str(trans_id)] = {
# -1 specify the highest protocol version available
'command_obj': pickle.dumps(command_obj, -1)
}
@@ -414,7 +370,7 @@ def initialize_query_tool(sgid, sid, did=None):
return make_json_response(
data={
- 'gridTransId': trans_id,
+ 'connId': str(conn_id),
'serverVersion': manager.version,
}
)
diff --git a/web/pgadmin/tools/datagrid/static/js/datagrid.js b/web/pgadmin/tools/datagrid/static/js/datagrid.js
index a405b7de..f12ab7a7 100644
--- a/web/pgadmin/tools/datagrid/static/js/datagrid.js
+++ b/web/pgadmin/tools/datagrid/static/js/datagrid.js
@@ -13,10 +13,10 @@ define('pgadmin.datagrid', [
'sources/sqleditor_utils', 'backbone',
'tools/datagrid/static/js/show_data',
'tools/datagrid/static/js/show_query_tool', 'pgadmin.browser.toolbar',
- 'tools/datagrid/static/js/datagrid_panel_title', 'wcdocker',
+ 'tools/datagrid/static/js/datagrid_panel_title', 'sources/utils', 'wcdocker',
], function(
gettext, url_for, $, _, alertify, pgAdmin, codemirror, sqlEditorUtils,
- Backbone, showData, showQueryTool, toolBar, panelTitleFunc
+ Backbone, showData, showQueryTool, toolBar, panelTitleFunc, commonUtils
) {
// Some scripts do export their object in the window only.
// Generally the one, which do no have AMD support.
@@ -52,7 +52,6 @@ define('pgadmin.datagrid', [
self.preferences = pgBrowser.get_preferences_for_module('sqleditor');
});
-
// Define list of nodes on which view data option appears
var supported_nodes = [
'table', 'view', 'mview',
@@ -195,97 +194,48 @@ define('pgadmin.datagrid', [
// This is a callback function to show data when user click on menu item.
show_data_grid: function(data, i) {
- showData.showDataGrid(this, pgBrowser, alertify, data, i);
+ const transId = commonUtils.getRandomInt(1, 9999999);
+ showData.showDataGrid(this, pgBrowser, alertify, data, i, transId);
},
// This is a callback function to show filtered data when user click on menu item.
show_filtered_row: function(data, i) {
- showData.showDataGrid(this, pgBrowser, alertify, data, i, true, this.preferences);
+ const transId = commonUtils.getRandomInt(1, 9999999);
+ showData.showDataGrid(this, pgBrowser, alertify, data, i, transId, true, this.preferences);
},
// This is a callback function to show query tool when user click on menu item.
show_query_tool: function(url, aciTreeIdentifier) {
- showQueryTool.showQueryTool(this, pgBrowser, alertify, url, aciTreeIdentifier);
+ const transId = commonUtils.getRandomInt(1, 9999999);
+ showQueryTool.showQueryTool(this, pgBrowser, alertify, url, aciTreeIdentifier, transId);
},
- create_transaction: function(baseUrl, target, is_query_tool, server_type, sURL, panel_title, sql_filter, recreate) {
+ launch_grid: function(trans_id, panel_url, is_query_tool, panel_title, sURL=null, sql_filter=null) {
var self = this;
- target = target || self;
- if (recreate) {
- baseUrl += '?recreate=1';
- }
- /* Send the data only if required. Sending non required data may
- * cause connection reset error if data is not read by flask server
- */
- let reqData = null;
- if(sql_filter != '') {
- reqData = JSON.stringify(sql_filter);
- }
+ let queryToolForm = `
+ <form id="queryToolForm" action="${panel_url}" method="post">
+ <input id="title" name="title" hidden />`;
- $.ajax({
- url: baseUrl,
- method: 'POST',
- dataType: 'json',
- data: reqData,
- contentType: 'application/json',
- })
- .done(function(res) {
- res.data.is_query_tool = is_query_tool;
- res.data.server_type = server_type;
- res.data.sURL = sURL;
- res.data.panel_title = panel_title;
- target.trigger('pgadmin-datagrid:transaction:created', res.data);
- })
- .fail(function(xhr) {
- if (target !== self) {
- if(xhr.status == 503 && xhr.responseJSON.info != undefined &&
- xhr.responseJSON.info == 'CONNECTION_LOST') {
- setTimeout(function() {
- target.handle_connection_lost(true, xhr);
- });
- return;
- }
- }
-
- try {
- var err = JSON.parse(xhr.responseText);
- alertify.alert(gettext('Query Tool initialization error'),
- err.errormsg
- );
- } catch (e) {
- alertify.alert(gettext('Query Tool initialization error'),
- e.statusText
- );
- }
- });
- },
- launch_grid: function(trans_obj) {
- var self = this,
- panel_title = trans_obj.panel_title,
- grid_title = trans_obj.panel_title;
+ if(sURL){
+ queryToolForm +=`<input name="query_url" value="${sURL}" hidden />`;
+ }
+ if(sql_filter) {
+ queryToolForm +=`<textarea name="sql_filter" hidden>${sql_filter}</textarea>`;
+ }
- // Open the panel if frame is initialized
- let titileForURLObj = sqlEditorUtils.removeSlashInTheString(grid_title);
- var url_params = {
- 'trans_id': trans_obj.gridTransId,
- 'is_query_tool': trans_obj.is_query_tool,
- 'editor_title': titileForURLObj.title,
- },
- baseUrl = url_for('datagrid.panel', url_params) +
- '?' + 'query_url=' + encodeURI(trans_obj.sURL) +
- '&server_type=' + encodeURIComponent(trans_obj.server_type) +
- '&server_ver=' + trans_obj.serverVersion+
- '&fslashes=' + titileForURLObj.slashLocations;
+ queryToolForm +=`
+ </form>
+ <script>
+ document.getElementById("title").value = "${panel_title}";
+ document.getElementById("queryToolForm").submit();
+ </script>
+ `;
if (self.preferences.new_browser_tab) {
- var newWin = window.open(baseUrl, '_blank');
-
- // add a load listener to the window so that the title gets changed on page load
- newWin.addEventListener('load', function() {
- newWin.document.title = panel_title;
- });
-
+ var newWin = window.open('', '_blank');
+ newWin.document.write(queryToolForm);
+ newWin.document.title = panel_title;
} else {
/* On successfully initialization find the dashboard panel,
* create new panel and add it to the dashboard panel.
@@ -294,13 +244,13 @@ define('pgadmin.datagrid', [
var queryToolPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, propertiesPanel[0]);
// Set panel title and icon
- panelTitleFunc.setQueryToolDockerTitle(queryToolPanel, trans_obj.is_query_tool, panel_title);
+ panelTitleFunc.setQueryToolDockerTitle(queryToolPanel, is_query_tool, panel_title);
queryToolPanel.focus();
// Listen on the panel closed event.
queryToolPanel.on(wcDocker.EVENT.CLOSED, function() {
$.ajax({
- url: url_for('datagrid.close', {'trans_id': trans_obj.gridTransId}),
+ url: url_for('datagrid.close', {'trans_id': trans_id}),
method: 'DELETE',
});
});
@@ -325,7 +275,7 @@ define('pgadmin.datagrid', [
frame.onLoaded(()=>{
$spinner_el.remove();
});
- frame.openURL(baseUrl);
+ frame.openHTML(queryToolForm);
}
}
}, 100);
diff --git a/web/pgadmin/tools/datagrid/static/js/datagrid_panel_title.js b/web/pgadmin/tools/datagrid/static/js/datagrid_panel_title.js
index ec3a2306..8c9b999c 100644
--- a/web/pgadmin/tools/datagrid/static/js/datagrid_panel_title.js
+++ b/web/pgadmin/tools/datagrid/static/js/datagrid_panel_title.js
@@ -52,6 +52,6 @@ export function setQueryToolDockerTitle(panel, is_query_tool, panel_title, is_fi
panel_icon = 'fa fa-bolt';
}
- panel.title('<span title="'+_.escape(panel_tooltip)+'">'+_.escape(panel_title)+'</span>');
+ panel.title('<span title="'+ panel_tooltip +'">'+ panel_title +'</span>');
panel.icon(panel_icon);
}
diff --git a/web/pgadmin/tools/datagrid/static/js/show_data.js b/web/pgadmin/tools/datagrid/static/js/show_data.js
index 547daf77..c2fbc7be 100644
--- a/web/pgadmin/tools/datagrid/static/js/show_data.js
+++ b/web/pgadmin/tools/datagrid/static/js/show_data.js
@@ -20,6 +20,7 @@ export function showDataGrid(
alertify,
connectionData,
aciTreeIdentifier,
+ transId,
filter=false,
preferences=null
) {
@@ -42,43 +43,25 @@ export function showDataGrid(
return;
}
- const baseUrl = generateUrl(connectionData, node.getData(), parentData);
- const grid_title = generateDatagridTitle(pgBrowser, aciTreeIdentifier);
-
+ const gridUrl = generateUrl(transId, connectionData, node.getData(), parentData);
+ const queryToolTitle = generateDatagridTitle(pgBrowser, aciTreeIdentifier);
if(filter) {
initFilterDialog(alertify, pgBrowser, preferences);
const validateUrl = generateFilterValidateUrl(node.getData(), parentData);
let okCallback = function(sql) {
- datagrid.create_transaction(
- baseUrl,
- null,
- 'false',
- parentData.server.server_type,
- '',
- grid_title,
- sql,
- false
- );
+ datagrid.launch_grid(transId, gridUrl, false, queryToolTitle, null, sql);
};
$.get(url_for('datagrid.filter'),
function(data) {
- alertify.filterDialog(`Data Filter - ${grid_title}`, data, validateUrl, preferences, okCallback)
+ alertify.filterDialog(`Data Filter - ${queryToolTitle}`, data, validateUrl, preferences, okCallback)
.resizeTo(pgBrowser.stdW.sm,pgBrowser.stdH.sm);
}
);
} else {
- datagrid.create_transaction(
- baseUrl,
- null,
- 'false',
- parentData.server.server_type,
- '',
- grid_title,
- ''
- );
+ datagrid.launch_grid(transId, gridUrl, false, queryToolTitle);
}
}
@@ -96,17 +79,21 @@ export function retrieveNameSpaceName(parentData) {
return '';
}
-function generateUrl(connectionData, nodeData, parentData) {
- const url_params = {
- 'cmd_type': connectionData.mnuid,
- 'obj_type': nodeData._type,
- 'sgid': parentData.server_group._id,
- 'sid': parentData.server._id,
- 'did': parentData.database._id,
- 'obj_id': nodeData._id,
- };
-
- return url_for('datagrid.initialize_datagrid', url_params);
+function generateUrl(trans_id, connectionData, nodeData, parentData) {
+ let url_endpoint = url_for('datagrid.panel', {
+ 'trans_id': trans_id,
+ });
+
+ url_endpoint += `?is_query_tool=${false}`
+ +`&cmd_type=${connectionData.mnuid}`
+ +`&obj_type=${nodeData._type}`
+ +`&obj_id=${nodeData._id}`
+ +`&sgid=${parentData.server_group._id}`
+ +`&sid=${parentData.server._id}`
+ +`&did=${parentData.database._id}`
+ +`&server_type=${parentData.server.server_type}`;
+
+ return url_endpoint;
}
function generateFilterValidateUrl(nodeData, parentData) {
diff --git a/web/pgadmin/tools/datagrid/static/js/show_query_tool.js b/web/pgadmin/tools/datagrid/static/js/show_query_tool.js
index 4b42c7a6..b7a8d033 100644
--- a/web/pgadmin/tools/datagrid/static/js/show_query_tool.js
+++ b/web/pgadmin/tools/datagrid/static/js/show_query_tool.js
@@ -16,19 +16,21 @@ function hasDatabaseInformation(parentData) {
return parentData.database;
}
-function generateUrl(parentData) {
- let url_endpoint = 'datagrid.initialize_query_tool';
- let url_params = {
- 'sgid': parentData.server_group._id,
- 'sid': parentData.server._id,
- };
+function generateUrl(trans_id, title, parentData) {
+ let url_endpoint = url_for('datagrid.panel', {
+ 'trans_id': trans_id,
+ });
+
+ url_endpoint += `?is_query_tool=${true}`
+ +`&sgid=${parentData.server_group._id}`
+ +`&sid=${parentData.server._id}`
+ +`&server_type=${parentData.server.server_type}`;
if (hasDatabaseInformation(parentData)) {
- url_params['did'] = parentData.database._id;
- url_endpoint = 'datagrid.initialize_query_tool_with_did';
+ url_endpoint += `&did=${parentData.database._id}`;
}
- return url_for(url_endpoint, url_params);
+ return url_endpoint;
}
function hasServerInformations(parentData) {
@@ -40,7 +42,7 @@ function generateTitle(pgBrowser, aciTreeIdentifier) {
return baseTitle;
}
-export function showQueryTool(datagrid, pgBrowser, alertify, url, aciTreeIdentifier) {
+export function showQueryTool(datagrid, pgBrowser, alertify, url, aciTreeIdentifier, transId) {
const sURL = url || '';
const queryToolTitle = generateTitle(pgBrowser, aciTreeIdentifier);
@@ -60,9 +62,7 @@ export function showQueryTool(datagrid, pgBrowser, alertify, url, aciTreeIdentif
return;
}
- const baseUrl = generateUrl(parentData);
+ const gridUrl = generateUrl(transId, queryToolTitle, parentData);
- datagrid.create_transaction(
- baseUrl, null, 'true',
- parentData.server.server_type, sURL, queryToolTitle, '', false);
+ datagrid.launch_grid(transId, gridUrl, true, queryToolTitle, sURL);
}
diff --git a/web/pgadmin/tools/datagrid/templates/datagrid/index.html b/web/pgadmin/tools/datagrid/templates/datagrid/index.html
index b1be514d..3b3e3508 100644
--- a/web/pgadmin/tools/datagrid/templates/datagrid/index.html
+++ b/web/pgadmin/tools/datagrid/templates/datagrid/index.html
@@ -1,5 +1,5 @@
{% extends "base.html" %}
-{% block title %}{{ config.APP_NAME }} - Datagrid{% endblock %}
+{% block title %}{{title}}{% endblock %}
{% block body %}
<style>
body {padding: 0px;}
@@ -228,7 +228,7 @@
</button>
<button id="btn-flash" data-test-selector="execute-refresh-button" type="button" class="btn btn-sm btn-secondary" style="width: 32px;"
title=""
- tabindex="0">
+ tabindex="0" disabled>
<i class="fa fa-bolt sql-icon-lg" aria-hidden="true"></i>
</button>
<button id="btn-query-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
@@ -256,12 +256,12 @@
<button id="btn-explain" type="button" class="btn btn-sm btn-secondary"
title=""
accesskey=""
- tabindex="0">
+ tabindex="0" disabled>
<i class="fa fa-hand-pointer-o sql-icon-lg" aria-hidden="true"></i>
</button>
<button id="btn-explain-analyze" type="button" class="btn btn-sm btn-secondary"
title=""
- accesskey="">
+ accesskey="" disabled>
<i class="fa fa-list-alt sql-icon-lg" aria-hidden="true"></i>
</button>
<button id="btn-explain-options-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
@@ -358,20 +358,20 @@
data-panel-visible="visible"
accesskey=""
tabindex="0">
- <i class="fa-custom fa-query-tool-disconnected" aria-hidden="true"
+ <i class="fa-custom fa-query-tool-disconnected obtaining-conn" aria-hidden="true"
title="">
</i>
</div>
<div class="editor-title"
- style="background-color: {% if fgcolor %}{{ bgcolor or '#FFFFFF' }}{% endif %}; color: {% if fgcolor %}{{ fgcolor }}{% endif %};"></div>
+ style="background-color: {% if fgcolor %}{{ bgcolor or '#FFFFFF' }}{% endif %}; color: {% if fgcolor %}{{ fgcolor }}{% endif %};"> </div>
</div>
<div id="editor-panel" tabindex="0">
- <div id="fetching_data" class="pg-sp-container sql-editor-busy-fetching d-none">
+ <div id="fetching_data" class="pg-sp-container sql-editor-busy-fetching">
<div class="pg-sp-content">
<div class="row">
<div class="col-12 pg-sp-icon sql-editor-busy-icon"></div>
</div>
- <div class="row"><div class="col-12 pg-sp-text sql-editor-busy-text">{{ _('Loading {0} v{1}...').format(config.APP_NAME, config.APP_VERSION) }}</div></div>
+ <div class="row"><div class="col-12 pg-sp-text sql-editor-busy-text">{{ _('Loading...') }}</div></div>
</div>
</div>
</div>
@@ -412,13 +412,13 @@
// Listen on events to show/hide loading-icon and change messages.
sqlEditorController.on('pgadmin-sqleditor:loading-icon:message', function(msg) {
- msgDiv.text(msg);
+ msgDiv.text(msg);
}).on('pgadmin-sqleditor:loading-icon:show', function(msg) {
loadingDiv.removeClass('d-none');
msgDiv.text(msg);
- }).on('pgadmin-sqleditor:loading-icon:hide', function() {
- loadingDiv.addClass('d-none');
- });
+ }).on('pgadmin-sqleditor:loading-icon:hide', function() {
+ loadingDiv.addClass('d-none');
+ });
{% if script_type_url %}
var script_type_url = '{{ script_type_url }}';
{% else %}
@@ -427,13 +427,8 @@
// Start the query tool.
sqlEditorController.start(
{{ uniqueId }},
- {{ is_query_tool }},
- "{{ editor_title }}",
- script_type_url,
- "{{ server_type }}",
{{ url_params|safe}},
'{{ layout|safe }}',
- {{ server_ver }}
);
});
{% endblock %}
diff --git a/web/pgadmin/tools/sqleditor/static/css/sqleditor.css b/web/pgadmin/tools/sqleditor/static/css/sqleditor.css
index ae5ce685..e078ea75 100644
--- a/web/pgadmin/tools/sqleditor/static/css/sqleditor.css
+++ b/web/pgadmin/tools/sqleditor/static/css/sqleditor.css
@@ -291,6 +291,10 @@ input.editor-checkbox:focus {
background-image: url('../img/disconnect.svg');
}
+.connection_status .obtaining-conn {
+ background-image: url('../img/loading.gif') !important;
+}
+
.icon-commit, .icon-rollback, .icon-save-data-changes, .icon-view-data {
display: inline-block;
align-content: center;
diff --git a/web/pgadmin/tools/sqleditor/static/img/loading.gif b/web/pgadmin/tools/sqleditor/static/img/loading.gif
new file mode 100644
index 0000000000000000000000000000000000000000..500fa0860e2eb9883f86c30da579008475f596c4
GIT binary patch
literal 1728
zcmaLUYfMvV8o=?_0=-b6t(-%J4!uyhmeRt3-fxHApp^o00J&3YK}w+uij3<To%i&d
zI1Vc(#`S|^3}cKj4#Nt#);Nq8)-c93j&WS$x~_4IF^)0DF~&H?jO%2aWIvF7KD}R_
z<o7;*Z>`5*3<`k|yaM3eyLSM9n>TOn-@iW?4B|NMcDrM-*pVYg?%ut7^ytz2{QTnL
z;_~uxy<Ts(+lPjR&YnG+o143N^X8{dpFVr`Y-wp}&z?Pvjg37$J?GAyyMFz;*=!bz
z#gmhhCr+H`>gw9DW5<IB4``Ye2n2(JgNF_s8W<QjefqT5>*e$LCr_R{aNt08b~cB@
zdHneC%a<>=ZQB-)$6vjA1tC0s{P>$UZ{EIrd*Q-`D_5?(e*OB^ty{CRv(KMDzj5Qn
z!-o&=-Me?~+O_57<;BIt`}gnPzJ2?}ix+q9+}XZ;`>9i>=I7_@>gt-BnmRf<LZOh;
z>9ks{mo8nJn3%vY?8%cSDwS&Q-o0&YZECezCX-E1PuJJiXJ%&Z-n}~<4p&uGUA}zz
z>eZ`{9z8m9=FHBWJNNC|clhw(*49>rVf=o7ZEdYmsXTV<m`Ef_PfwqjnMp}WIe743
zVPPSPqDG@}e0*G^(eQY@(a}+bLebpZJUl$SYuB##H~(!EKPU52-#-<<<T%H|!7bs9
z@`=GMo8-Yr@Z)GKxUp<-q(24}@Av^X(d5J%+!bZoq*d=1N`Kw|H6q~rc^80WoT4Pk
zVl_>1KU!N-26ZMqmCDb}S81SLYt@k~_G&4uLy!X?iJv(Mtad9*P7}>x4m(UqN9KUp
z4cQs!oF2D9jv#9esWw9{TRdlTx*$)uMn;=eSsqf9EiaI0F`j{I`A<AYQOGH;l$Kg}
zlX(p%nIFFJ?Co7z&1Qk$zw|%C$qzzvQtO7ajxGreENhziZR*aoJq47nzNtop5Wen`
z&bT+Z;d82jN@Xh<s3&XujSIk}gURcxXFVQRSa)dwL7_N+FPQrN0cwTZ1;TL=*v0E}
zXbsEt4K!9%*78gyjk{O!J&6~zl(x%!&LF`M#@fh?a37#&Nx)jQ67bUxKwfI*AiKMi
zMFS_t&lY5)r$wTap?hFcBZ@lL52bO*yo~`1y-D35fgxc(1BAm}ur$+_@Qp-ZMU6H=
zl&PV#5=&53V(;~MZ`hg8nMg#|f1WZ~zaza>GMv!swTK4QQ4VL3vl=%$G<RtaPcrse
zzWT52e{-y)oBE)$7fFQyMbt|JqnJ~eJ<t&e_$XXi6P0+Z)m?&m3rQ4I80h|<b!KR6
zDPllPS`ze?@)Dw<Rv7I!C6Lw4Fc$rmA#%rHmZdM@8}>tQku4D@Q9@6zA&>b(I!<bO
zjd@zAe+fn@#LeR65mrn$^5eAJla{h(Rjl|Ugu9aQ_rypr7M2!>>@?u1M#JLDn#_tU
z%4JE-a$p!MHD8!RdJGmb?UQFZpd%z<K)53cZ3ZGy9T|tgYJCC~_!seS88m~vz|tn1
zTe~63JI{=dB|%-E{hySyt(Zk(1cH&O!p;0tO6Sp<VA;qPZeqlMX_sz&MZ*7|SnDtr
zsYEzJ0|GaMd@}B6s*OS=y<S3R%FAhK!AYINrlG4V!+p@o`-+LJ7eT^>F~G*z^!5CC
zPd5jmQ_FRQQ0vj3uU@wi>ag#bu1J*B|C=fh1iW;ziXcMeP4zx{>%>T>x@~NYg~64B
z{IqNP|Mk<C_or7(y!%69z142Ene((XFcB^u3$Hdb=21FSgJM9Bnu}^3ajn%vdu2Wp
z>aiK7u^*q;G0;_NS)?#&_+lKZltOmd1%_2#04qwm7uz`^D9Pv))0V)WK8Ni?>W@PR
zn$_~hZUe=w-!`^2LlD{S{4Sg=U}wl{darJfuhjOl-*B|v<Uvu7jwW@O2kCRUtW*JQ
zLfmGA#M8^B2;7E2Wl3NP@UmRczg9JiIE|3sNzCeeA(*B<H)WEY1_NzHv#xd#4D-il
zMWr}o`8SNxSz_)oh&61fXta9ps6s5ERPy@By1H(TG&tqumS+b#9Y6j3FBkDo05Ja-
Dm!B`=
literal 0
HcmV?d00001
diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
index 2a956a3d..0f54aa5c 100644
--- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
@@ -83,7 +83,6 @@ define('tools.querytool', [
this.handler.preferences = this.preferences;
this.connIntervalId = null;
this.layout = opts.layout;
- this.set_server_version(opts.server_ver);
},
// Bind all the events
@@ -188,12 +187,14 @@ define('tools.querytool', [
});
},
+ set_editor_title: function(title) {
+ this.$el.find('.editor-title').text(title);
+ },
+
// This function is used to render the template.
render: function() {
var self = this;
- $('.editor-title').text(_.unescape(self.editor_title));
-
// Updates connection status flag
self.gain_focus = function() {
setTimeout(function() {
@@ -207,7 +208,6 @@ define('tools.querytool', [
}, 100);
};
-
// Create main wcDocker instance
self.docker = new wcDocker(
'#editor-panel', {
@@ -338,6 +338,10 @@ define('tools.querytool', [
});
self.render_history_grid();
+ pgBrowser.Events.on('pgadmin:query_tool:connected:'+self.handler.transId, ()=>{
+ self.fetch_query_history();
+ });
+
queryToolNotifications.renderNotificationsGrid(self.notifications_panel);
var text_container = $('<textarea id="sql_query_tool" tabindex="-1"></textarea>');
@@ -1327,6 +1331,24 @@ define('tools.querytool', [
}
},
+ fetch_query_history: function() {
+ let self = this;
+ $.ajax({
+ url: url_for('sqleditor.get_query_history', {
+ 'trans_id': self.handler.transId,
+ }),
+ method: 'GET',
+ contentType: 'application/json',
+ }).done(function(res) {
+ res.data.result.map((entry) => {
+ let newEntry = JSON.parse(entry);
+ newEntry.start_time = new Date(newEntry.start_time);
+ self.history_collection.add(newEntry);
+ });
+ }).fail(function() {
+ /* history fetch fail should not affect query tool */
+ });
+ },
/* This function is responsible to create and render the
* new backgrid for the history tab.
*/
@@ -1363,25 +1385,6 @@ define('tools.querytool', [
});
}
- // Make ajax call to get history data
- $.ajax({
- url: url_for('sqleditor.get_query_history', {
- 'trans_id': self.handler.transId,
- }),
- method: 'GET',
- contentType: 'application/json',
- })
- .done(function(res) {
- res.data.result.map((entry) => {
- let newEntry = JSON.parse(entry);
- newEntry.start_time = new Date(newEntry.start_time);
- self.history_collection.add(newEntry);
- });
- })
- .fail(function() {
- /* history fetch fail should not affect query tool */
- });
-
if(!self.handler.is_query_tool) {
self.historyComponent.setEditorPref({'copy_to_editor':false});
}
@@ -2016,13 +2019,13 @@ define('tools.querytool', [
},
initTransaction: function() {
- var url_endpoint;
- if (this.is_query_tool) {
+ var self = this, url_endpoint;
+ if (self.is_query_tool) {
url_endpoint = 'datagrid.initialize_query_tool';
// If database not present then use Maintenance database
// We will handle this at server side
- if (this.url_params.did) {
+ if (self.url_params.did) {
url_endpoint = 'datagrid.initialize_query_tool_with_did';
}
@@ -2030,10 +2033,25 @@ define('tools.querytool', [
url_endpoint = 'datagrid.initialize_datagrid';
}
- var baseUrl = url_for(url_endpoint, this.url_params);
+ var baseUrl = url_for(url_endpoint, {
+ ...self.url_params,
+ 'trans_id': self.transId,
+ });
- Datagrid.create_transaction(baseUrl, this, this.is_query_tool,
- this.server_type, '', '', '', true);
+ $.ajax({
+ url: baseUrl,
+ type: 'POST',
+ data: self.is_query_tool?null:JSON.stringify(self.url_params.sql_filter),
+ contentType: 'application/json',
+ }).done((res)=>{
+ pgBrowser.Events.trigger(
+ 'pgadmin:query_tool:connected:' + self.transId, res.data
+ );
+ }).fail((xhr, status, error)=>{
+ pgBrowser.Events.trigger(
+ 'pgadmin:query_tool:connected_fail:' + self.transId, xhr, error
+ );
+ });
},
handle_connection_lost: function(create_transaction, xhr) {
@@ -2138,12 +2156,10 @@ define('tools.querytool', [
* call the render method of the grid view to render the backgrid
* header and loading icon and start execution of the sql query.
*/
- start: function(transId, is_query_tool, editor_title, script_type_url,
- server_type, url_params, layout, server_ver
- ) {
+ start: function(transId, url_params, layout) {
var self = this;
- self.is_query_tool = is_query_tool;
+ self.is_query_tool = url_params.is_query_tool==='true'?true:false;
self.rows_affected = 0;
self.marked_line_no = 0;
self.has_more_rows = false;
@@ -2151,9 +2167,8 @@ define('tools.querytool', [
self.close_on_save = false;
self.close_on_idle_transaction = false;
self.last_transaction_status = -1;
- self.server_type = server_type;
+ self.server_type = url_params.server_type;
self.url_params = url_params;
- self.script_type_url = script_type_url;
self.is_transaction_buttons_disabled = true;
// We do not allow to call the start multiple times.
@@ -2164,16 +2179,48 @@ define('tools.querytool', [
el: self.container,
handler: self,
layout: layout,
- server_ver: server_ver,
});
self.transId = self.gridView.transId = transId;
- self.gridView.editor_title = _.unescape(editor_title);
self.gridView.current_file = undefined;
// Render the header
self.gridView.render();
+ self.trigger('pgadmin-sqleditor:loading-icon:hide');
+
+ self.gridView.set_editor_title(`(${gettext('Obtaining connection...')} ${_.unescape(url_params.title)}`);
+
+ let afterConn = function() {
+ let enableBtns = [];
+
+ if(self.is_query_tool){
+ enableBtns = ['#btn-flash', '#btn-explain', '#btn-explain-analyze'];
+ } else {
+ enableBtns = ['#btn-flash'];
+ }
+
+ enableBtns.forEach((selector)=>{
+ $(selector).prop('disabled', false);
+ });
+
+ $('#btn-conn-status i').removeClass('obtaining-conn');
+ self.gridView.set_editor_title(_.unescape(url_params.title));
+ };
+
+ pgBrowser.Events.on('pgadmin:query_tool:connected:' + transId, afterConn);
+ pgBrowser.Events.on('pgadmin:query_tool:connected_fail:' + transId, afterConn);
+
+ pgBrowser.Events.on('pgadmin:query_tool:connected:' + transId, (res_data)=>{
+ self.gridView.set_server_version(res_data.serverVersion);
+ });
+
+ pgBrowser.Events.on('pgadmin:query_tool:connected_fail:' + transId, (xhr, error)=>{
+ alertify.pgRespErrorNotify(xhr, error);
+ });
+
+ self.initTransaction();
+
/* wcDocker focuses on window always, and all our shortcuts are
* bind to editor-panel. So when we use wcDocker focus, editor-panel
* loses focus and events don't work.
@@ -2187,9 +2234,9 @@ define('tools.querytool', [
if (self.is_query_tool) {
// Fetch the SQL for Scripts (eg: CREATE/UPDATE/DELETE/SELECT)
// Call AJAX only if script type url is present
- if (script_type_url) {
+ if (url_params.query_url) {
$.ajax({
- url: script_type_url,
+ url: url_params.query_url,
type:'GET',
})
.done(function(res) {
@@ -2224,7 +2271,9 @@ define('tools.querytool', [
cm.className += ' bg-gray-lighter opacity-5 hide-cursor-workaround';
}
self.disable_tool_buttons(true);
- self.execute_data_query();
+ pgBrowser.Events.on('pgadmin:query_tool:connected:'+ transId,()=>{
+ self.execute_data_query();
+ });
}
},
@@ -3334,7 +3383,7 @@ define('tools.querytool', [
// Find the title of the visible panel
_.each(window.top.pgAdmin.Browser.docker.findPanels('frm_datagrid'), function(p) {
if (p.isVisible()) {
- self.gridView.panel_title = $(p._title).text();
+ self.gridView.panel_title = $(p._title).html();
}
});
diff --git a/web/pgadmin/tools/sqleditor/tests/test_download_csv_query_tool.py b/web/pgadmin/tools/sqleditor/tests/test_download_csv_query_tool.py
index 227c602a..f3652fc0 100644
--- a/web/pgadmin/tools/sqleditor/tests/test_download_csv_query_tool.py
+++ b/web/pgadmin/tools/sqleditor/tests/test_download_csv_query_tool.py
@@ -27,7 +27,7 @@ class TestDownloadCSV(BaseTestGenerator):
'Download csv URL with valid query',
dict(
sql='SELECT 1 as "A",2 as "B",3 as "C"',
- init_url='/datagrid/initialize/query_tool/{0}/{1}/{2}',
+ init_url='/datagrid/initialize/query_tool/{0}/{1}/{2}/{3}',
donwload_url="/sqleditor/query_tool/download/{0}",
output_columns='"A","B","C"',
output_values='1,2,3',
@@ -39,7 +39,7 @@ class TestDownloadCSV(BaseTestGenerator):
'Download csv URL with wrong TX id',
dict(
sql='SELECT 1 as "A",2 as "B",3 as "C"',
- init_url='/datagrid/initialize/query_tool/{0}/{1}/{2}',
+ init_url='/datagrid/initialize/query_tool/{0}/{1}/{2}/{3}',
donwload_url="/sqleditor/query_tool/download/{0}",
output_columns=None,
output_values=None,
@@ -51,7 +51,7 @@ class TestDownloadCSV(BaseTestGenerator):
'Download csv URL with wrong query',
dict(
sql='SELECT * FROM this_table_does_not_exist',
- init_url='/datagrid/initialize/query_tool/{0}/{1}/{2}',
+ init_url='/datagrid/initialize/query_tool/{0}/{1}/{2}/{3}',
donwload_url="/sqleditor/query_tool/download/{0}",
output_columns=None,
output_values=None,
@@ -81,13 +81,12 @@ class TestDownloadCSV(BaseTestGenerator):
raise Exception("Could not connect to the database.")
# Initialize query tool
+ self.trans_id = str(random.randint(1, 9999999))
url = self.init_url.format(
- test_utils.SERVER_GROUP, self._sid, self._did)
+ self.trans_id, test_utils.SERVER_GROUP, self._sid, self._did)
response = self.tester.post(url)
self.assertEquals(response.status_code, 200)
- response_data = json.loads(response.data.decode('utf-8'))
- self.trans_id = response_data['data']['gridTransId']
# If invalid tx test then make the Tx id invalid so that tests fails
if not self.is_valid_tx:
self.trans_id = self.trans_id + '007'
diff --git a/web/pgadmin/tools/sqleditor/tests/test_editor_history.py b/web/pgadmin/tools/sqleditor/tests/test_editor_history.py
index b43a20c5..f94c2598 100644
--- a/web/pgadmin/tools/sqleditor/tests/test_editor_history.py
+++ b/web/pgadmin/tools/sqleditor/tests/test_editor_history.py
@@ -14,6 +14,7 @@ from pgadmin.browser.server_groups.servers.databases.tests import utils as \
from pgadmin.utils.route import BaseTestGenerator
from regression import parent_node_dict
from regression.python_test_utils import test_utils as utils
+import random
class TestEditorHistory(BaseTestGenerator):
@@ -68,14 +69,12 @@ class TestEditorHistory(BaseTestGenerator):
raise Exception("Could not connect to the database.")
# Initialize query tool
- url = '/datagrid/initialize/query_tool/{0}/{1}/{2}'.format(
- utils.SERVER_GROUP, self.server_id, self.db_id)
+ self.trans_id = str(random.randint(1, 9999999))
+ url = '/datagrid/initialize/query_tool/{0}/{1}/{2}/{3}'.format(
+ self.trans_id, utils.SERVER_GROUP, self.server_id, self.db_id)
response = self.tester.post(url)
self.assertEquals(response.status_code, 200)
- response_data = json.loads(response.data.decode('utf-8'))
- self.trans_id = response_data['data']['gridTransId']
-
def runTest(self):
url = '/sqleditor/query_history/{0}'.format(self.trans_id)
diff --git a/web/pgadmin/tools/sqleditor/tests/test_encoding_charset.py b/web/pgadmin/tools/sqleditor/tests/test_encoding_charset.py
index caa2e53f..d5aa30c9 100644
--- a/web/pgadmin/tools/sqleditor/tests/test_encoding_charset.py
+++ b/web/pgadmin/tools/sqleditor/tests/test_encoding_charset.py
@@ -11,7 +11,6 @@
from pgadmin.utils.route import BaseTestGenerator
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
database_utils
-from regression import parent_node_dict
from regression.python_test_utils import test_utils
import json
from pgadmin.utils import server_utils, IS_PY2
@@ -256,14 +255,13 @@ class TestEncodingCharset(BaseTestGenerator):
raise Exception("Could not connect to the database.")
# Initialize query tool
- url = '/datagrid/initialize/query_tool/{0}/{1}/{2}'.format(
- test_utils.SERVER_GROUP, self.encode_sid, self.encode_did)
+ self.trans_id = str(random.randint(1, 9999999))
+ url = '/datagrid/initialize/query_tool/{0}/{1}/{2}/{3}'\
+ .format(self.trans_id, test_utils.SERVER_GROUP, self.encode_sid,
+ self.encode_did)
response = self.tester.post(url)
self.assertEquals(response.status_code, 200)
- response_data = json.loads(response.data.decode('utf-8'))
- self.trans_id = response_data['data']['gridTransId']
-
# Check character
url = "/sqleditor/query_tool/start/{0}".format(self.trans_id)
sql = "select E'{0}';".format(self.test_str)
diff --git a/web/pgadmin/tools/sqleditor/tests/test_explain_plan.py b/web/pgadmin/tools/sqleditor/tests/test_explain_plan.py
index 9f9d1384..daff5ba8 100644
--- a/web/pgadmin/tools/sqleditor/tests/test_explain_plan.py
+++ b/web/pgadmin/tools/sqleditor/tests/test_explain_plan.py
@@ -8,6 +8,7 @@
##########################################################################
import json
+import random
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
database_utils
@@ -32,14 +33,12 @@ class TestExplainPlan(BaseTestGenerator):
raise Exception("Could not connect to the database.")
# Initialize query tool
- url = '/datagrid/initialize/query_tool/{0}/{1}/{2}'.format(
- utils.SERVER_GROUP, self.server_id, self.db_id)
+ self.trans_id = str(random.randint(1, 9999999))
+ url = '/datagrid/initialize/query_tool/{0}/{1}/{2}/{3}'.format(
+ self.trans_id, utils.SERVER_GROUP, self.server_id, self.db_id)
response = self.tester.post(url)
self.assertEquals(response.status_code, 200)
- response_data = json.loads(response.data.decode('utf-8'))
- self.trans_id = response_data['data']['gridTransId']
-
# Start query tool transaction
url = '/sqleditor/query_tool/start/{0}'.format(self.trans_id)
response = self.tester.post(
diff --git a/web/pgadmin/tools/sqleditor/tests/test_poll_query_tool.py b/web/pgadmin/tools/sqleditor/tests/test_poll_query_tool.py
index 317019ed..5b4b354b 100644
--- a/web/pgadmin/tools/sqleditor/tests/test_poll_query_tool.py
+++ b/web/pgadmin/tools/sqleditor/tests/test_poll_query_tool.py
@@ -14,6 +14,7 @@ from pgadmin.browser.server_groups.servers.databases.tests import utils as \
from pgadmin.utils.route import BaseTestGenerator
from regression import parent_node_dict
from regression.python_test_utils import test_utils as utils
+import random
class TestPollQueryTool(BaseTestGenerator):
@@ -75,14 +76,12 @@ NOTICE: Hello, world!
raise Exception("Could not connect to the database.")
# Initialize query tool
- url = '/datagrid/initialize/query_tool/{0}/{1}/{2}'.format(
- utils.SERVER_GROUP, self.server_id, self.db_id)
+ self.trans_id = str(random.randint(1, 9999999))
+ url = '/datagrid/initialize/query_tool/{0}/{1}/{2}/{3}'.format(
+ self.trans_id, utils.SERVER_GROUP, self.server_id, self.db_id)
response = self.tester.post(url)
self.assertEquals(response.status_code, 200)
- response_data = json.loads(response.data.decode('utf-8'))
- self.trans_id = response_data['data']['gridTransId']
-
cnt = 0
for s in self.sql:
print("Executing and polling with: " + self.print_messages[cnt])
diff --git a/web/pgadmin/tools/sqleditor/tests/test_transaction_status.py b/web/pgadmin/tools/sqleditor/tests/test_transaction_status.py
index 57242962..59c855fb 100644
--- a/web/pgadmin/tools/sqleditor/tests/test_transaction_status.py
+++ b/web/pgadmin/tools/sqleditor/tests/test_transaction_status.py
@@ -301,14 +301,12 @@ class TestTransactionControl(BaseTestGenerator):
raise Exception("Could not connect to the database.")
def _initialize_query_tool(self):
- url = '/datagrid/initialize/query_tool/{0}/{1}/{2}'.format(
- utils.SERVER_GROUP, self.server_id, self.db_id)
+ self.trans_id = str(random.randint(1, 9999999))
+ url = '/datagrid/initialize/query_tool/{0}/{1}/{2}/{3}'.format(
+ self.trans_id, utils.SERVER_GROUP, self.server_id, self.db_id)
response = self.tester.post(url)
self.assertEquals(response.status_code, 200)
- response_data = json.loads(response.data.decode('utf-8'))
- self.trans_id = response_data['data']['gridTransId']
-
def _initialize_urls(self):
self.start_query_tool_url = \
'/sqleditor/query_tool/start/{0}'.format(self.trans_id)
diff --git a/web/pgadmin/tools/sqleditor/tests/test_view_data.py b/web/pgadmin/tools/sqleditor/tests/test_view_data.py
index b02e0e90..1096d5f6 100644
--- a/web/pgadmin/tools/sqleditor/tests/test_view_data.py
+++ b/web/pgadmin/tools/sqleditor/tests/test_view_data.py
@@ -70,15 +70,14 @@ class TestViewData(BaseTestGenerator):
table_id = result[0][0]
# Initialize query tool
- url = '/datagrid/initialize/datagrid/3/table/{0}/{1}/{2}/{3}'.format(
- test_utils.SERVER_GROUP, self.server_id, self.db_id, table_id)
+ self.trans_id = str(random.randint(1, 9999999))
+ url = '/datagrid/initialize/datagrid/{0}/3/table/{1}/{2}/{3}/{4}'\
+ .format(self.trans_id, test_utils.SERVER_GROUP, self.server_id,
+ self.db_id, table_id)
response = self.tester.post(url)
self.assertEquals(response.status_code, 200)
- response_data = json.loads(response.data.decode('utf-8'))
- self.trans_id = response_data['data']['gridTransId']
-
url = "/sqleditor/view_data/start/{0}".format(self.trans_id)
response = self.tester.get(url)
self.assertEquals(response.status_code, 200)
diff --git a/web/pgadmin/tools/sqleditor/utils/tests/test_is_query_resultset_updatable.py b/web/pgadmin/tools/sqleditor/utils/tests/test_is_query_resultset_updatable.py
index e620f8d0..40ca4c8f 100644
--- a/web/pgadmin/tools/sqleditor/utils/tests/test_is_query_resultset_updatable.py
+++ b/web/pgadmin/tools/sqleditor/utils/tests/test_is_query_resultset_updatable.py
@@ -149,14 +149,12 @@ class TestQueryUpdatableResultset(BaseTestGenerator):
raise Exception("Could not connect to the database.")
def _initialize_query_tool(self):
- url = '/datagrid/initialize/query_tool/{0}/{1}/{2}'.format(
- utils.SERVER_GROUP, self.server_id, self.db_id)
+ self.trans_id = str(random.randint(1, 9999999))
+ url = '/datagrid/initialize/query_tool/{0}/{1}/{2}/{3}'.format(
+ self.trans_id, utils.SERVER_GROUP, self.server_id, self.db_id)
response = self.tester.post(url)
self.assertEquals(response.status_code, 200)
- response_data = json.loads(response.data.decode('utf-8'))
- self.trans_id = response_data['data']['gridTransId']
-
def _initialize_urls(self):
self.start_query_tool_url = \
'/sqleditor/query_tool/start/{0}'.format(self.trans_id)
diff --git a/web/pgadmin/tools/sqleditor/utils/tests/test_save_changed_data.py b/web/pgadmin/tools/sqleditor/utils/tests/test_save_changed_data.py
index 3ae337b2..a0cb9f76 100644
--- a/web/pgadmin/tools/sqleditor/utils/tests/test_save_changed_data.py
+++ b/web/pgadmin/tools/sqleditor/utils/tests/test_save_changed_data.py
@@ -323,14 +323,12 @@ class TestSaveChangedData(BaseTestGenerator):
raise Exception("Could not connect to the database.")
def _initialize_query_tool(self):
- url = '/datagrid/initialize/query_tool/{0}/{1}/{2}'.format(
- utils.SERVER_GROUP, self.server_id, self.db_id)
+ self.trans_id = str(random.randint(1, 9999999))
+ url = '/datagrid/initialize/query_tool/{0}/{1}/{2}/{3}'.format(
+ self.trans_id, utils.SERVER_GROUP, self.server_id, self.db_id)
response = self.tester.post(url)
self.assertEquals(response.status_code, 200)
- response_data = json.loads(response.data.decode('utf-8'))
- self.trans_id = response_data['data']['gridTransId']
-
def _initialize_urls_and_select_sql(self):
self.start_query_tool_url = \
'/sqleditor/query_tool/start/{0}'.format(self.trans_id)
diff --git a/web/regression/javascript/datagrid/show_data_spec.js b/web/regression/javascript/datagrid/show_data_spec.js
index 3a97e5a2..278872ef 100644
--- a/web/regression/javascript/datagrid/show_data_spec.js
+++ b/web/regression/javascript/datagrid/show_data_spec.js
@@ -17,10 +17,11 @@ describe('#show_data', () => {
let datagrid;
let pgBrowser;
let alertify;
+ let transId = 98765432;
beforeEach(() => {
alertify = jasmine.createSpyObj('alertify', ['alert']);
datagrid = {
- create_transaction: jasmine.createSpy('create_transaction'),
+ launch_grid: jasmine.createSpy('launch_grid'),
};
pgBrowser = {
treeMenu: new TreeFake(),
@@ -98,12 +99,12 @@ describe('#show_data', () => {
context('cannot find the tree node', () => {
it('does not create a transaction', () => {
- showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: '10'}]);
- expect(datagrid.create_transaction).not.toHaveBeenCalled();
+ showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: '10'}], transId);
+ expect(datagrid.launch_grid).not.toHaveBeenCalled();
});
it('display alert', () => {
- showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: '10'}]);
+ showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: '10'}], transId);
expect(alertify.alert).toHaveBeenCalledWith(
'Data Grid Error',
'No object selected.'
@@ -113,59 +114,52 @@ describe('#show_data', () => {
context('current node is not underneath a server', () => {
it('does not create a transaction', () => {
- showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: 'parent'}]);
- expect(datagrid.create_transaction).not.toHaveBeenCalled();
+ showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: 'parent'}], transId);
+ expect(datagrid.launch_grid).not.toHaveBeenCalled();
});
});
context('current node is not underneath a schema or view or catalog', () => {
it('does not create a transaction', () => {
- showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: 'database1'}]);
- expect(datagrid.create_transaction).not.toHaveBeenCalled();
+ showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: 'database1'}], transId);
+ expect(datagrid.launch_grid).not.toHaveBeenCalled();
});
});
context('current node is underneath a schema', () => {
it('does not create a transaction', () => {
- showDataGrid(datagrid, pgBrowser, alertify, {mnuid: 11}, [{id: 'schema1'}]);
- expect(datagrid.create_transaction).toHaveBeenCalledWith(
- '/initialize/datagrid/11/schema/1/2/3/4',
- null,
- 'false',
- 'pg',
- '',
- 'schema1.schema1/database1/someuser@server1',
- ''
+ showDataGrid(datagrid, pgBrowser, alertify, {mnuid: 11}, [{id: 'schema1'}], transId);
+
+ expect(datagrid.launch_grid).toHaveBeenCalledWith(
+ 98765432,
+ '/panel/98765432?is_query_tool=false&cmd_type=11&obj_type=schema&obj_id=4&sgid=1&sid=2&did=3&server_type=pg',
+ false,
+ 'schema1.schema1/database1/someuser@server1'
);
});
});
context('current node is underneath a view', () => {
it('does not create a transaction', () => {
- showDataGrid(datagrid, pgBrowser, alertify, {mnuid: 11}, [{id: 'view1'}]);
- expect(datagrid.create_transaction).toHaveBeenCalledWith(
- '/initialize/datagrid/11/view/1/2/3/5',
- null,
- 'false',
- 'pg',
- '',
- 'view1.view1/database1/someuser@server1',
- ''
+ showDataGrid(datagrid, pgBrowser, alertify, {mnuid: 11}, [{id: 'view1'}], transId);
+
+ expect(datagrid.launch_grid).toHaveBeenCalledWith(
+ 98765432,
+ '/panel/98765432?is_query_tool=false&cmd_type=11&obj_type=view&obj_id=5&sgid=1&sid=2&did=3&server_type=pg',
+ false,
+ 'view1.view1/database1/someuser@server1'
);
});
});
context('current node is underneath a catalog', () => {
it('does not create a transaction', () => {
- showDataGrid(datagrid, pgBrowser, alertify, {mnuid: 11}, [{id: 'catalog1'}]);
- expect(datagrid.create_transaction).toHaveBeenCalledWith(
- '/initialize/datagrid/11/catalog/1/2/3/6',
- null,
- 'false',
- 'pg',
- '',
- 'catalog1.catalog1/database1/someuser@server1',
- ''
+ showDataGrid(datagrid, pgBrowser, alertify, {mnuid: 11}, [{id: 'catalog1'}], transId);
+ expect(datagrid.launch_grid).toHaveBeenCalledWith(
+ 98765432,
+ '/panel/98765432?is_query_tool=false&cmd_type=11&obj_type=catalog&obj_id=6&sgid=1&sid=2&did=3&server_type=pg',
+ false,
+ 'catalog1.catalog1/database1/someuser@server1'
);
});
});
diff --git a/web/regression/javascript/datagrid/show_query_tool_spec.js b/web/regression/javascript/datagrid/show_query_tool_spec.js
index 04cda926..c7a89726 100644
--- a/web/regression/javascript/datagrid/show_query_tool_spec.js
+++ b/web/regression/javascript/datagrid/show_query_tool_spec.js
@@ -17,10 +17,11 @@ describe('#showQueryTool', () => {
let queryTool;
let pgBrowser;
let alertify;
+ let transId = 98765432;
beforeEach(() => {
alertify = jasmine.createSpyObj('alertify', ['alert']);
queryTool = {
- create_transaction: jasmine.createSpy('create_transaction'),
+ launch_grid: jasmine.createSpy('launch_grid'),
};
pgBrowser = {
treeMenu: new TreeFake(),
@@ -66,10 +67,10 @@ describe('#showQueryTool', () => {
context('cannot find the tree node', () => {
beforeEach(() => {
- showQueryTool(queryTool, pgBrowser, alertify, '', [{id: '10'}]);
+ showQueryTool(queryTool, pgBrowser, alertify, '', [{id: '10'}], transId);
});
it('does not create a transaction', () => {
- expect(queryTool.create_transaction).not.toHaveBeenCalled();
+ expect(queryTool.launch_grid).not.toHaveBeenCalled();
});
it('display alert', () => {
@@ -82,8 +83,8 @@ describe('#showQueryTool', () => {
context('current node is not underneath a server', () => {
it('does not create a transaction', () => {
- showQueryTool(queryTool, pgBrowser, alertify, '', [{id: 'parent'}], 'title');
- expect(queryTool.create_transaction).not.toHaveBeenCalled();
+ showQueryTool(queryTool, pgBrowser, alertify, '', [{id: 'parent'}], transId);
+ expect(queryTool.launch_grid).not.toHaveBeenCalled();
});
it('no alert is displayed', () => {
@@ -94,32 +95,26 @@ describe('#showQueryTool', () => {
context('current node is underneath a server', () => {
context('current node is not underneath a database', () => {
it('creates a transaction', () => {
- showQueryTool(queryTool, pgBrowser, alertify, 'http://someurl', [{id: 'server1'}]);
- expect(queryTool.create_transaction).toHaveBeenCalledWith(
- '/initialize/query_tool/1/2',
- null,
- 'true',
- 'pg',
- 'http://someurl',
+ showQueryTool(queryTool, pgBrowser, alertify, 'http://someurl', [{id: 'server1'}], transId);
+ expect(queryTool.launch_grid).toHaveBeenCalledWith(
+ 98765432,
+ '/panel/98765432?is_query_tool=true&sgid=1&sid=2&server_type=pg',
+ true,
'otherdblabel/someuser@server1',
- '',
- false
+ 'http://someurl'
);
});
});
context('current node is underneath a database', () => {
it('creates a transaction', () => {
- showQueryTool(queryTool, pgBrowser, alertify, 'http://someurl', [{id: 'database1'}], 'title');
- expect(queryTool.create_transaction).toHaveBeenCalledWith(
- '/initialize/query_tool/1/2/3',
- null,
- 'true',
- 'pg',
- 'http://someurl',
+ showQueryTool(queryTool, pgBrowser, alertify, 'http://someurl', [{id: 'database1'}], transId);
+ expect(queryTool.launch_grid).toHaveBeenCalledWith(
+ 98765432,
+ '/panel/98765432?is_query_tool=true&sgid=1&sid=2&server_type=pg&did=3',
+ true,
'database1/someuser@server1',
- '',
- false
+ 'http://someurl'
);
});
});
diff --git a/web/regression/javascript/fake_endpoints.js b/web/regression/javascript/fake_endpoints.js
index e6df02e3..d706cff9 100644
--- a/web/regression/javascript/fake_endpoints.js
+++ b/web/regression/javascript/fake_endpoints.js
@@ -18,5 +18,6 @@ define(function () {
'datagrid.initialize_query_tool': '/initialize/query_tool/<int:sgid>/<int:sid>',
'datagrid.initialize_query_tool_with_did': '/initialize/query_tool/<int:sgid>/<int:sid>/<int:did>',
'restore.create_job': '/restore/job/<int:sid>',
+ 'datagrid.panel': '/panel/<int:trans_id>',
};
});
diff --git a/web/regression/javascript/pgadmin_utils_spec.js b/web/regression/javascript/pgadmin_utils_spec.js
index bc1959a4..31a5babe 100644
--- a/web/regression/javascript/pgadmin_utils_spec.js
+++ b/web/regression/javascript/pgadmin_utils_spec.js
@@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
-import { getEpoch, getGCD, getMod, quote_ident, parseFuncParams } from 'sources/utils';
+import { getEpoch, getGCD, getMod, quote_ident, parseFuncParams, getRandomInt } from 'sources/utils';
describe('getEpoch', function () {
it('should return non zero', function () {
@@ -135,3 +135,10 @@ describe('parseFuncParams', function () {
expect(parseFuncParams(funcLabel)).toEqual(expectedObj);
});
});
+
+describe('getRandomInt', function () {
+ it('is between', function () {
+ let id = getRandomInt(1, 9999999);
+ expect(1 <= id && id <= 9999999).toBeTruthy();
+ });
+});
diff --git a/web/regression/javascript/sqleditor_utils_spec.js b/web/regression/javascript/sqleditor_utils_spec.js
index 789f370c..614caeb5 100644
--- a/web/regression/javascript/sqleditor_utils_spec.js
+++ b/web/regression/javascript/sqleditor_utils_spec.js
@@ -36,61 +36,5 @@ define(['sources/sqleditor_utils'],
expect(SqlEditorUtils.calcFontSize(2)).toEqual('2em');
});
});
-
- describe('Remove the slashes', function () {
- it('it will remove the slashes', function () {
- expect(
- SqlEditorUtils.removeSlashInTheString('/')
- ).toEqual({
- 'slashLocations': '0',
- 'title': '',
- });
- });
-
- it('it will remove if slashes are present', function () {
- expect(
- SqlEditorUtils.removeSlashInTheString('my/test')
- ).toEqual({
- 'slashLocations': '2',
- 'title': 'mytest',
- });
- });
-
- it('it will remove all the slashes are present', function () {
- expect(
- SqlEditorUtils.removeSlashInTheString('my/test/value')
- ).toEqual({
- 'slashLocations': '2,7',
- 'title': 'mytestvalue',
- });
- });
-
- it('it will remove all the slashes are present', function () {
- expect(
- SqlEditorUtils.removeSlashInTheString('a/bb/ccc/dddd/eeeee')
- ).toEqual({
- 'slashLocations': '1,4,8,13',
- 'title': 'abbcccddddeeeee',
- });
- });
-
- it('it will not remove if slash is not present', function () {
- expect(
- SqlEditorUtils.removeSlashInTheString('mytest')
- ).toEqual({
- 'slashLocations': '',
- 'title': 'mytest',
- });
- });
-
- it('it will not remove if value is not present', function () {
- expect(
- SqlEditorUtils.removeSlashInTheString('')
- ).toEqual({
- 'slashLocations': '',
- 'title': '',
- });
- });
- });
});
});