diff --git a/docs/en_US/release_notes_4_25.rst b/docs/en_US/release_notes_4_25.rst index 8c28e677d..ac57b0e2a 100644 --- a/docs/en_US/release_notes_4_25.rst +++ b/docs/en_US/release_notes_4_25.rst @@ -26,6 +26,7 @@ Bug fixes | `Issue #3767 `_ - Ensure that the original file format should be retained when saving the same file in SQL editor. | `Issue #3791 `_ - Added missing comments in reverse engineering SQL for each column of a View. +| `Issue #4123 `_ - Fixed an issue where debugger doesn't work if the search path is set other than 'public'. | `Issue #4361 `_ - Fixed ssh tunnel hang issue when the user tries to disconnect the server. | `Issue #4387 `_ - Fixed an issue where the user is not able to insert the data if the table and columns name contains special characters. | `Issue #4810 `_ - Fixed an issue where the user is not able to save the new row if the table is empty. diff --git a/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py index 5270c4af4..cb52ba5aa 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py @@ -20,6 +20,8 @@ from pgadmin.browser.utils import PGChildNodeView from pgadmin.utils.ajax import make_json_response, \ make_response as ajax_response, internal_server_error, gone from pgadmin.utils.driver import get_driver +from pgadmin.browser.server_groups.servers.databases.extensions.utils \ + import get_extension_details from config import PG_DEFAULT_DRIVER from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry from pgadmin.tools.schema_diff.compare import SchemaDiffObjectCompare @@ -90,6 +92,7 @@ class ExtensionView(PGChildNodeView, SchemaDiffObjectCompare): * ids - id with type and name of extension module being used. * operations - function routes mappings defined. """ + EXT_TEMPLATE_PATH = 'extensions/sql' node_type = blueprint.node_type parent_ids = [ @@ -133,7 +136,7 @@ class ExtensionView(PGChildNodeView, SchemaDiffObjectCompare): PG_DEFAULT_DRIVER ).connection_manager(kwargs['sid']) self.conn = self.manager.connection(did=kwargs['did']) - self.template_path = 'extensions/sql' + self.template_path = self.EXT_TEMPLATE_PATH self.datlastsysoid = \ self.manager.db_info[kwargs['did']]['datlastsysoid'] \ @@ -281,26 +284,21 @@ class ExtensionView(PGChildNodeView, SchemaDiffObjectCompare): if not status: return internal_server_error(errormsg=res) - status, rset = self.conn.execute_dict( - render_template( - "/".join([self.template_path, self._PROPERTIES_SQL]), - ename=data['name'] + status, res = get_extension_details( + self.conn, data['name'], + "/".join([self.template_path, self._PROPERTIES_SQL])) + if not status: + return internal_server_error(errormsg=res) + + return jsonify( + node=self.blueprint.generate_browser_node( + res['oid'], + did, + res['name'], + 'icon-extension' ) ) - if not status: - return internal_server_error(errormsg=rset) - - for row in rset['rows']: - return jsonify( - node=self.blueprint.generate_browser_node( - row['oid'], - did, - row['name'], - 'icon-extension' - ) - ) - @check_precondition def update(self, gid, sid, did, eid): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/extensions/utils.py b/web/pgadmin/browser/server_groups/servers/databases/extensions/utils.py new file mode 100644 index 000000000..b4dab314d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/extensions/utils.py @@ -0,0 +1,37 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2020, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + +""" Utility for Extension Node """ + +from flask import render_template + + +def get_extension_details(conn, ename, properties_sql=None): + """ + This function is used to get the extension details. + :param conn: + :param ename: + :param properties_sql: + :return: + """ + if properties_sql is None: + from pgadmin.browser.server_groups.servers.databases.extensions \ + import ExtensionView + + properties_sql = "/".join( + [ExtensionView.EXT_TEMPLATE_PATH, 'properties.sql']) + + status, rset = conn.execute_dict( + render_template(properties_sql, ename=ename) + ) + + if status: + return True, rset['rows'][0] + + return status, rset diff --git a/web/pgadmin/tools/debugger/__init__.py b/web/pgadmin/tools/debugger/__init__.py index 3209e4f0a..42097e36e 100644 --- a/web/pgadmin/tools/debugger/__init__.py +++ b/web/pgadmin/tools/debugger/__init__.py @@ -31,14 +31,17 @@ 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 +from pgadmin.browser.server_groups.servers.databases.extensions.utils \ + import get_extension_details MODULE_NAME = 'debugger' # Constants +PLDBG_EXTN = 'pldbgapi' ASYNC_OK = 1 DEBUGGER_SQL_PATH = 'debugger/sql' DEBUGGER_SQL_V1_PATH = 'debugger/sql/v1' -DEBUGGER_SQL_V2_PATH = 'debugger/sql/v2' +DEBUGGER_SQL_V3_PATH = 'debugger/sql/v3' class DebuggerModule(PgAdminModule): @@ -304,6 +307,18 @@ def script_debugger_direct_js(): ) +def execute_dict_search_path(conn, sql, search_path): + sql = "SET search_path={0};".format(search_path) + sql + status, res = conn.execute_dict(sql) + return status, res + + +def execute_async_search_path(conn, sql, search_path): + sql = "SET search_path={0};".format(search_path) + sql + status, res = conn.execute_async(sql) + return status, res + + @blueprint.route( '/init/////', methods=['GET'], endpoint='init_for_function' @@ -606,7 +621,7 @@ def direct_new(trans_id): ) -def get_debugger_version(conn): +def get_debugger_version(conn, search_path): """ Function returns the debugger version. :param conn: @@ -614,23 +629,24 @@ def get_debugger_version(conn): """ debugger_version = 0 status, rid = conn.execute_scalar( + "SET search_path={0};" "SELECT COUNT(*) FROM pg_catalog.pg_proc p" " LEFT JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid" " WHERE n.nspname = ANY(current_schemas(false)) AND" - " p.proname = 'pldbg_get_proxy_info';" + " p.proname = 'pldbg_get_proxy_info';".format(search_path) ) if not status: return False, internal_server_error(errormsg=rid) - if rid == 0: + if int(rid) == 0: debugger_version = 1 + else: + status, rid = conn.execute_scalar( + "SELECT proxyapiver FROM pldbg_get_proxy_info();") - status, rid = conn.execute_scalar( - "SELECT proxyapiver FROM pldbg_get_proxy_info();") - - if status and rid in (2, 3): - debugger_version = rid + if status and rid in (2, 3): + debugger_version = rid return True, debugger_version @@ -687,6 +703,20 @@ def validate_debug(conn, debug_type, is_superuser): return True, None +def get_search_path(conn): + status, res = get_extension_details(conn, PLDBG_EXTN) + if not status: + return False, internal_server_error(errormsg=res) + + status, res = conn.execute_scalar( + "SELECT current_setting('search_path')||',{0}'".format(res['schema'])) + + if not status: + return False, internal_server_error(errormsg=res) + + return True, res + + @blueprint.route( '/initialize_target/////' '/', @@ -752,8 +782,12 @@ def initialize_target(debug_type, trans_id, sid, did, func_id = tr_set['rows'][0]['tgfoid'] + status, search_path = get_search_path(conn) + if not status: + return search_path + # Find out the debugger version and store it in session variables - status, debugger_version = get_debugger_version(conn) + status, debugger_version = get_debugger_version(conn, search_path) if not status: return debugger_version @@ -783,6 +817,7 @@ def initialize_target(debug_type, trans_id, sid, did, 'function_name': de_inst.function_data['name'], 'debug_type': debug_type, 'debugger_version': debugger_version, + 'search_path': search_path, 'frame_id': 0, 'restart_debug': 0 } @@ -926,7 +961,7 @@ def start_debugger_listener(trans_id): if dbg_version <= 2: template_path = DEBUGGER_SQL_V1_PATH else: - template_path = DEBUGGER_SQL_V2_PATH + template_path = DEBUGGER_SQL_V3_PATH # If user again start the same debug function with different arguments # then we need to save that values to session variable and database. @@ -973,7 +1008,8 @@ def start_debugger_listener(trans_id): packge_oid=de_inst.function_data['pkg'], function_oid=de_inst.debugger_data['function_id'] ) - status, res = conn.execute_dict(sql) + status, res = execute_dict_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=res) @@ -1031,7 +1067,8 @@ def start_debugger_listener(trans_id): is_ppas_database=de_inst.function_data['is_ppas_database'] ) - status, result = conn.execute_async(str_query) + status, result = execute_async_search_path( + conn, str_query, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=result) else: @@ -1041,7 +1078,8 @@ def start_debugger_listener(trans_id): sql = render_template( "/".join([template_path, 'create_listener.sql'])) - status, res = conn.execute_dict(sql) + status, res = execute_dict_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=res) @@ -1062,7 +1100,8 @@ def start_debugger_listener(trans_id): function_oid=de_inst.debugger_data['function_id'] ) - status, res = conn.execute_dict(sql) + status, res = execute_dict_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=res) else: @@ -1072,7 +1111,8 @@ def start_debugger_listener(trans_id): function_oid=de_inst.debugger_data['function_id'] ) - status, res = conn.execute_dict(sql) + status, res = execute_dict_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=res) @@ -1082,7 +1122,8 @@ def start_debugger_listener(trans_id): session_id=int_session_id ) - status, res = conn.execute_async(sql) + status, res = execute_async_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=res) @@ -1158,7 +1199,7 @@ def execute_debugger_query(trans_id, query_type): # find the debugger version and execute the query accordingly template_path = DEBUGGER_SQL_V1_PATH \ if de_inst.debugger_data['debugger_version'] <= 2 \ - else DEBUGGER_SQL_V2_PATH + else DEBUGGER_SQL_V3_PATH if not conn.connected(): result = gettext('Not connected to server or connection ' @@ -1178,14 +1219,16 @@ def execute_debugger_query(trans_id, query_type): de_inst.debugger_data['frame_id'] = 0 de_inst.update_session() - status, result = conn.execute_async(sql) + status, result = execute_async_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=result) return make_json_response( data={'status': status, 'result': result} ) - status, result = conn.execute_dict(sql) + status, result = execute_dict_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=result) if query_type == 'abort_target': @@ -1317,12 +1360,13 @@ def start_execution(trans_id, port_num): if dbg_version <= 2: template_path = DEBUGGER_SQL_V1_PATH else: - template_path = DEBUGGER_SQL_V2_PATH + template_path = DEBUGGER_SQL_V3_PATH # connect to port and store the session ID in the session variables sql = render_template( "/".join([template_path, 'attach_to_port.sql']), port=port_num) - status_port, res_port = conn.execute_dict(sql) + status_port, res_port = execute_dict_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status_port: return internal_server_error(errormsg=res_port) @@ -1386,7 +1430,7 @@ def set_clear_breakpoint(trans_id, line_no, set_type): if dbg_version <= 2: template_path = DEBUGGER_SQL_V1_PATH else: - template_path = DEBUGGER_SQL_V2_PATH + template_path = DEBUGGER_SQL_V3_PATH query_type = '' @@ -1398,7 +1442,8 @@ def set_clear_breakpoint(trans_id, line_no, set_type): "/".join([template_path, "get_stack_info.sql"]), session_id=de_inst.debugger_data['session_id'] ) - status, res_stack = conn.execute_dict(sql_) + status, res_stack = execute_dict_search_path( + conn, sql_, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=res_stack) @@ -1420,7 +1465,8 @@ def set_clear_breakpoint(trans_id, line_no, set_type): foid=foid, line_number=line_no ) - status, result = conn.execute_dict(sql) + status, result = execute_dict_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=result) else: @@ -1473,7 +1519,7 @@ def clear_all_breakpoint(trans_id): if dbg_version <= 2: template_path = DEBUGGER_SQL_V1_PATH else: - template_path = DEBUGGER_SQL_V2_PATH + template_path = DEBUGGER_SQL_V3_PATH if conn.connected(): # get the data sent through post from client @@ -1487,7 +1533,8 @@ def clear_all_breakpoint(trans_id): line_number=line_no ) - status, result = conn.execute_dict(sql) + status, result = execute_dict_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=result) else: @@ -1539,7 +1586,7 @@ def deposit_parameter_value(trans_id): if dbg_version <= 2: template_path = DEBUGGER_SQL_V1_PATH else: - template_path = DEBUGGER_SQL_V2_PATH + template_path = DEBUGGER_SQL_V3_PATH if conn.connected(): # get the data sent through post from client @@ -1553,7 +1600,8 @@ def deposit_parameter_value(trans_id): val=data[0]['value'] ) - status, result = conn.execute_dict(sql) + status, result = execute_dict_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=result) @@ -1620,7 +1668,7 @@ def select_frame(trans_id, frame_id): if dbg_version <= 2: template_path = DEBUGGER_SQL_V1_PATH else: - template_path = DEBUGGER_SQL_V2_PATH + template_path = DEBUGGER_SQL_V3_PATH de_inst.debugger_data['frame_id'] = frame_id de_inst.update_session() @@ -1632,7 +1680,8 @@ def select_frame(trans_id, frame_id): frame_id=frame_id ) - status, result = conn.execute_dict(sql) + status, result = execute_dict_search_path( + conn, sql, de_inst.debugger_data['search_path']) if not status: return internal_server_error(errormsg=result) else: diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/abort_target.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/abort_target.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/abort_target.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/abort_target.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/add_breakpoint_edb.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/add_breakpoint_edb.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/add_breakpoint_edb.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/add_breakpoint_edb.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/add_breakpoint_pg.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/add_breakpoint_pg.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/add_breakpoint_pg.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/add_breakpoint_pg.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/attach_to_port.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/attach_to_port.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/attach_to_port.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/attach_to_port.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/clear_breakpoint.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/clear_breakpoint.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/clear_breakpoint.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/clear_breakpoint.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/continue.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/continue.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/continue.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/continue.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/create_listener.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/create_listener.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/create_listener.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/create_listener.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/debug_plpgsql_execute_target.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/debug_plpgsql_execute_target.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/debug_plpgsql_execute_target.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/debug_plpgsql_execute_target.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/debug_plpgsql_init.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/debug_plpgsql_init.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/debug_plpgsql_init.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/debug_plpgsql_init.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/debug_spl_execute_target.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/debug_spl_execute_target.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/debug_spl_execute_target.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/debug_spl_execute_target.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/debug_spl_init.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/debug_spl_init.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/debug_spl_init.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/debug_spl_init.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/deposit_value.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/deposit_value.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/deposit_value.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/deposit_value.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/get_breakpoints.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/get_breakpoints.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/get_breakpoints.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/get_breakpoints.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/get_function_info.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/get_function_info.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/get_function_info.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/get_function_info.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/get_stack_info.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/get_stack_info.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/get_stack_info.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/get_stack_info.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/get_variables.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/get_variables.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/get_variables.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/get_variables.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/select_frame.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/select_frame.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/select_frame.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/select_frame.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/set_breakpoint.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/set_breakpoint.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/set_breakpoint.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/set_breakpoint.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/step_into.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/step_into.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/step_into.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/step_into.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/step_over.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/step_over.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/step_over.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/step_over.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/wait_for_breakpoint.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/wait_for_breakpoint.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/wait_for_breakpoint.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/wait_for_breakpoint.sql diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/v2/wait_for_target.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/v3/wait_for_target.sql similarity index 100% rename from web/pgadmin/tools/debugger/templates/debugger/sql/v2/wait_for_target.sql rename to web/pgadmin/tools/debugger/templates/debugger/sql/v3/wait_for_target.sql