cqlsh: add vertical output option (see EXPAND)

patch by Michał Michalski; reviewed by Aleksey Yeschenko for
 CASSANDRA-5597
This commit is contained in:
Aleksey Yeschenko 2013-05-29 20:59:51 +03:00
parent 6d7404bc2e
commit 26c65e640c
3 changed files with 73 additions and 6 deletions

View File

@ -9,6 +9,7 @@
* Exclude localTimestamp from validation for tombstones (CASSANDRA-5398)
* cqlsh: add custom prompt support (CASSANDRA-5539)
* Reuse prepared statements in hot auth queries (CASSANDRA-5594)
* cqlsh: add vertical output option (see EXPAND) (CASSANDRA-5597)
Merged from 1.1:
* Remove buggy thrift max message length option (CASSANDRA-5529)
* Fix NPE in Pig's widerow mode (CASSANDRA-5488)

View File

@ -32,7 +32,7 @@ exit 1
from __future__ import with_statement
description = "CQL Shell for Apache Cassandra"
version = "3.0.3"
version = "3.1.0"
from StringIO import StringIO
from itertools import groupby
@ -188,6 +188,7 @@ my_commands_ending_with_newline = (
'capture',
'debug',
'tracing',
'expand',
'exit',
'quit'
)
@ -214,6 +215,7 @@ cqlsh_extra_syntax_rules = r'''
| <debugCommand>
| <helpCommand>
| <tracingCommand>
| <expandCommand>
| <exitCommand>
;
@ -281,6 +283,9 @@ cqlsh_extra_syntax_rules = r'''
<tracingCommand> ::= "TRACING" ( switch=( "ON" | "OFF" ) )?
;
<expandCommand> ::= "EXPAND" ( switch=( "ON" | "OFF" ) )?
;
<exitCommand> ::= "exit" | "quit"
;
@ -467,7 +472,8 @@ class Shell(cmd.Cmd):
def __init__(self, hostname, port, transport_factory, color=False,
username=None, password=None, encoding=None, stdin=None, tty=True,
completekey=DEFAULT_COMPLETEKEY, use_conn=None,
cqlver=DEFAULT_CQLVER, keyspace=None, tracing_enabled=False,
cqlver=DEFAULT_CQLVER, keyspace=None,
tracing_enabled=False, expand_enabled=False,
display_time_format=DEFAULT_TIME_FORMAT,
display_float_precision=DEFAULT_FLOAT_PRECISION):
cmd.Cmd.__init__(self, completekey=completekey)
@ -478,6 +484,7 @@ class Shell(cmd.Cmd):
self.password = password
self.keyspace = keyspace
self.tracing_enabled = tracing_enabled
self.expand_enabled = expand_enabled
if use_conn is not None:
self.conn = use_conn
else:
@ -1109,7 +1116,10 @@ class Shell(cmd.Cmd):
colnames_t = [(name, self.get_nametype(cursor, n)) for (n, name) in enumerate(colnames)]
formatted_names = [self.myformat_colname(name, nametype) for (name, nametype) in colnames_t]
formatted_values = [map(self.myformat_value, row, cursor.column_types) for row in cursor]
self.print_formatted_result(formatted_names, formatted_values)
if self.expand_enabled:
self.print_formatted_result_vertically(formatted_names, formatted_values)
else:
self.print_formatted_result(formatted_names, formatted_values)
def print_formatted_result(self, formatted_names, formatted_values):
# determine column widths
@ -1128,6 +1138,20 @@ class Shell(cmd.Cmd):
line = ' | '.join(col.rjust(w, color=self.color) for (col, w) in zip(row, widths))
self.writeresult(' ' + line)
def print_formatted_result_vertically(self, formatted_names, formatted_values):
max_col_width = max([n.displaywidth for n in formatted_names])
max_val_width = max([n.displaywidth for row in formatted_values for n in row])
# for each row returned, list all the column-value pairs
for row_id, row in enumerate(formatted_values):
self.writeresult("@ Row %d" % (row_id + 1))
self.writeresult('-%s-' % '-+-'.join(['-' * max_col_width, '-' * max_val_width]))
for field_id, field in enumerate(row):
column = formatted_names[field_id].ljust(max_col_width, color=self.color)
value = field.ljust(field.displaywidth, color=self.color)
self.writeresult(' ' + " | ".join([column, value]))
self.writeresult('')
def print_dynamic_result(self, cursor):
for row in cursor:
colnames = [d[0] for d in cursor.description]
@ -1984,6 +2008,48 @@ class Shell(cmd.Cmd):
self.tracing_enabled = False
print 'Disabled tracing.'
def do_expand(self, parsed):
"""
EXPAND [cqlsh]
Enables or disables expanded (vertical) output.
EXPAND ON
Enables expanded (vertical) output.
EXPAND OFF
Disables expanded (vertical) output.
EXPAND
EXPAND with no arguments shows the current value of expand setting.
"""
switch = parsed.get_binding('switch')
if switch is None:
if self.expand_enabled:
print "Expanded output is currently enabled. Use EXPAND OFF to disable"
else:
print "Expanded output is currently disabled. Use EXPAND ON to enable."
return
if switch.upper() == 'ON':
if self.expand_enabled:
self.printerr('Expanded output is already enabled. '
'Use EXPAND OFF to disable.')
return
self.expand_enabled = True
print 'Now printing expanded output'
return
if switch.upper() == 'OFF':
if not self.expand_enabled:
self.printerr('Expanded output is not enabled.')
return
self.expand_enabled = False
print 'Disabled expanded output.'
def do_consistency(self, parsed):
"""
CONSISTENCY [cqlsh with CQL3 only]

View File

@ -98,7 +98,7 @@ class TestCqlshCompletion_CQL2(CqlshCompletionCase):
self.trycompletions('', choices=('?', 'ALTER', 'ASSUME', 'BEGIN', 'CAPTURE', 'CONSISTENCY',
'COPY', 'CREATE', 'DEBUG', 'DELETE', 'DESC', 'DESCRIBE',
'DROP', 'HELP', 'INSERT', 'SELECT', 'SHOW', 'SOURCE',
'TRACING', 'TRUNCATE', 'UPDATE', 'USE', 'exit', 'quit'))
'TRACING', 'EXPAND', 'TRUNCATE', 'UPDATE', 'USE', 'exit', 'quit'))
def test_complete_command_words(self):
self.trycompletions('alt', '\b\b\bALTER ')
@ -181,8 +181,8 @@ class TestCqlshCompletion_CQL3final(TestCqlshCompletion_CQL2):
self.trycompletions('', choices=('?', 'ALTER', 'ASSUME', 'BEGIN', 'CAPTURE', 'CONSISTENCY',
'COPY', 'CREATE', 'DEBUG', 'DELETE', 'DESC', 'DESCRIBE',
'DROP', 'GRANT', 'HELP', 'INSERT', 'LIST', 'REVOKE',
'SELECT', 'SHOW', 'SOURCE', 'TRACING', 'TRUNCATE', 'UPDATE',
'USE', 'exit', 'quit'))
'SELECT', 'SHOW', 'SOURCE', 'TRACING', 'EXPAND', 'TRUNCATE',
'UPDATE', 'USE', 'exit', 'quit'))
def test_complete_in_create_keyspace(self):
self.trycompletions('create keyspace ', '', choices=('<identifier>', '<quotedName>'))