mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-25 10:10:19 -06:00
Fix an initialisation error when two functions with parameters are debugged in parallel. Fixes #4329
This commit is contained in:
parent
6d52f2b911
commit
5437a8adab
@ -22,4 +22,5 @@ Bug fixes
|
||||
| `Bug #4255 <https://redmine.postgresql.org/issues/4255>`_ - Prevent the geometry viewer grabbing key presses when not in focus under Firefox, IE and Edge.
|
||||
| `Bug #4310 <https://redmine.postgresql.org/issues/4310>`_ - Ensure that the Return key can be used to submit the Master Password dialogue.
|
||||
| `Bug #4317 <https://redmine.postgresql.org/issues/4317>`_ - Ensure that browser auto-fill doesn't cause Help pages to be opened unexpectedly.
|
||||
| `Bug #4320 <https://redmine.postgresql.org/issues/4320>`_ - Fix issue where SSH tunnel connection using password is failing, it's regression of Master Password.
|
||||
| `Bug #4320 <https://redmine.postgresql.org/issues/4320>`_ - Fix issue where SSH tunnel connection using password is failing, it's regression of Master Password.
|
||||
| `Bug #4329 <https://redmine.postgresql.org/issues/4329>`_ - Fix an initialisation error when two functions with parameters are debugged in parallel.
|
File diff suppressed because it is too large
Load Diff
@ -313,8 +313,8 @@ define([
|
||||
url: _url,
|
||||
cache: false,
|
||||
})
|
||||
.done(function() {
|
||||
self.start_global_debugger();
|
||||
.done(function(res) {
|
||||
self.start_global_debugger(args, item, res.data.trans_id);
|
||||
})
|
||||
.fail(function(xhr) {
|
||||
try {
|
||||
@ -329,7 +329,7 @@ define([
|
||||
},
|
||||
|
||||
//Callback function when user start the indirect debugging ( Listen to another session to invoke the target )
|
||||
start_global_debugger: function(args, item) {
|
||||
start_global_debugger: function(args, item, trans_id) {
|
||||
// Initialize the target and create asynchronous connection and unique transaction ID
|
||||
var t = pgBrowser.tree,
|
||||
i = item || t.selected(),
|
||||
@ -343,48 +343,33 @@ define([
|
||||
var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]),
|
||||
baseUrl;
|
||||
|
||||
if (d._type == 'function') {
|
||||
if (d._type == 'function' || d._type == 'edbfunc') {
|
||||
baseUrl = url_for(
|
||||
'debugger.initialize_target_for_function', {
|
||||
'debug_type': 'indirect',
|
||||
'trans_id': trans_id,
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
'func_id': treeInfo.function._id,
|
||||
'func_id': debuggerUtils.getFunctionId(treeInfo),
|
||||
}
|
||||
);
|
||||
} else if (d._type == 'procedure') {
|
||||
} else if (d._type == 'procedure' || d._type == 'edbproc') {
|
||||
baseUrl = url_for(
|
||||
'debugger.initialize_target_for_function', {
|
||||
'debug_type': 'indirect',
|
||||
'trans_id': trans_id,
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
'func_id': debuggerUtils.getProcedureId(treeInfo),
|
||||
}
|
||||
);
|
||||
} else if (d._type == 'edbfunc') {
|
||||
// Get the existing function parameters available from sqlite database
|
||||
baseUrl = url_for('debugger.initialize_target_for_function', {
|
||||
'debug_type': 'indirect',
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
'func_id': treeInfo.edbfunc._id,
|
||||
});
|
||||
} else if (d._type == 'edbproc') {
|
||||
// Get the existing function parameters available from sqlite database
|
||||
baseUrl = url_for('debugger.initialize_target_for_function', {
|
||||
'debug_type': 'indirect',
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
'func_id': treeInfo.edbproc._id,
|
||||
});
|
||||
} else if (d._type == 'trigger_function') {
|
||||
baseUrl = url_for(
|
||||
'debugger.initialize_target_for_function', {
|
||||
'debug_type': 'indirect',
|
||||
'trans_id': trans_id,
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
@ -395,6 +380,7 @@ define([
|
||||
baseUrl = url_for(
|
||||
'debugger.initialize_target_for_trigger', {
|
||||
'debug_type': 'indirect',
|
||||
'trans_id': trans_id,
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
@ -406,6 +392,7 @@ define([
|
||||
baseUrl = url_for(
|
||||
'debugger.initialize_target_for_trigger', {
|
||||
'debug_type': 'indirect',
|
||||
'trans_id': trans_id,
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
@ -491,9 +478,11 @@ define([
|
||||
})
|
||||
.done(function(res) {
|
||||
|
||||
let debug_info = res.data.debug_info,
|
||||
trans_id = res.data.trans_id;
|
||||
// Open Alertify the dialog to take the input arguments from user if function having input arguments
|
||||
if (res.data[0]['require_input']) {
|
||||
get_function_arguments(res.data[0], 0, is_edb_proc);
|
||||
if (debug_info[0]['require_input']) {
|
||||
get_function_arguments(debug_info[0], 0, is_edb_proc, trans_id);
|
||||
} else {
|
||||
// Initialize the target and create asynchronous connection and unique transaction ID
|
||||
// If there is no arguments to the functions then we should not ask for for function arguments and
|
||||
@ -509,20 +498,22 @@ define([
|
||||
var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]),
|
||||
baseUrl;
|
||||
|
||||
if (d._type == 'function') {
|
||||
if (d._type == 'function' || d._type == 'edbfunc') {
|
||||
baseUrl = url_for(
|
||||
'debugger.initialize_target_for_function', {
|
||||
'debug_type': 'direct',
|
||||
'trans_id': trans_id,
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
'func_id': treeInfo.function._id,
|
||||
'func_id': debuggerUtils.getFunctionId(treeInfo),
|
||||
}
|
||||
);
|
||||
} else {
|
||||
} else if(d._type == 'procedure' || d._type == 'edbproc') {
|
||||
baseUrl = url_for(
|
||||
'debugger.initialize_target_for_function', {
|
||||
'debug_type': 'direct',
|
||||
'trans_id': trans_id,
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
@ -535,10 +526,10 @@ define([
|
||||
url: baseUrl,
|
||||
method: 'GET',
|
||||
})
|
||||
.done(function(res) {
|
||||
.done(function() {
|
||||
|
||||
var url = url_for('debugger.direct', {
|
||||
'trans_id': res.data.debuggerTransId,
|
||||
'trans_id': trans_id,
|
||||
});
|
||||
|
||||
if (self.preferences.debugger_new_browser_tab) {
|
||||
@ -563,7 +554,7 @@ define([
|
||||
// Register Panel Closed event
|
||||
panel.on(wcDocker.EVENT.CLOSED, function() {
|
||||
var closeUrl = url_for('debugger.close', {
|
||||
'trans_id': res.data.debuggerTransId,
|
||||
'trans_id': trans_id,
|
||||
});
|
||||
$.ajax({
|
||||
url: closeUrl,
|
||||
|
@ -163,11 +163,11 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
var res = function(debug_info, restart_debug, is_edb_proc) {
|
||||
var res = function(debug_info, restart_debug, is_edb_proc, trans_id) {
|
||||
if (!Alertify.debuggerInputArgsDialog) {
|
||||
Alertify.dialog('debuggerInputArgsDialog', function factory() {
|
||||
return {
|
||||
main: function(title, debug_info, restart_debug, is_edb_proc) {
|
||||
main: function(title, debug_info, restart_debug, is_edb_proc, trans_id) {
|
||||
this.preferences = window.top.pgAdmin.Browser.get_preferences_for_module('debugger');
|
||||
this.set('title', title);
|
||||
|
||||
@ -175,6 +175,7 @@ define([
|
||||
// other functions other than main function.
|
||||
this.set('debug_info', debug_info);
|
||||
this.set('restart_debug', restart_debug);
|
||||
this.set('trans_id', trans_id);
|
||||
|
||||
// Variables to store the data sent from sqlite database
|
||||
var func_args_data = this.func_args_data = [];
|
||||
@ -579,6 +580,7 @@ define([
|
||||
settings: {
|
||||
debug_info: undefined,
|
||||
restart_debug: undefined,
|
||||
trans_id: undefined,
|
||||
},
|
||||
setup: function() {
|
||||
return {
|
||||
@ -706,6 +708,7 @@ define([
|
||||
if (d._type == 'function') {
|
||||
baseUrl = url_for('debugger.initialize_target_for_function', {
|
||||
'debug_type': 'direct',
|
||||
'trans_id': self.setting('trans_id'),
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
@ -714,6 +717,7 @@ define([
|
||||
} else if (d._type == 'procedure') {
|
||||
baseUrl = url_for('debugger.initialize_target_for_function', {
|
||||
'debug_type': 'direct',
|
||||
'trans_id': self.setting('trans_id'),
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
@ -722,6 +726,7 @@ define([
|
||||
} else if (d._type == 'edbfunc') {
|
||||
baseUrl = url_for('debugger.initialize_target_for_function', {
|
||||
'debug_type': 'direct',
|
||||
'trans_id': self.setting('trans_id'),
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
@ -730,6 +735,7 @@ define([
|
||||
} else if (d._type == 'edbproc') {
|
||||
baseUrl = url_for('debugger.initialize_target_for_function', {
|
||||
'debug_type': 'direct',
|
||||
'trans_id': self.setting('trans_id'),
|
||||
'sid': treeInfo.server._id,
|
||||
'did': treeInfo.database._id,
|
||||
'scid': treeInfo.schema._id,
|
||||
@ -885,7 +891,12 @@ define([
|
||||
}
|
||||
|
||||
if (e.button.text === gettext('Cancel')) {
|
||||
//close the dialog...
|
||||
/* Clear the trans id */
|
||||
$.ajax({
|
||||
method: 'DELETE',
|
||||
url: url_for('debugger.close', {'trans_id': this.setting('trans_id')}),
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
@ -959,7 +970,7 @@ define([
|
||||
}
|
||||
|
||||
Alertify.debuggerInputArgsDialog(
|
||||
gettext('Debugger'), debug_info, restart_debug, is_edb_proc
|
||||
gettext('Debugger'), debug_info, restart_debug, is_edb_proc, trans_id
|
||||
).resizeTo(pgBrowser.stdW.md,pgBrowser.stdH.md);
|
||||
|
||||
};
|
||||
|
@ -18,6 +18,18 @@ function setFocusToDebuggerEditor(editor, command) {
|
||||
}
|
||||
}
|
||||
|
||||
function getFunctionId(treeInfoObject) {
|
||||
let objectId;
|
||||
if(treeInfoObject) {
|
||||
if (treeInfoObject.function && treeInfoObject.function._id) {
|
||||
objectId = treeInfoObject.function._id;
|
||||
} else if (treeInfoObject.edbfunc && treeInfoObject.edbfunc._id) {
|
||||
objectId = treeInfoObject.edbfunc._id;
|
||||
}
|
||||
}
|
||||
return objectId;
|
||||
}
|
||||
|
||||
function getProcedureId(treeInfoObject) {
|
||||
let objectId;
|
||||
if(treeInfoObject) {
|
||||
@ -32,5 +44,6 @@ function getProcedureId(treeInfoObject) {
|
||||
|
||||
module.exports = {
|
||||
setFocusToDebuggerEditor: setFocusToDebuggerEditor,
|
||||
getFunctionId: getFunctionId,
|
||||
getProcedureId: getProcedureId,
|
||||
};
|
||||
|
81
web/pgadmin/tools/debugger/utils/debugger_instance.py
Normal file
81
web/pgadmin/tools/debugger/utils/debugger_instance.py
Normal file
@ -0,0 +1,81 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2019, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
from flask import session
|
||||
from threading import Lock
|
||||
import random
|
||||
|
||||
debugger_sessions_lock = Lock()
|
||||
|
||||
|
||||
class DebuggerInstance:
|
||||
def __init__(self, trans_id=None):
|
||||
if trans_id is None:
|
||||
self._trans_id = str(random.randint(1, 9999999))
|
||||
else:
|
||||
self._trans_id = trans_id
|
||||
|
||||
self._function_data = None
|
||||
self._debugger_data = None
|
||||
self.load_from_session()
|
||||
|
||||
@property
|
||||
def trans_id(self):
|
||||
"""
|
||||
trans_id be readonly with no setter
|
||||
"""
|
||||
return self._trans_id
|
||||
|
||||
@property
|
||||
def function_data(self):
|
||||
return self._function_data
|
||||
|
||||
@function_data.setter
|
||||
def function_data(self, data):
|
||||
self._function_data = data
|
||||
self.update_session()
|
||||
|
||||
@property
|
||||
def debugger_data(self):
|
||||
return self._debugger_data
|
||||
|
||||
@debugger_data.setter
|
||||
def debugger_data(self, data):
|
||||
self._debugger_data = data
|
||||
self.update_session()
|
||||
|
||||
@staticmethod
|
||||
def get_trans_ids():
|
||||
if '__debugger_sessions' in session:
|
||||
return [trans_id for trans_id in session['__debugger_sessions']]
|
||||
else:
|
||||
return []
|
||||
|
||||
def load_from_session(self):
|
||||
if '__debugger_sessions' in session:
|
||||
if str(self.trans_id) in session['__debugger_sessions']:
|
||||
trans_data = session['__debugger_sessions'][str(self.trans_id)]
|
||||
self.function_data = trans_data.get('function_data', None)
|
||||
self.debugger_data = trans_data.get('debugger_data', None)
|
||||
|
||||
def update_session(self):
|
||||
with debugger_sessions_lock:
|
||||
if '__debugger_sessions' not in session:
|
||||
session['__debugger_sessions'] = dict()
|
||||
|
||||
session['__debugger_sessions'][str(self.trans_id)] = dict(
|
||||
function_data=self.function_data,
|
||||
debugger_data=self.debugger_data
|
||||
)
|
||||
|
||||
def clear(self):
|
||||
with debugger_sessions_lock:
|
||||
if '__debugger_sessions' in session:
|
||||
if str(self.trans_id) in session['__debugger_sessions']:
|
||||
session['__debugger_sessions'].pop(str(self.trans_id))
|
Loading…
Reference in New Issue
Block a user