Beispiel #1
0
 def progress_update(self, line):
     if not self.config.getboolean('main', 'timing'):
         return
     # Parse X-ClickHouse-Progress header
     now = datetime.now()
     progress = json.loads(line[23:].decode().strip())
     progress = {
         'timestamp': now,
         'read_rows': int(progress['read_rows']),
         'total_rows': int(progress['total_rows']),
         'read_bytes': int(progress['read_bytes']),
     }
     # Calculate percentage completed and format initial message
     progress['percents'] = int(
         (progress['read_rows'] / progress['total_rows']) *
         100) if progress['total_rows'] > 0 else 0
     message = 'Progress: {} rows, {}'.format(
         numberunit_fmt(progress['read_rows']),
         sizeof_fmt(progress['read_bytes']))
     # Calculate row and byte read velocity
     if self.progress:
         delta = (now - self.progress['timestamp']).total_seconds()
         if delta > 0:
             rps = (progress['read_rows'] -
                    self.progress['read_rows']) / delta
             bps = (progress['read_bytes'] -
                    self.progress['read_bytes']) / delta
             message += ' ({} rows/s, {}/s)'.format(numberunit_fmt(rps),
                                                    sizeof_fmt(bps))
     self.progress = progress
     self.progress_print(message, progress['percents'])
Beispiel #2
0
    def handle_query(self,
                     query,
                     data=None,
                     stream=False,
                     verbose=False,
                     query_id=None,
                     compress=False,
                     **kwargs):
        if query.rstrip(';') == '':
            return

        elif query.lower() in EXIT_COMMANDS:
            raise EOFError

        elif query.lower() in (r'\?', 'help'):
            rows = [
                ['', ''],
                ["clickhouse-cli's custom commands:", ''],
                ['---------------------------------', ''],
                ['USE', "Change the current database."],
                ['SET', "Set an option for the current CLI session."],
                ['QUIT', "Exit clickhouse-cli."],
                ['HELP', "Show this help message."],
                ['', ''],
                ["PostgreSQL-like custom commands:", ''],
                ['--------------------------------', ''],
                [r'\l', "Show databases."],
                [r'\c', "Change the current database."],
                [r'\d, \dt', "Show tables in the current database."],
                [r'\d+', "Show table's schema."],
                [r'\ps', "Show current queries."],
                [r'\kill', "Kill query by its ID."],
                ['', ''],
                ["Query suffixes:", ''],
                ['---------------', ''],
                [r'\g, \G', "Use the Vertical format."],
                [r'\p', "Enable the pager."],
            ]

            for row in rows:
                self.echo.success('{:<8s}'.format(row[0]), nl=False)
                self.echo.info(row[1])
            return

        elif query in (r'\d', r'\dt'):
            query = 'SHOW TABLES'

        elif query.startswith(r'\d+ '):
            query = 'DESCRIBE TABLE ' + query[4:]

        elif query == r'\l':
            query = 'SHOW DATABASES'

        elif query.startswith(r'\c '):
            query = 'USE ' + query[3:]

        elif query.startswith(r'\ps'):
            query = (
                "SELECT query_id, user, address, elapsed, {}, memory_usage "
                "FROM system.processes WHERE query_id != '{}'").format(
                    'read_rows' if self.server_version[2] >= 54115 else
                    'rows_read', query_id)

        elif query.startswith(r'\kill '):
            self.client.kill_query(query[6:])
            return

        response = ''

        self.progress_reset()

        try:
            response = self.client.query(
                query,
                fmt=self.format,
                data=data,
                stream=stream,
                verbose=verbose,
                query_id=query_id,
                compress=compress,
            )
        except TimeoutError:
            self.echo.error("Error: Connection timeout.")
            return
        except ConnectionError:
            self.echo.error("Error: Failed to connect.")
            return
        except DBException as e:
            self.progress_reset()
            self.echo.error("\nQuery:")
            self.echo.error(query)
            self.echo.error("\n\nReceived exception from server:")
            self.echo.error(e.error)

            if self.stacktrace and e.stacktrace:
                self.echo.print("\nStack trace:")
                self.echo.print(e.stacktrace)

            self.echo.print('\nElapsed: {elapsed:.3f} sec.\n'.format(
                elapsed=e.response.elapsed.total_seconds()))

            return

        total_rows, total_bytes = self.progress_reset()

        self.echo.print()

        if stream:
            data = response.iter_lines() if hasattr(
                response, 'iter_lines') else response.data
            for line in data:
                print(line.decode('utf-8', 'ignore'))

        else:
            if response.data != '':
                print_func = print

                if self.config.getboolean('main', 'pager') or kwargs.pop(
                        'force_pager', False):
                    print_func = self.echo.pager

                should_highlight_output = (verbose and self.highlight
                                           and self.highlight_output and
                                           response.format in PRETTY_FORMATS)

                formatter = TerminalFormatter()

                if self.highlight and self.highlight_truecolor:
                    formatter = TerminalTrueColorFormatter(
                        style=CHPygmentsStyle)

                if should_highlight_output:
                    print_func(
                        pygments.highlight(response.data,
                                           CHPrettyFormatLexer(), formatter))
                else:
                    print_func(response.data)

        if response.message != '':
            self.echo.print(response.message)
            self.echo.print()

        self.echo.success('Ok. ', nl=False)

        if response.rows is not None:
            self.echo.print('{rows_count} row{rows_plural} in set.'.format(
                rows_count=response.rows,
                rows_plural='s' if response.rows != 1 else '',
            ),
                            end=' ')

        if self.config.getboolean(
                'main', 'timing') and response.time_elapsed is not None:
            self.echo.print(
                'Elapsed: {elapsed:.3f} sec. Processed: {rows} rows, {bytes} ({avg_rps} rows/s, {avg_bps}/s)'
                .format(
                    elapsed=response.time_elapsed,
                    rows=numberunit_fmt(total_rows),
                    bytes=sizeof_fmt(total_bytes),
                    avg_rps=numberunit_fmt(total_rows /
                                           max(response.time_elapsed, 0.001)),
                    avg_bps=sizeof_fmt(total_bytes /
                                       max(response.time_elapsed, 0.001)),
                ),
                end='')

        self.echo.print('\n')