def _connect_and_respond(self, request_context: RequestContext, params: ConnectRequestParams) -> None: """Open a connection and fire the connection complete notification""" response = self.connect(params) # Send the connection complete response unless the connection was canceled if response is not None: request_context.send_notification(CONNECTION_COMPLETE_METHOD, response)
def _expand_node_error(self, request_context: RequestContext, params: ExpandParameters, message: str): if self._service_provider.logger is not None: self._service_provider.logger.warning(f'OE service errored while expanding node: {message}') response = ExpandCompletedParameters(params.session_id, params.node_path) response.error_message = f'Failed to expand node: {message}' # TODO: Localize request_context.send_notification(EXPAND_COMPLETED_METHOD, response)
def _expand_node_thread(self, is_refresh: bool, request_context: RequestContext, params: ExpandParameters, session: ObjectExplorerSession): try: response = ExpandCompletedParameters(session.id, params.node_path) response.nodes = route_request(is_refresh, session, params.node_path) request_context.send_notification(EXPAND_COMPLETED_METHOD, response) except Exception as e: self._expand_node_error(request_context, params, str(e))
def _session_created_error(self, request_context: RequestContext, session: ObjectExplorerSession, message: str): if self._service_provider.logger is not None: self._service_provider.logger.warning(f'OE service errored while creating session: {message}') # Create error notification response = SessionCreatedParameters() response.success = False response.session_id = session.id response.root_node = None response.error_message = message request_context.send_notification(SESSION_CREATED_METHOD, response) # Clean up the session from the session map self._session_map.pop(session.id)
def _initialize_session(self, request_context: RequestContext, session: ObjectExplorerSession): conn_service = self._service_provider[utils.constants.CONNECTION_SERVICE_NAME] connection = None try: # Step 1: Connect with the provided connection details connect_request = ConnectRequestParams( session.connection_details, session.id, ConnectionType.OBJECT_EXLPORER ) connect_result = conn_service.connect(connect_request) if connect_result is None: raise RuntimeError('Connection was cancelled during connect') # TODO Localize if connect_result.error_message is not None: raise RuntimeError(connect_result.error_message) # Step 2: Get the connection to use for object explorer connection = conn_service.get_connection(session.id, ConnectionType.OBJECT_EXLPORER) # Step 3: Create the PGSMO Server object for the session and create the root node for the server session.server = Server(connection, functools.partial(self._create_connection, session)) metadata = ObjectMetadata(session.server.urn_base, None, 'Database', session.server.maintenance_db_name) node = NodeInfo() node.label = session.connection_details.options['dbname'] node.is_leaf = False node.node_path = session.id node.node_type = 'Database' node.metadata = metadata # Step 4: Send the completion notification to the server response = SessionCreatedParameters() response.success = True response.session_id = session.id response.root_node = node response.error_message = None request_context.send_notification(SESSION_CREATED_METHOD, response) # Mark the session as complete session.is_ready = True except Exception as e: # Return a notification that an error occurred message = f'Failed to initialize object explorer session: {str(e)}' # TODO Localize self._session_created_error(request_context, session, message) # Attempt to clean up the connection if connection is not None: conn_service.disconnect(session.id, ConnectionType.OBJECT_EXLPORER)
def handle_definition_request( self, request_context: RequestContext, text_document_position: TextDocumentPosition) -> None: request_context.send_notification( STATUS_CHANGE_NOTIFICATION, StatusChangeParams( owner_uri=text_document_position.text_document.uri, status="DefinitionRequested")) def do_send_default_empty_response(): request_context.send_response([]) if self.should_skip_intellisense( text_document_position.text_document.uri): do_send_default_empty_response() return script_file: ScriptFile = self._workspace_service.workspace.get_file( text_document_position.text_document.uri) if script_file is None: do_send_default_empty_response() return script_parse_info: ScriptParseInfo = self.get_script_parse_info( text_document_position.text_document.uri, create_if_not_exists=False) if not script_parse_info or not script_parse_info.can_queue(): do_send_default_empty_response() return cursor_position: int = len( script_file.get_text_in_range( Range.from_data(0, 0, text_document_position.position.line, text_document_position.position.character))) text: str = script_file.get_all_text() script_parse_info.document = Document(text, cursor_position) operation = QueuedOperation( script_parse_info.connection_key, functools.partial(self.send_definition_using_connected_completions, request_context, script_parse_info, text_document_position), functools.partial(do_send_default_empty_response)) self.operations_queue.add_operation(operation) request_context.send_notification( STATUS_CHANGE_NOTIFICATION, StatusChangeParams( owner_uri=text_document_position.text_document.uri, status="DefinitionRequestCompleted"))
def _resolve_query_exception(self, e: Exception, query: Query, request_context: RequestContext, conn: 'psycopg2.connection', is_rollback_error=False): utils.log.log_debug( self._service_provider.logger, f'Query execution failed for following query: {query.query_text}\n {e}' ) if isinstance(e, psycopg2.DatabaseError) or isinstance( e, RuntimeError) or isinstance( e, psycopg2.extensions.QueryCanceledError): error_message = str(e) else: error_message = 'Unhandled exception while executing query: {}'.format( str(e)) # TODO: Localize if self._service_provider.logger is not None: self._service_provider.logger.exception( 'Unhandled exception while executing query') # If the error occured during rollback, add a note about it if is_rollback_error: error_message = 'Error while rolling back open transaction due to previous failure: ' + error_message # TODO: Localize # Send a message with the error to the client result_message_params = self.build_message_params( query.owner_uri, query.batches[query.current_batch_index].id, error_message, True) request_context.send_notification(MESSAGE_NOTIFICATION, result_message_params) # If there was a failure in the middle of a transaction, roll it back. # Note that conn.rollback() won't work since the connection is in autocommit mode if not is_rollback_error and conn.get_transaction_status( ) is psycopg2.extensions.TRANSACTION_STATUS_INERROR: rollback_query = Query( query.owner_uri, 'ROLLBACK', QueryExecutionSettings(ExecutionPlanOptions(), None), QueryEvents()) try: rollback_query.execute(conn) except Exception as rollback_exception: # If the rollback failed, handle the error as usual but don't try to roll back again self._resolve_query_exception(rollback_exception, rollback_query, request_context, conn, True)