summaryrefslogtreecommitdiffstats
path: root/mycli/packages/special/dbcommands.py
blob: ed90e4c3775efff1cc6ebf5f5736edd5fd307abd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import logging
import os
import platform
from mycli import __version__
from mycli.packages.special import iocommands
from mycli.packages.special.utils import format_uptime
from .main import special_command, RAW_QUERY, PARSED_QUERY
from pymysql import ProgrammingError

log = logging.getLogger(__name__)


@special_command('\\dt', '\\dt[+] [table]', 'List or describe tables.',
                 arg_type=PARSED_QUERY, case_sensitive=True)
def list_tables(cur, arg=None, arg_type=PARSED_QUERY, verbose=False):
    if arg:
        query = 'SHOW FIELDS FROM {0}'.format(arg)
    else:
        query = 'SHOW TABLES'
    log.debug(query)
    cur.execute(query)
    tables = cur.fetchall()
    status = ''
    if cur.description:
        headers = [x[0] for x in cur.description]
    else:
        return [(None, None, None, '')]

    if verbose and arg:
        query = 'SHOW CREATE TABLE {0}'.format(arg)
        log.debug(query)
        cur.execute(query)
        status = cur.fetchone()[1]

    return [(None, tables, headers, status)]

@special_command('\\l', '\\l', 'List databases.', arg_type=RAW_QUERY, case_sensitive=True)
def list_databases(cur, **_):
    query = 'SHOW DATABASES'
    log.debug(query)
    cur.execute(query)
    if cur.description:
        headers = [x[0] for x in cur.description]
        return [(None, cur, headers, '')]
    else:
        return [(None, None, None, '')]

@special_command('status', '\\s', 'Get status information from the server.',
                 arg_type=RAW_QUERY, aliases=('\\s', ), case_sensitive=True)
def status(cur, **_):
    query = 'SHOW GLOBAL STATUS;'
    log.debug(query)
    try:
        cur.execute(query)
    except ProgrammingError:
        # Fallback in case query fail, as it does with Mysql 4
        query = 'SHOW STATUS;'
        log.debug(query)
        cur.execute(query)
    status = dict(cur.fetchall())

    query = 'SHOW GLOBAL VARIABLES;'
    log.debug(query)
    cur.execute(query)
    variables = dict(cur.fetchall())

    # prepare in case keys are bytes, as with Python 3 and Mysql 4
    if (isinstance(list(variables)[0], bytes) and
            isinstance(list(status)[0], bytes)):
        variables = {k.decode('utf-8'): v.decode('utf-8') for k, v
                     in variables.items()}
        status = {k.decode('utf-8'): v.decode('utf-8') for k, v
                  in status.items()}

    # Create output buffers.
    title = []
    output = []
    footer = []

    title.append('--------------')

    # Output the mycli client information.
    implementation = platform.python_implementation()
    version = platform.python_version()
    client_info = []
    client_info.append('mycli {0},'.format(__version__))
    client_info.append('running on {0} {1}'.format(implementation, version))
    title.append(' '.join(client_info) + '\n')

    # Build the output that will be displayed as a table.
    output.append(('Connection id:', cur.connection.thread_id()))

    query = 'SELECT DATABASE(), USER();'
    log.debug(query)
    cur.execute(query)
    db, user = cur.fetchone()
    if db is None:
        db = ''

    output.append(('Current database:', db))
    output.append(('Current user:', user))

    if iocommands.is_pager_enabled():
        if 'PAGER' in os.environ:
            pager = os.environ['PAGER']
        else:
            pager = 'System default'
    else:
        pager = 'stdout'
    output.append(('Current pager:', pager))

    output.append(('Server version:', '{0} {1}'.format(
        variables['version'], variables['version_comment'])))
    output.append(('Protocol version:', variables['protocol_version']))

    if 'unix' in cur.connection.host_info.lower():
        host_info = cur.connection.host_info
    else:
        host_info = '{0} via TCP/IP'.format(cur.connection.host)

    output.append(('Connection:', host_info))

    query = ('SELECT @@character_set_server, @@character_set_database, '
             '@@character_set_client, @@character_set_connection LIMIT 1;')
    log.debug(query)
    cur.execute(query)
    charset = cur.fetchone()
    output.append(('Server characterset:', charset[0]))
    output.append(('Db characterset:', charset[1]))
    output.append(('Client characterset:', charset[2]))
    output.append(('Conn. characterset:', charset[3]))

    if 'TCP/IP' in host_info:
        output.append(('TCP port:', cur.connection.port))
    else:
        output.append(('UNIX socket:', variables['socket']))

    output.append(('Uptime:', format_uptime(status['Uptime'])))

    # Print the current server statistics.
    stats = []
    stats.append('Connections: {0}'.format(status['Threads_connected']))
    if 'Queries' in status:
        stats.append('Queries: {0}'.format(status['Queries']))
    stats.append('Slow queries: {0}'.format(status['Slow_queries']))
    stats.append('Opens: {0}'.format(status['Opened_tables']))
    stats.append('Flush tables: {0}'.format(status['Flush_commands']))
    stats.append('Open tables: {0}'.format(status['Open_tables']))
    if 'Queries' in status:
        queries_per_second = int(status['Queries']) / int(status['Uptime'])
        stats.append('Queries per second avg: {:.3f}'.format(
            queries_per_second))
    stats = '  '.join(stats)
    footer.append('\n' + stats)

    footer.append('--------------')
    return [('\n'.join(title), output, '', '\n'.join(footer))]