예제 #1
0
    def refresh(self, callbacks, history=None, settings=None) -> str:
        """
        Creates a PGCompleter object and populates it with the relevant
        completion suggestions in a background thread.

        settings - dict of settings for completer object
        callbacks - A function or a list of functions to call after the thread
                    has completed the refresh. The newly created completion
                    object will be passed in as an argument to each callback.
        """
        if self.server is None:
            # Delay server creation until on background thread
            self.server = Server(self.connection)

        if self.is_refreshing():
            self._restart_refresh.set()
            return 'Auto-completion refresh restarted.'
        else:
            self._completer_thread = threading.Thread(
                target=self._bg_refresh,
                args=(callbacks, history, settings),
                name='completion_refresh')
            self._completer_thread.daemon = True
            self._completer_thread.start()
            return 'Auto-completion refresh started in the background.'  # TODO localize
 def setUp(self):
     mock_server = Server(utils.MockPGServerConnection())
     db = Database(mock_server, mock_server.maintenance_db_name)
     mock_server._child_objects[
         Database.__name__] = self._as_node_collection([db])
     mock_server._search_path = self._as_node_collection([MYSCHEMA])
     self.schema1 = Schema(mock_server, db, MYSCHEMA)
     self.schema2 = Schema(mock_server, db, MYSCHEMA2)
     db._schemas = self._as_node_collection([self.schema1, self.schema2])
     self.mock_server = mock_server
     self.executor: MetadataExecutor = MetadataExecutor(mock_server)
    def get(self, connection: 'psycopg2.extensions.connection',
            schema_name: str, object_name: str,
            object_type: str) -> EditTableMetadata:

        server = Server(connection)
        result_object: Table = None
        object_metadata = ObjectMetadata(server.urn_base, None, object_type,
                                         object_name, schema_name)

        if object_type.lower() == 'table':
            result_object = object_finder.find_table(server, object_metadata)
        elif object_type.lower() == 'view':
            result_object = object_finder.find_view(server, object_metadata)
        else:
            raise ValueError('Not supported object type')

        edit_columns_metadata: List[EditColumnMetadata] = []

        for column in result_object.columns:
            db_column = self.create_db_column(column)
            edit_columns_metadata.append(
                EditColumnMetadata(db_column, column.default_value))

        return EditTableMetadata(schema_name, object_name,
                                 edit_columns_metadata)
    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 setUp(self):
     self._smo_metadata_factory = SmoEditTableMetadataFactory()
     self._connection = MockPGServerConnection(cur=None,
                                               port="8080",
                                               host="test",
                                               name="test",
                                               user="******")
     self._server = Server(self._connection)
     self._schema_name = 'public'
     self._table_name = 'Employee'
     self._view_name = 'Vendor'
     self._table_object_type = 'TABLE'
     self._view_object_type = 'VIEW'
     self._columns = [
         Column(self._server, "testTable", 'testName', 'testDatatype')
     ]
 def setUp(self):
     self._smo_metadata_factory = SmoEditTableMetadataFactory()
     self._connection = MockConnection({
         "port": "8080",
         "host": "test",
         "dbname": "test",
         "user": "******"
     })
     self._server = Server(self._connection)
     self._schema_name = 'public'
     self._table_name = 'Employee'
     self._view_name = 'Vendor'
     self._table_object_type = 'TABLE'
     self._view_object_type = 'VIEW'
     self._columns = [
         Column(self._server, "testTable", 'testName', 'testDatatype')
     ]
    def test_tables(self):
        # Given 2 tables in the database
        expected_table_tuples = []
        for x in range(0, 3):
            s1_table_name = 's1_t%s' % x
            s2_table_name = 's2_t%s' % x
            expected_table_tuples.append(
                tuple([self.schema1.name, s1_table_name]))
            expected_table_tuples.append(
                tuple([self.schema2.name, s2_table_name]))

        cursor = MockCursor(expected_table_tuples)
        mock_server = Server(utils.MockPGServerConnection(cursor))
        executor: MetadataExecutor = MetadataExecutor(mock_server)
        # When I query tables
        actual_table_tuples = executor.tables()

        # I expect to get 2 tables from the executor
        self.assertEqual(len(expected_table_tuples), len(actual_table_tuples))
        for expected in expected_table_tuples:
            self.assertTrue(expected in actual_table_tuples)
예제 #8
0
 def __init__(self, conn):
     # get server from psycopg2 connection
     self.server: Server = Server(conn)
예제 #9
0
class CompletionRefresher:
    """
    Handles creating a PGCompleter object and populates it with the relevant
    completion suggestions in a background thread.
    """

    refreshers = OrderedDict()

    def __init__(self,
                 connection: 'psycopg2.extensions.connection',
                 logger: Logger = None):
        self.connection = connection
        self.logger: Logger = logger
        self.server: Server = None
        self._completer_thread: threading.Thread = None
        self._restart_refresh: threading.Event = threading.Event()

    def refresh(self, callbacks, history=None, settings=None) -> str:
        """
        Creates a PGCompleter object and populates it with the relevant
        completion suggestions in a background thread.

        settings - dict of settings for completer object
        callbacks - A function or a list of functions to call after the thread
                    has completed the refresh. The newly created completion
                    object will be passed in as an argument to each callback.
        """
        if self.server is None:
            # Delay server creation until on background thread
            self.server = Server(self.connection)

        if self.is_refreshing():
            self._restart_refresh.set()
            return 'Auto-completion refresh restarted.'
        else:
            self._completer_thread = threading.Thread(
                target=self._bg_refresh,
                args=(callbacks, history, settings),
                name='completion_refresh')
            self._completer_thread.daemon = True
            self._completer_thread.start()
            return 'Auto-completion refresh started in the background.'  # TODO localize

    def is_refreshing(self):
        return self._completer_thread and self._completer_thread.is_alive()

    def _bg_refresh(self, callbacks, history=None, settings=None):
        settings = settings or {}
        completer = PGCompleter(smart_completion=True, settings=settings)

        self.server.refresh()
        metadata_executor = MetadataExecutor(self.server)

        # If callbacks is a single function then push it into a list.
        if callable(callbacks):
            callbacks = [callbacks]

        try:
            while True:
                for do_refresh in self.refreshers.values():
                    do_refresh(completer, metadata_executor)
                    if self._restart_refresh.is_set():
                        self._restart_refresh.clear()
                        break
                else:
                    # Break out of while loop if the for loop finishes natually
                    # without hitting the break statement.
                    break

                # Start over the refresh from the beginning if the for loop hit the
                # break statement.
                continue

            # Load history into pgcompleter so it can learn user preferences
            n_recent = 100
            if history:
                for recent in history[-n_recent:]:
                    completer.extend_query_history(recent, is_init=True)

        except Exception as e:
            if self.logger:
                self.logger.exception('Error during metadata refresh: {0}', e)

        for callback in callbacks:
            callback(completer)

        if self._restart_refresh.is_set():
            self._restart_refresh.clear()