public inbox for [email protected]
help / color / mirror / Atom feedFrom: Aditya Toshniwal <[email protected]>
To: Akshay Joshi <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Subject: Re: [pgAdmin][RM4329] Initialization error when parameterised functions debugged in parallel in two separate tabs
Date: Mon, 10 Jun 2019 18:27:48 +0530
Message-ID: <CAM9w-_mkawLvUPZP0Y+KRbJ=5NoRKou67PG9UESdQYtktKEzbQ@mail.gmail.com> (raw)
In-Reply-To: <CANxoLDd7ERSsT2YxHpoLR8WL-Dz0E8HF0RpcxaT_KCFSpgoc_A@mail.gmail.com>
References: <CAM9w-_m2nNvKEQPGiHEtFCNF4Qg1aZ0MeTqB=6zNpMe5zj8rUg@mail.gmail.com>
<CANxoLDd7ERSsT2YxHpoLR8WL-Dz0E8HF0RpcxaT_KCFSpgoc_A@mail.gmail.com>
Hi Hackers,
Attached is the updated patch with fixes.
On Mon, Jun 10, 2019 at 12:58 PM Akshay Joshi <[email protected]>
wrote:
> Hi Aditya
>
> Following are the review comments:
>
> - "Set breakpoint" option not working, when click it throws an error.
>
> Fixed.
>
> - Create an empty function and try to debug that. It should show
> proper error message.
>
> This seems to be a bug in the debugger itself. I'll raise a bug with
simulation steps if it is. But, not sure where to raise.
>
> - Got the following backend error when closing the connection, please
> fix this:
> - File
> "E:\Projects\pgadmin4\web\pgadmin\tools\debugger\__init__.py", line 2053,
> in close_debugger_session
> conn_id=dbg_obj['exe_conn_id'])
>
> Fixed.
>
> On Fri, Jun 7, 2019 at 12:21 PM Aditya Toshniwal <
> [email protected]> wrote:
>
>> Hi Hackers,
>>
>> Attached is the patch for debugger improvements. The changes include:
>> 1) Change the way debug info is stored in session. Removed redundant
>> session related code in debugger code. All the session related handling
>> done at one place.
>> 2) Fixed a bug where debugger was not opening for EPAS package function.
>> 3) If a package is defined without body and we try to debug a proc/func,
>> the debugger opened a blank window. Changes made so that it will throw
>> error as "XYZ is not defined in package body."
>>
>> --
>> Thanks and Regards,
>> Aditya Toshniwal
>> Software Engineer | EnterpriseDB India | Pune
>> "Don't Complain about Heat, Plant a TREE"
>>
>
>
> --
> *Thanks & Regards*
> *Akshay Joshi*
>
> *Sr. Software Architect*
> *EnterpriseDB Software India Private Limited*
> *Mobile: +91 976-788-8246*
>
--
Thanks and Regards,
Aditya Toshniwal
Software Engineer | EnterpriseDB India | Pune
"Don't Complain about Heat, Plant a TREE"
Attachments:
[application/octet-stream] RM4329_v2.patch (59.8K, 3-RM4329_v2.patch)
download | inline diff:
diff --git a/web/pgadmin/tools/debugger/__init__.py b/web/pgadmin/tools/debugger/__init__.py
index 44d55da8..6d1a80b4 100644
--- a/web/pgadmin/tools/debugger/__init__.py
+++ b/web/pgadmin/tools/debugger/__init__.py
@@ -15,7 +15,6 @@ import simplejson as json
import random
import re
-from threading import Lock
from flask import url_for, Response, render_template, request, session, \
current_app
from flask_babelex import gettext
@@ -33,10 +32,10 @@ from pgadmin.settings import get_setting
from config import PG_DEFAULT_DRIVER
from pgadmin.model import db, DebuggerFunctionArguments
+from pgadmin.tools.debugger.utils.debugger_instance import DebuggerInstance
# Constants
ASYNC_OK = 1
-debugger_close_session_lock = Lock()
class DebuggerModule(PgAdminModule):
@@ -234,14 +233,7 @@ class DebuggerModule(PgAdminModule):
:param user:
:return:
"""
- with debugger_close_session_lock:
- if 'debuggerData' in session:
- for trans_id in session['debuggerData']:
- close_debugger_session(trans_id)
-
- # Delete the all debugger data from session variable
- del session['debuggerData']
- del session['functionData']
+ close_debugger_session(None, close_all=True)
blueprint = DebuggerModule(MODULE_NAME, __name__)
@@ -291,26 +283,6 @@ def script_debugger_direct_js():
)
-def update_session_debugger_transaction(trans_id, data):
- """
- Update the session variables required for debugger with transaction ID
- """
- debugger_data = session['debuggerData']
- debugger_data[str(trans_id)] = data
-
- session['debuggerData'] = debugger_data
-
-
-def update_session_function_transaction(trans_id, data):
- """
- Update the session variables of functions required to debug with
- transaction ID
- """
- function_data = session['functionData']
- function_data[str(trans_id)] = data
- session['functionData'] = function_data
-
-
@blueprint.route(
'/init/<node_type>/<int:sid>/<int:did>/<int:scid>/<int:fid>',
methods=['GET'], endpoint='init_for_function'
@@ -332,6 +304,8 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
not require these data because user will
provide all the arguments and other functions information through another
session to invoke the target.
+ It will also create a unique transaction id and store the information
+ into session variable.
Parameters:
node_type
@@ -404,10 +378,19 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
# Check that the function is actually debuggable...
if r_set['rows'][0]:
+ # If func/proc is not defined in package body
+ # then it is not debuggable
+ if (r_set['rows'][0]['pkgname'] is not None or
+ r_set['rows'][0]['pkgname'] != '') and \
+ r_set['rows'][0]['prosrc'] == '':
+ ret_status = False
+ msg = r_set['rows'][0]['name'] + ' ' + \
+ gettext("is not defined in package body.")
+
# Function with a colon in the name cannot be debugged.
# If this is an EDB wrapped function, no debugging allowed
# Function with return type "trigger" cannot be debugged.
- if ":" in r_set['rows'][0]['name']:
+ elif ":" in r_set['rows'][0]['name']:
ret_status = False
msg = gettext(
"Functions with a colon in the name cannot be debugged.")
@@ -469,12 +452,6 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
current_app.logger.debug(msg)
return internal_server_error(msg)
- # Store the function information in session variable
- if 'funcData' not in session:
- function_data = dict()
- else:
- function_data = session['funcData']
-
data = {'name': r_set['rows'][0]['proargnames'],
'type': r_set['rows'][0]['proargtypenames'],
'use_default': r_set['rows'][0]['pronargdefaults'],
@@ -502,7 +479,9 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
r_set['rows'][0]['require_input'] = data['require_input']
- function_data = {
+ # Create a debugger instance
+ de_inst = DebuggerInstance()
+ de_inst.function_data = {
'oid': fid,
'name': r_set['rows'][0]['name'],
'is_func': r_set['rows'][0]['isfunc'],
@@ -522,10 +501,11 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
'args_value': ''
}
- session['funcData'] = function_data
-
return make_json_response(
- data=r_set['rows'],
+ data=dict(
+ debug_info=r_set['rows'],
+ trans_id=de_inst.trans_id
+ ),
status=200
)
@@ -533,16 +513,15 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
@blueprint.route('/direct/<int:trans_id>', methods=['GET'], endpoint='direct')
@login_required
def direct_new(trans_id):
- debugger_data = session['debuggerData']
+ de_inst = DebuggerInstance(trans_id)
+
# Return from the function if transaction id not found
- if str(trans_id) not in debugger_data:
+ if de_inst.debugger_data is None:
return make_json_response(data={'status': True})
- obj = debugger_data[str(trans_id)]
-
# if indirect debugging pass value 0 to client and for direct debugging
# pass it to 1
- debug_type = 0 if obj['debug_type'] == 'indirect' else 1
+ debug_type = 0 if de_inst.debugger_data['debug_type'] == 'indirect' else 1
"""
Animations and transitions are not automatically GPU accelerated and by
@@ -572,12 +551,11 @@ def direct_new(trans_id):
function_arguments = '('
if 'functionData' in session:
- session_function_data = session['functionData'][str(trans_id)]
- if 'args_name' in session_function_data and \
- session_function_data['args_name'] is not None and \
- session_function_data['args_name'] != '':
- args_name_list = session_function_data['args_name'].split(",")
- args_type_list = session_function_data['args_type'].split(",")
+ if 'args_name' in de_inst.function_data and \
+ de_inst.function_data['args_name'] is not None and \
+ de_inst.function_data['args_name'] != '':
+ args_name_list = de_inst.function_data['args_name'].split(",")
+ args_type_list = de_inst.function_data['args_type'].split(",")
index = 0
for args_name in args_name_list:
function_arguments = '{}{} {}, '.format(function_arguments,
@@ -592,40 +570,42 @@ def direct_new(trans_id):
layout = get_setting('Debugger/Layout')
+ function_name_with_arguments = \
+ de_inst.debugger_data['function_name'] + function_arguments
+
return render_template(
"debugger/direct.html",
_=gettext,
- function_name=obj['function_name'],
+ function_name=de_inst.debugger_data['function_name'],
uniqueId=trans_id,
debug_type=debug_type,
is_desktop_mode=current_app.PGADMIN_RUNTIME,
is_linux=is_linux_platform,
client_platform=user_agent.platform,
- function_name_with_arguments=obj['function_name'] + function_arguments,
+ function_name_with_arguments=function_name_with_arguments,
layout=layout
)
@blueprint.route(
- '/initialize_target/<debug_type>/<int:sid>/<int:did>/<int:scid>/'
- '<int:func_id>',
+ '/initialize_target/<debug_type>/<int:trans_id>/<int:sid>/<int:did>/'
+ '<int:scid>/<int:func_id>',
methods=['GET', 'POST'],
endpoint='initialize_target_for_function'
)
@blueprint.route(
- '/initialize_target/<debug_type>/<int:sid>/<int:did>/<int:scid>/'
- '<int:func_id>/<int:tri_id>',
+ '/initialize_target/<debug_type>/<int:trans_id>/<int:sid>/<int:did>/'
+ '<int:scid>/<int:func_id>/<int:tri_id>',
methods=['GET', 'POST'],
endpoint='initialize_target_for_trigger'
)
@login_required
-def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
+def initialize_target(debug_type, trans_id, sid, did,
+ scid, func_id, tri_id=None):
"""
initialize_target(debug_type, sid, did, scid, func_id, tri_id)
This method is responsible for creating an asynchronous connection.
- It will also create a unique transaction id and store the information
- into session variable.
Parameters:
debug_type
@@ -718,16 +698,6 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
func_id = tr_set['rows'][0]['tgfoid']
- # Create a unique id for the transaction
- trans_id = str(random.randint(1, 9999999))
-
- # If there is no debugging information in session variable then create
- # the store that information
- if 'debuggerData' not in session:
- debugger_data = dict()
- else:
- debugger_data = session['debuggerData']
-
status = True
# Find out the debugger version and store it in session variables
@@ -756,6 +726,7 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
# Add the debugger version information to pgadmin4 log file
current_app.logger.debug("Debugger version is: %d", debugger_version)
+ de_inst = DebuggerInstance(trans_id)
# We need to pass the value entered by the user in dialog for direct
# debugging, Here we get the value in case of direct debugging so update
# the session variables accordingly, For indirect debugging user will
@@ -764,65 +735,26 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
if request.method == 'POST':
data = json.loads(request.values['data'], encoding='utf-8')
if data:
- d = session['funcData']
- d['args_value'] = data
- session['funcData'] = d
+ de_inst.function_data['args_value'] = data
# Update the debugger data session variable
# Here frame_id is required when user debug the multilevel function.
# When user select the frame from client we need to update the frame
# here and set the breakpoint information on that function oid
- debugger_data[str(trans_id)] = {
+ de_inst.debugger_data = {
'conn_id': conn_id,
'server_id': sid,
'database_id': did,
'schema_id': scid,
'function_id': func_id,
- 'function_name': session['funcData']['name'],
+ 'function_name': de_inst.function_data['name'],
'debug_type': debug_type,
'debugger_version': debugger_version,
'frame_id': 0,
'restart_debug': 0
}
- # Store the grid dictionary into the session variable
- session['debuggerData'] = debugger_data
-
- # Update the function session information with same transaction id
- func_data = session['funcData']
-
- # Store the function information in session variable
- if 'functionData' not in session:
- function_data = dict()
- else:
- function_data = session['functionData']
-
- function_data[str(trans_id)] = {
- 'oid': func_data['oid'],
- 'name': func_data['name'],
- 'is_func': func_data['is_func'],
- 'is_ppas_database': func_data['is_ppas_database'],
- 'is_callable': func_data['is_callable'],
- 'schema': func_data['schema'],
- 'language': func_data['language'],
- 'return_type': func_data['return_type'],
- 'args_type': func_data['args_type'],
- 'args_name': func_data['args_name'],
- 'arg_mode': func_data['arg_mode'],
- 'use_default': func_data['use_default'],
- 'default_value': func_data['default_value'],
- 'pkgname': func_data['pkgname'],
- 'pkg': func_data['pkg'],
- 'require_input': func_data['require_input'],
- 'args_value': func_data['args_value']
- }
-
- # Update the session variable of function information
- session['functionData'] = function_data
-
- # Delete the 'funcData' session variables as it is not used now as target
- # is initialized
- del session['funcData']
+ de_inst.update_session()
return make_json_response(data={'status': status,
'debuggerTransId': trans_id})
@@ -843,24 +775,9 @@ def close(trans_id):
trans_id
- unique transaction id.
"""
- # As debugger data is not in session that means we have already
- # deleted and close the target
- if 'debuggerData' not in session:
- return make_json_response(data={'status': True})
-
- # Return from the function if transaction id not found
- if str(trans_id) not in session['debuggerData']:
- return make_json_response(data={'status': True})
- with debugger_close_session_lock:
- try:
- close_debugger_session(trans_id)
- # Delete the existing debugger data in session variable
- del session['debuggerData'][str(trans_id)]
- del session['functionData'][str(trans_id)]
- return make_json_response(data={'status': True})
- except Exception as e:
- return internal_server_error(errormsg=str(e))
+ close_debugger_session(trans_id)
+ return make_json_response(data={'status': True})
@blueprint.route(
@@ -878,8 +795,8 @@ def restart_debugging(trans_id):
- Transaction ID
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+ de_inst = DebuggerInstance(trans_id)
+ if de_inst.debugger_data is None:
return make_json_response(
data={
'status': False,
@@ -889,44 +806,39 @@ def restart_debugging(trans_id):
)
}
)
- obj = debugger_data[str(trans_id)]
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
- conn = manager.connection(did=obj['database_id'], conn_id=obj['conn_id'])
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+ de_inst.debugger_data['server_id'])
+ conn = manager.connection(
+ did=de_inst.debugger_data['database_id'],
+ conn_id=de_inst.debugger_data['conn_id'])
if conn.connected():
# Update the session variable "restart_debug" to know that same
# function debugging has been restarted. Delete the existing debugger
# data in session variable and update with new data
- if obj['restart_debug'] == 0:
- debugger_data = session['debuggerData']
- session_obj = debugger_data[str(trans_id)]
- session_obj['restart_debug'] = 1
- update_session_debugger_transaction(trans_id, session_obj)
-
- # Store the function information in session variable
- if 'functionData' not in session:
- function_data = dict()
- else:
- session_function_data = session['functionData'][str(trans_id)]
- function_data = {
- 'server_id': obj['server_id'],
- 'database_id': obj['database_id'],
- 'schema_id': obj['schema_id'],
- 'function_id': obj['function_id'],
- 'trans_id': str(trans_id),
- 'proargmodes': session_function_data['arg_mode'],
- 'proargtypenames': session_function_data['args_type'],
- 'pronargdefaults': session_function_data['use_default'],
- 'proargdefaults': session_function_data['default_value'],
- 'proargnames': session_function_data['args_name'],
- 'require_input': session_function_data['require_input']
- }
+ if de_inst.debugger_data['restart_debug'] == 0:
+ de_inst.debugger_data['restart_debug'] = 1
+ de_inst.update_session()
+
+ de_inst.function_data = {
+ 'server_id': de_inst.debugger_data['server_id'],
+ 'database_id': de_inst.debugger_data['database_id'],
+ 'schema_id': de_inst.debugger_data['schema_id'],
+ 'function_id': de_inst.debugger_data['function_id'],
+ 'trans_id': str(trans_id),
+ 'proargmodes': de_inst.function_data['arg_mode'],
+ 'proargtypenames': de_inst.function_data['args_type'],
+ 'pronargdefaults': de_inst.function_data['use_default'],
+ 'proargdefaults': de_inst.function_data['default_value'],
+ 'proargnames': de_inst.function_data['args_name'],
+ 'require_input': de_inst.function_data['require_input']
+ }
return make_json_response(
data={
- 'status': True, 'restart_debug': True, 'result': function_data
+ 'status': True, 'restart_debug': True,
+ 'result': de_inst.function_data
}
)
else:
@@ -935,8 +847,7 @@ def restart_debugging(trans_id):
'Not connected to server or connection with the server has '
'been closed.'
)
-
- return make_json_response(data={'status': status})
+ return make_json_response(data={'status': status, 'result': result})
@blueprint.route(
@@ -956,8 +867,8 @@ def start_debugger_listener(trans_id):
- Transaction ID
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+ de_inst = DebuggerInstance(trans_id)
+ if de_inst.debugger_data is None:
return make_json_response(
data={
'status': False,
@@ -967,17 +878,18 @@ def start_debugger_listener(trans_id):
)
}
)
- obj = debugger_data[str(trans_id)]
driver = get_driver(PG_DEFAULT_DRIVER)
- manager = driver.connection_manager(obj['server_id'])
- conn = manager.connection(did=obj['database_id'], conn_id=obj['conn_id'])
+ manager = driver.connection_manager(de_inst.debugger_data['server_id'])
+ conn = manager.connection(
+ did=de_inst.debugger_data['database_id'],
+ conn_id=de_inst.debugger_data['conn_id'])
ver = manager.version
server_type = manager.server_type
# find the debugger version and execute the query accordingly
- dbg_version = obj['debugger_version']
+ dbg_version = de_inst.debugger_data['debugger_version']
if dbg_version <= 2:
template_path = 'debugger/sql/v1'
else:
@@ -988,94 +900,91 @@ def start_debugger_listener(trans_id):
if request.method == 'POST':
data = json.loads(request.values['data'], encoding='utf-8')
if data:
- function_data = session['functionData']
- session_obj = function_data[str(trans_id)]
- session_obj['args_value'] = data
- update_session_function_transaction(trans_id, session_obj)
+ de_inst.function_data['args_value'] = data
+ de_inst.update_session()
if conn.connected():
# For the direct debugging extract the function arguments values from
# user and pass to jinja template to create the query for execution.
- if obj['debug_type'] == 'direct':
+ if de_inst.debugger_data['debug_type'] == 'direct':
str_query = ''
- session_function_data = session['functionData'][str(trans_id)]
- if session_function_data['pkg'] == 0:
+ if de_inst.function_data['pkg'] == 0:
# Form the function name with schema name
func_name = driver.qtIdent(
conn,
- session_function_data['schema'],
- session_function_data['name']
+ de_inst.function_data['schema'],
+ de_inst.function_data['name']
)
else:
# Form the edb package function/procedure name with schema name
func_name = driver.qtIdent(
- conn, session_function_data['schema'],
- session_function_data['pkgname'],
- session_function_data['name']
+ conn, de_inst.function_data['schema'],
+ de_inst.function_data['pkgname'],
+ de_inst.function_data['name']
)
- if obj['restart_debug'] == 0:
+ if de_inst.debugger_data['restart_debug'] == 0:
# render the SQL template and send the query to server
- if session_function_data['language'] == 'plpgsql':
+ if de_inst.function_data['language'] == 'plpgsql':
sql = render_template(
"/".join([template_path,
'debug_plpgsql_execute_target.sql']),
- packge_oid=session_function_data['pkg'],
- function_oid=obj['function_id']
+ packge_oid=de_inst.function_data['pkg'],
+ function_oid=de_inst.debugger_data['function_id']
)
else:
sql = render_template(
"/".join([template_path,
'debug_spl_execute_target.sql']),
- packge_oid=session_function_data['pkg'],
- function_oid=obj['function_id']
+ packge_oid=de_inst.function_data['pkg'],
+ function_oid=de_inst.debugger_data['function_id']
)
status, res = conn.execute_dict(sql)
if not status:
return internal_server_error(errormsg=res)
- if session_function_data['arg_mode']:
+ if de_inst.function_data['arg_mode']:
# In EDBAS 90, if an SPL-function has both an OUT-parameter
# and a return value (which is not possible on PostgreSQL
# otherwise), the return value is transformed into an extra
# OUT-parameter named "_retval_"
- if session_function_data['args_name']:
- arg_name = session_function_data['args_name'].split(",")
+ if de_inst.function_data['args_name']:
+ arg_name = de_inst.function_data['args_name'].split(",")
if '_retval_' in arg_name:
- arg_mode = session_function_data['arg_mode'].split(",")
+ arg_mode = de_inst.function_data['arg_mode'].split(",")
arg_mode.pop()
else:
- arg_mode = session_function_data['arg_mode'].split(",")
+ arg_mode = de_inst.function_data['arg_mode'].split(",")
else:
- arg_mode = session_function_data['arg_mode'].split(",")
+ arg_mode = de_inst.function_data['arg_mode'].split(",")
else:
arg_mode = ['i'] * len(
- session_function_data['args_type'].split(",")
+ de_inst.function_data['args_type'].split(",")
)
- if session_function_data['args_type']:
- if session_function_data['args_name']:
- arg_name = session_function_data['args_name'].split(",")
+ if de_inst.function_data['args_type']:
+ if de_inst.function_data['args_name']:
+ arg_name = de_inst.function_data['args_name'].split(",")
if '_retval_' in arg_name:
- arg_type = session_function_data[
+ arg_type = de_inst.function_data[
'args_type'].split(",")
arg_type.pop()
else:
- arg_type = session_function_data[
+ arg_type = de_inst.function_data[
'args_type'].split(",")
else:
- arg_type = session_function_data['args_type'].split(",")
+ arg_type = de_inst.function_data['args_type'].split(",")
# Below are two different template to execute and start executer
if manager.server_type != 'pg' and manager.version < 90300:
str_query = render_template(
"/".join(['debugger/sql', 'execute_edbspl.sql']),
func_name=func_name,
- is_func=session_function_data['is_func'],
- lan_name=session_function_data['language'],
- ret_type=session_function_data['return_type'],
- data=session_function_data['args_value'],
+ is_func=de_inst.function_data['is_func'],
+ lan_name=de_inst.function_data['language'],
+ ret_type=de_inst.function_data['return_type'],
+ data=de_inst.function_data['args_value'],
arg_type=arg_type,
args_mode=arg_mode
)
@@ -1083,10 +992,10 @@ def start_debugger_listener(trans_id):
str_query = render_template(
"/".join(['debugger/sql', 'execute_plpgsql.sql']),
func_name=func_name,
- is_func=session_function_data['is_func'],
- ret_type=session_function_data['return_type'],
- data=session_function_data['args_value'],
- is_ppas_database=session_function_data['is_ppas_database']
+ is_func=de_inst.function_data['is_func'],
+ ret_type=de_inst.function_data['return_type'],
+ data=de_inst.function_data['args_value'],
+ is_ppas_database=de_inst.function_data['is_ppas_database']
)
status, result = conn.execute_async(str_query)
@@ -1117,7 +1026,7 @@ def start_debugger_listener(trans_id):
sql = render_template(
"/".join([template_path, 'add_breakpoint_edb.sql']),
session_id=int_session_id,
- function_oid=obj['function_id']
+ function_oid=de_inst.debugger_data['function_id']
)
status, res = conn.execute_dict(sql)
@@ -1127,7 +1036,7 @@ def start_debugger_listener(trans_id):
sql = render_template(
"/".join([template_path, 'add_breakpoint_pg.sql']),
session_id=int_session_id,
- function_oid=obj['function_id']
+ function_oid=de_inst.debugger_data['function_id']
)
status, res = conn.execute_dict(sql)
@@ -1144,13 +1053,12 @@ def start_debugger_listener(trans_id):
if not status:
return internal_server_error(errormsg=res)
- debugger_data = session['debuggerData']
- session_obj = debugger_data[str(trans_id)]
- session_obj['exe_conn_id'] = obj['conn_id']
- session_obj['restart_debug'] = 1
- session_obj['frame_id'] = 0
- session_obj['session_id'] = int_session_id
- update_session_debugger_transaction(trans_id, session_obj)
+ de_inst.debugger_data['exe_conn_id'] = \
+ de_inst.debugger_data['conn_id']
+ de_inst.debugger_data['restart_debug'] = 1
+ de_inst.debugger_data['frame_id'] = 0
+ de_inst.debugger_data['session_id'] = int_session_id
+ de_inst.update_session()
return make_json_response(
data={'status': status, 'result': res}
)
@@ -1196,8 +1104,8 @@ def execute_debugger_query(trans_id, query_type):
- Type of query to execute
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+ de_inst = DebuggerInstance(trans_id)
+ if de_inst.debugger_data is None:
return make_json_response(
data={
'status': False,
@@ -1207,15 +1115,15 @@ def execute_debugger_query(trans_id, query_type):
)
}
)
- obj = debugger_data[str(trans_id)]
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+ de_inst.debugger_data['server_id'])
conn = manager.connection(
- did=obj['database_id'], conn_id=obj['exe_conn_id'])
+ did=de_inst.debugger_data['database_id'],
+ conn_id=de_inst.debugger_data['exe_conn_id'])
# find the debugger version and execute the query accordingly
- dbg_version = obj['debugger_version']
+ dbg_version = de_inst.debugger_data['debugger_version']
if dbg_version <= 2:
template_path = 'debugger/sql/v1'
else:
@@ -1224,7 +1132,7 @@ def execute_debugger_query(trans_id, query_type):
if conn.connected():
sql = render_template(
"/".join([template_path, query_type + ".sql"]),
- session_id=obj['session_id']
+ session_id=de_inst.debugger_data['session_id']
)
# As the query type is continue or step_into or step_over then we
# may get result after some time so poll the result.
@@ -1233,10 +1141,9 @@ def execute_debugger_query(trans_id, query_type):
if query_type == 'continue' or query_type == 'step_into' or \
query_type == 'step_over':
# We should set the frame_id to 0 when execution starts.
- if obj['frame_id'] != 0:
- session_obj = debugger_data[str(trans_id)]
- session_obj['frame_id'] = 0
- update_session_debugger_transaction(trans_id, session_obj)
+ if de_inst.debugger_data['frame_id'] != 0:
+ de_inst.debugger_data['frame_id'] = 0
+ de_inst.update_session()
status, result = conn.execute_async(sql)
if not status:
@@ -1282,8 +1189,8 @@ def messages(trans_id):
- unique transaction id.
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+ de_inst = DebuggerInstance(trans_id)
+ if de_inst.debugger_data is None:
return make_json_response(
data={
'status': 'NotConnected',
@@ -1293,11 +1200,12 @@ def messages(trans_id):
)
}
)
- obj = debugger_data[str(trans_id)]
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
- conn = manager.connection(did=obj['database_id'], conn_id=obj['conn_id'])
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+ de_inst.debugger_data['server_id'])
+ conn = manager.connection(
+ did=de_inst.debugger_data['database_id'],
+ conn_id=de_inst.debugger_data['conn_id'])
port_number = ''
@@ -1357,8 +1265,8 @@ def start_execution(trans_id, port_num):
- Port number to attach
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+ de_inst = DebuggerInstance(trans_id)
+ if de_inst.debugger_data is None:
return make_json_response(
data={
'status': 'NotConnected',
@@ -1368,16 +1276,15 @@ def start_execution(trans_id, port_num):
)
}
)
- obj = debugger_data[str(trans_id)]
-
- dbg_version = obj['debugger_version']
# Create asynchronous connection using random connection id.
exe_conn_id = str(random.randint(1, 9999999))
try:
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
- conn = manager.connection(did=obj['database_id'], conn_id=exe_conn_id)
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+ de_inst.debugger_data['server_id'])
+ conn = manager.connection(
+ did=de_inst.debugger_data['database_id'],
+ conn_id=exe_conn_id)
except Exception as e:
return internal_server_error(errormsg=str(e))
@@ -1386,13 +1293,8 @@ def start_execution(trans_id, port_num):
if not status:
return internal_server_error(errormsg=str(msg))
- if 'debuggerData' not in session:
- debugger_data = dict()
- else:
- debugger_data = session['debuggerData']
-
# find the debugger version and execute the query accordingly
- dbg_version = obj['debugger_version']
+ dbg_version = de_inst.debugger_data['debugger_version']
if dbg_version <= 2:
template_path = 'debugger/sql/v1'
else:
@@ -1405,13 +1307,13 @@ def start_execution(trans_id, port_num):
if not status_port:
return internal_server_error(errormsg=res_port)
- session_obj = debugger_data[str(trans_id)]
- session_obj['restart_debug'] = 0
- session_obj['frame_id'] = 0
- session_obj['exe_conn_id'] = exe_conn_id
- session_obj['debugger_version'] = dbg_version
- session_obj['session_id'] = res_port['rows'][0]['pldbg_attach_to_port']
- update_session_debugger_transaction(trans_id, session_obj)
+ de_inst.debugger_data['restart_debug'] = 0
+ de_inst.debugger_data['frame_id'] = 0
+ de_inst.debugger_data['exe_conn_id'] = exe_conn_id
+ de_inst.debugger_data['debugger_version'] = dbg_version
+ de_inst.debugger_data['session_id'] = \
+ res_port['rows'][0]['pldbg_attach_to_port']
+ de_inst.update_session()
return make_json_response(
data={
@@ -1441,8 +1343,9 @@ def set_clear_breakpoint(trans_id, line_no, set_type):
- 0 - clear the breakpoint, 1 - set the breakpoint
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+ de_inst = DebuggerInstance(trans_id)
+
+ if de_inst.debugger_data is None:
return make_json_response(
data={
'status': False,
@@ -1452,15 +1355,15 @@ def set_clear_breakpoint(trans_id, line_no, set_type):
)
}
)
- obj = debugger_data[str(trans_id)]
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+ de_inst.debugger_data['server_id'])
conn = manager.connection(
- did=obj['database_id'], conn_id=obj['exe_conn_id'])
+ did=de_inst.debugger_data['database_id'],
+ conn_id=de_inst.debugger_data['exe_conn_id'])
# find the debugger version and execute the query accordingly
- dbg_version = obj['debugger_version']
+ dbg_version = de_inst.debugger_data['debugger_version']
if dbg_version <= 2:
template_path = 'debugger/sql/v1'
else:
@@ -1474,7 +1377,7 @@ def set_clear_breakpoint(trans_id, line_no, set_type):
# session variable and pass tha appropriate foid to set the breakpoint.
sql_ = render_template(
"/".join([template_path, "get_stack_info.sql"]),
- session_id=obj['session_id']
+ session_id=de_inst.debugger_data['session_id']
)
status, res_stack = conn.execute_dict(sql_)
if not status:
@@ -1483,7 +1386,7 @@ def set_clear_breakpoint(trans_id, line_no, set_type):
# For multilevel function debugging, we need to fetch current selected
# frame's function oid for setting the breakpoint. For single function
# the frame id will be 0.
- foid = res_stack['rows'][obj['frame_id']]['func']
+ foid = res_stack['rows'][de_inst.debugger_data['frame_id']]['func']
# Check the result of the stack before setting the breakpoint
if conn.connected():
@@ -1494,7 +1397,7 @@ def set_clear_breakpoint(trans_id, line_no, set_type):
sql = render_template(
"/".join([template_path, query_type + ".sql"]),
- session_id=obj['session_id'],
+ session_id=de_inst.debugger_data['session_id'],
foid=foid, line_number=line_no
)
@@ -1528,8 +1431,9 @@ def clear_all_breakpoint(trans_id):
trans_id
- Transaction ID
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+
+ de_inst = DebuggerInstance(trans_id)
+ if de_inst.debugger_data is None:
return make_json_response(
data={
'status': False,
@@ -1539,22 +1443,19 @@ def clear_all_breakpoint(trans_id):
)
}
)
- obj = debugger_data[str(trans_id)]
-
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+ de_inst.debugger_data['server_id'])
conn = manager.connection(
- did=obj['database_id'], conn_id=obj['exe_conn_id'])
+ did=de_inst.debugger_data['database_id'],
+ conn_id=de_inst.debugger_data['exe_conn_id'])
# find the debugger version and execute the query accordingly
- dbg_version = obj['debugger_version']
+ dbg_version = de_inst.debugger_data['debugger_version']
if dbg_version <= 2:
template_path = 'debugger/sql/v1'
else:
template_path = 'debugger/sql/v2'
- query_type = ''
-
if conn.connected():
# get the data sent through post from client
if request.form['breakpoint_list']:
@@ -1562,8 +1463,9 @@ def clear_all_breakpoint(trans_id):
for line_no in line_numbers:
sql = render_template(
"/".join([template_path, "clear_breakpoint.sql"]),
- session_id=obj['session_id'],
- foid=obj['function_id'], line_number=line_no
+ session_id=de_inst.debugger_data['session_id'],
+ foid=de_inst.debugger_data['function_id'],
+ line_number=line_no
)
status, result = conn.execute_dict(sql)
@@ -1597,8 +1499,9 @@ def deposit_parameter_value(trans_id):
trans_id
- Transaction ID
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+
+ de_inst = DebuggerInstance(trans_id)
+ if de_inst.debugger_data is None:
return make_json_response(
data={
'status': False,
@@ -1606,22 +1509,19 @@ def deposit_parameter_value(trans_id):
'with the server has been closed.')
}
)
- obj = debugger_data[str(trans_id)]
-
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+ de_inst.debugger_data['server_id'])
conn = manager.connection(
- did=obj['database_id'], conn_id=obj['exe_conn_id'])
+ did=de_inst.debugger_data['database_id'],
+ conn_id=de_inst.debugger_data['exe_conn_id'])
# find the debugger version and execute the query accordingly
- dbg_version = obj['debugger_version']
+ dbg_version = de_inst.debugger_data['debugger_version']
if dbg_version <= 2:
template_path = 'debugger/sql/v1'
else:
template_path = 'debugger/sql/v2'
- query_type = ''
-
if conn.connected():
# get the data sent through post from client
data = json.loads(request.values['data'], encoding='utf-8')
@@ -1629,7 +1529,7 @@ def deposit_parameter_value(trans_id):
if data:
sql = render_template(
"/".join([template_path, "deposit_value.sql"]),
- session_id=obj['session_id'],
+ session_id=de_inst.debugger_data['session_id'],
var_name=data[0]['name'], line_number=-1,
val=data[0]['value']
)
@@ -1678,8 +1578,8 @@ def select_frame(trans_id, frame_id):
frame_id
- Frame id selected
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+ de_inst = DebuggerInstance(trans_id)
+ if de_inst.debugger_data is None:
return make_json_response(
data={
'status': False,
@@ -1689,28 +1589,27 @@ def select_frame(trans_id, frame_id):
)
}
)
- obj = debugger_data[str(trans_id)]
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+ de_inst.debugger_data['server_id'])
conn = manager.connection(
- did=obj['database_id'], conn_id=obj['exe_conn_id'])
+ did=de_inst.debugger_data['database_id'],
+ conn_id=de_inst.debugger_data['exe_conn_id'])
# find the debugger version and execute the query accordingly
- dbg_version = obj['debugger_version']
+ dbg_version = de_inst.debugger_data['debugger_version']
if dbg_version <= 2:
template_path = 'debugger/sql/v1'
else:
template_path = 'debugger/sql/v2'
- session_obj = debugger_data[str(trans_id)]
- session_obj['frame_id'] = frame_id
- update_session_debugger_transaction(trans_id, session_obj)
+ de_inst.debugger_data['frame_id'] = frame_id
+ de_inst.update_session()
if conn.connected():
sql = render_template(
"/".join([template_path, "select_frame.sql"]),
- session_id=obj['session_id'],
+ session_id=de_inst.debugger_data['session_id'],
frame_id=frame_id
)
@@ -1950,8 +1849,8 @@ def poll_end_execution_result(trans_id):
- unique transaction id.
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+ de_inst = DebuggerInstance(trans_id)
+ if de_inst.debugger_data is None:
return make_json_response(
data={'status': 'NotConnected',
'result': gettext(
@@ -1959,11 +1858,12 @@ def poll_end_execution_result(trans_id):
'server has been closed.')
}
)
- obj = debugger_data[str(trans_id)]
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
- conn = manager.connection(did=obj['database_id'], conn_id=obj['conn_id'])
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+ de_inst.debugger_data['server_id'])
+ conn = manager.connection(
+ did=de_inst.debugger_data['database_id'],
+ conn_id=de_inst.debugger_data['conn_id'])
if conn.connected():
statusmsg = conn.status_message()
@@ -1980,11 +1880,10 @@ def poll_end_execution_result(trans_id):
}
)
- session_function_data = session['functionData'][str(trans_id)]
if status == ASYNC_OK and \
- not session_function_data['is_func'] and\
- (session_function_data['language'] == 'edbspl' or
- session_function_data['language'] == 'plpgsql'):
+ not de_inst.function_data['is_func'] and\
+ (de_inst.function_data['language'] == 'edbspl' or
+ de_inst.function_data['language'] == 'plpgsql'):
status = 'Success'
additional_msgs = conn.messages()
if len(additional_msgs) > 0:
@@ -2077,8 +1976,8 @@ def poll_result(trans_id):
- unique transaction id.
"""
- debugger_data = session['debuggerData']
- if str(trans_id) not in debugger_data:
+ de_inst = DebuggerInstance(trans_id)
+ if de_inst.debugger_data is None:
return make_json_response(
data={
'status': 'NotConnected',
@@ -2086,12 +1985,12 @@ def poll_result(trans_id):
'with the server has been closed.')
}
)
- obj = debugger_data[str(trans_id)]
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(obj['server_id'])
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+ de_inst.debugger_data['server_id'])
conn = manager.connection(
- did=obj['database_id'], conn_id=obj['exe_conn_id'])
+ did=de_inst.debugger_data['database_id'],
+ conn_id=de_inst.debugger_data['exe_conn_id'])
if conn.connected():
status, result = conn.poll()
@@ -2117,7 +2016,7 @@ def poll_result(trans_id):
)
-def close_debugger_session(trans_id):
+def close_debugger_session(_trans_id, close_all=False):
"""
This function is used to cancel the debugger transaction and
release the connection.
@@ -2125,21 +2024,41 @@ def close_debugger_session(trans_id):
:param trans_id: Transaction id
:return:
"""
- dbg_obj = session['debuggerData'][str(trans_id)]
- manager = get_driver(
- PG_DEFAULT_DRIVER).connection_manager(dbg_obj['server_id'])
+ if close_all:
+ trans_ids = DebuggerInstance.get_trans_ids()
+ else:
+ trans_ids = [_trans_id]
- if manager is not None:
- conn = manager.connection(
- did=dbg_obj['database_id'], conn_id=dbg_obj['conn_id'])
- if conn.connected():
- conn.cancel_transaction(dbg_obj['conn_id'],
- dbg_obj['database_id'])
- conn = manager.connection(
- did=dbg_obj['database_id'], conn_id=dbg_obj['exe_conn_id'])
- if conn.connected():
- conn.cancel_transaction(dbg_obj['exe_conn_id'],
- dbg_obj['database_id'])
- manager.release(conn_id=dbg_obj['conn_id'])
- manager.release(conn_id=dbg_obj['exe_conn_id'])
+ for trans_id in trans_ids:
+ de_inst = DebuggerInstance(trans_id)
+ dbg_obj = de_inst.debugger_data
+
+ try:
+ if dbg_obj is not None:
+ manager = get_driver(PG_DEFAULT_DRIVER).\
+ connection_manager(dbg_obj['server_id'])
+
+ if manager is not None:
+ conn = manager.connection(
+ did=dbg_obj['database_id'],
+ conn_id=dbg_obj['conn_id'])
+ if conn.connected():
+ conn.cancel_transaction(
+ dbg_obj['conn_id'],
+ dbg_obj['database_id'])
+ manager.release(conn_id=dbg_obj['conn_id'])
+
+ if 'exe_conn_id' in dbg_obj:
+ conn = manager.connection(
+ did=dbg_obj['database_id'],
+ conn_id=dbg_obj['exe_conn_id'])
+ if conn.connected():
+ conn.cancel_transaction(
+ dbg_obj['exe_conn_id'],
+ dbg_obj['database_id'])
+ manager.release(conn_id=dbg_obj['exe_conn_id'])
+ except Exception as _:
+ raise
+ finally:
+ de_inst.clear()
diff --git a/web/pgadmin/tools/debugger/static/js/debugger.js b/web/pgadmin/tools/debugger/static/js/debugger.js
index 2ee1d55c..a2149bf1 100644
--- a/web/pgadmin/tools/debugger/static/js/debugger.js
+++ b/web/pgadmin/tools/debugger/static/js/debugger.js
@@ -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,
diff --git a/web/pgadmin/tools/debugger/static/js/debugger_ui.js b/web/pgadmin/tools/debugger/static/js/debugger_ui.js
index 46d34eed..f05a22dc 100644
--- a/web/pgadmin/tools/debugger/static/js/debugger_ui.js
+++ b/web/pgadmin/tools/debugger/static/js/debugger_ui.js
@@ -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);
};
diff --git a/web/pgadmin/tools/debugger/static/js/debugger_utils.js b/web/pgadmin/tools/debugger/static/js/debugger_utils.js
index a3529d84..282acb01 100644
--- a/web/pgadmin/tools/debugger/static/js/debugger_utils.js
+++ b/web/pgadmin/tools/debugger/static/js/debugger_utils.js
@@ -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,
};
diff --git a/web/pgadmin/tools/debugger/utils/debugger_instance.py b/web/pgadmin/tools/debugger/utils/debugger_instance.py
new file mode 100644
index 00000000..d16021e1
--- /dev/null
+++ b/web/pgadmin/tools/debugger/utils/debugger_instance.py
@@ -0,0 +1,72 @@
+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))
view thread (8+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected]
Subject: Re: [pgAdmin][RM4329] Initialization error when parameterised functions debugged in parallel in two separate tabs
In-Reply-To: <CAM9w-_mkawLvUPZP0Y+KRbJ=5NoRKou67PG9UESdQYtktKEzbQ@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox