cqlsh: Remove ASSUME command

patch by Aleksey Yeschenko; reviewed by Brandon Williams for
CASSANDRA-5331
This commit is contained in:
Aleksey Yeschenko 2013-03-22 00:20:13 +03:00
parent effdb08b34
commit 207cdf3013
6 changed files with 10 additions and 194 deletions

View File

@ -18,6 +18,7 @@
* Allow custom configuration loader (CASSANDRA-5045)
* Remove memory emergency pressure valve logic (CASSANDRA-3534)
* Reduce request latency with eager retry (CASSANDRA-4705)
* cqlsh: Remove ASSUME command (CASSANDRA-5331)
1.2.4

View File

@ -22,6 +22,9 @@ Upgrading
Use CacheServiceMBean.set{Key,Row}CacheCapacityInMB() instead.
- authority option in cassandra.yaml has been deprecated since 1.2.0,
but it has been completely removed in 2.0. Please use 'authorizer' option.
- ASSUME command has been removed from cqlsh. Use CQL3 blobAsType() and
typeAsBlob() conversion functions instead.
See https://cassandra.apache.org/doc/cql3/CQL.html#blobFun for details.
Operations
----------

171
bin/cqlsh
View File

@ -38,7 +38,6 @@ from StringIO import StringIO
from itertools import groupby
from contextlib import contextmanager, closing
from glob import glob
from functools import partial
from uuid import UUID
import cmd
@ -102,8 +101,7 @@ except ImportError, e:
import cql.decoders
from cql.cursor import _VOID_DESCRIPTION
from cql.cqltypes import (cql_types, cql_typename, lookup_casstype, lookup_cqltype,
CassandraType)
from cql.cqltypes import (cql_types, cql_typename, lookup_casstype, CassandraType)
# cqlsh should run correctly when run out of a Cassandra source tree,
# out of an unpacked Cassandra tarball, and after a proper package install.
@ -183,7 +181,6 @@ my_commands_ending_with_newline = (
'describe',
'desc',
'show',
'assume',
'source',
'capture',
'debug',
@ -207,7 +204,6 @@ cqlsh_extra_syntax_rules = r'''
<specialCommand> ::= <describeCommand>
| <consistencyCommand>
| <showCommand>
| <assumeCommand>
| <sourceCommand>
| <captureCommand>
| <copyCommand>
@ -239,18 +235,9 @@ cqlsh_extra_syntax_rules = r'''
| "EACH_QUORUM"
;
<showCommand> ::= "SHOW" what=( "VERSION" | "HOST" | "ASSUMPTIONS" )
<showCommand> ::= "SHOW" what=( "VERSION" | "HOST" )
;
<assumeCommand> ::= "ASSUME" cf=<columnFamilyName> <assumeTypeDef>
( "," <assumeTypeDef> )*
;
<assumeTypeDef> ::= "NAMES" "ARE" names=<storageType>
| "VALUES" "ARE" values=<storageType>
| "(" colname=<colname> ")" "VALUES" "ARE" colvalues=<storageType>
;
<sourceCommand> ::= "SOURCE" fname=<stringLiteral>
;
@ -291,16 +278,6 @@ cqlsh_extra_syntax_rules = r'''
def complete_help(ctxt, cqlsh):
return sorted([ t.upper() for t in cqldocs.get_help_topics() + cqlsh.get_help_topics() ])
@cqlsh_syntax_completer('assumeTypeDef', 'colname')
def complete_assume_col(ctxt, cqlsh):
ks = ctxt.get_binding('ks', None)
ks = cqlsh.cql_unprotect_name(ks) if ks is not None else None
cf = cqlsh.cql_unprotect_name(ctxt.get_binding('cf'))
cfdef = cqlsh.get_columnfamily(cf, ksname=ks)
cols = [cm.name for cm in cfdef.column_metadata]
cols.append(cfdef.key_alias or 'KEY')
return cqlsh.cql_protect_names(cols)
def complete_source_quoted_filename(ctxt, cqlsh):
partial = ctxt.get_binding('partial', '')
head, tail = os.path.split(partial)
@ -512,7 +489,6 @@ class Shell(cmd.Cmd):
self.statement = StringIO()
self.lineno = 1
self.in_comment = False
self.schema_overrides = {}
self.prompt = ''
if stdin is None:
@ -575,32 +551,6 @@ class Shell(cmd.Cmd):
vers['cql'] = self.cql_version
print "[cqlsh %(shver)s | Cassandra %(build)s | CQL spec %(cql)s | Thrift protocol %(thrift)s]" % vers
def show_assumptions(self):
all_overrides = self.schema_overrides.items()
all_overrides.sort()
if all_overrides:
print
else:
print 'No overrides.'
return
for keyspace, ksoverrides in groupby(all_overrides, key=lambda x:x[0][0]):
keyspace = self.cql_protect_name(keyspace)
print 'USE %s;' % keyspace
print
for (ks, cf), override in ksoverrides:
cf = self.cql_protect_name(cf)
if override.default_name_type:
print 'ASSUME %s NAMES ARE %s;' \
% (cf, cql_typename(override.default_name_type))
if override.default_value_type:
print 'ASSUME %s VALUES ARE %s;' \
% (cf, cql_typename(override.default_value_type))
for colname, vtype in override.value_types.items():
colname = self.cql_protect_name(colname)
print 'ASSUME %s(%s) VALUES ARE %s;' \
% (cf, colname, cql_typename(vtype))
print
def get_connection_versions(self):
try:
self.cursor.execute("select * from system.local where key = 'local'")
@ -969,13 +919,12 @@ class Shell(cmd.Cmd):
if ksname is not None:
ksname = self.cql_unprotect_name(ksname)
cfname = self.cql_unprotect_name(parsed.get_binding('cfname'))
decoder = self.determine_decoder_for(cfname, ksname=ksname)
statement = parsed.extract_orig()
with_default_limit = parsed.get_binding('limit') is None
if with_default_limit:
statement = "%s LIMIT %d;" % (statement[:-1], DEFAULT_SELECT_LIMIT)
self.perform_statement(statement,
decoder=decoder,
decoder=ErrorHandlingSchemaDecoder,
with_default_limit=with_default_limit)
def perform_statement(self, statement, decoder=None, with_default_limit=False):
@ -1042,15 +991,6 @@ class Shell(cmd.Cmd):
def parseable_as_cql2(self, statement):
return cqlhandling.CqlRuleSet.lex_and_whole_match(statement) is not None
def determine_decoder_for(self, cfname, ksname=None):
decoder = ErrorHandlingSchemaDecoder
if ksname is None:
ksname = self.current_keyspace
overrides = self.schema_overrides.get((ksname, cfname), None)
if overrides:
decoder = partial(decoder, overrides=overrides)
return decoder
def get_nametype(self, cursor, num):
"""
Determine the Cassandra type of a column name from the current row of
@ -1748,11 +1688,6 @@ class Shell(cmd.Cmd):
SHOW HOST
Shows where cqlsh is currently connected.
SHOW ASSUMPTIONS
Outputs the current list of type assumptions as specified by the
user. See the help for the ASSUME command for more information.
"""
showwhat = parsed.get_binding('what').lower()
if showwhat == 'version':
@ -1760,73 +1695,9 @@ class Shell(cmd.Cmd):
self.show_version()
elif showwhat == 'host':
self.show_host()
elif showwhat == 'assumptions':
self.show_assumptions()
else:
self.printerr('Wait, how do I show %r?' % (showwhat,))
def do_assume(self, parsed):
"""
ASSUME [cqlsh only]
Instruct cqlsh to consider certain column names or values to be of a
specified type, even if that type information is not specified in
the table's metadata. Data will be deserialized according to the
given type, and displayed appropriately when retrieved.
Use thus:
ASSUME [<keyspace>.]<tablename> NAMES ARE <type>;
Treat all column names in the given table as being of the
given type.
ASSUME [<keyspace>.]<tablename> VALUES ARE <type>;
Treat all column values in the given table as being of the
given type, unless there is more information about the specific
column being deserialized. That is, a column-specific ASSUME will
take precedence here, as will column-specific metadata in the
table's definition.
ASSUME [<keyspace>.]<tablename>(<colname>) VALUES ARE <type>;
Treat all values in the given column in the given table as
being of the specified type. This overrides any other information
about the type of a value.
Assign multiple overrides at once for the same table by
separating with commas:
ASSUME ks.table NAMES ARE uuid, VALUES ARE int, (col) VALUES ARE ascii
See HELP TYPES for information on the supported data storage types.
"""
ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
colname = self.cql_unprotect_name(parsed.get_binding('colname', None))
params = {}
for paramname in ('names', 'values', 'colvalues'):
val = parsed.get_binding(paramname, None)
params[paramname] = self.cql_unprotect_value(val)
if ks is None:
if self.current_keyspace is None:
self.printerr('Error: not in any keyspace.')
return
ks = self.current_keyspace
for overridetype in ('names', 'values', 'colvalues'):
cqltype = params[overridetype]
if cqltype is None:
continue
try:
validator_class = lookup_cqltype(cqltype).cass_parameterized_type()
except KeyError:
self.printerr('Error: validator type %s not found.' % cqltype)
else:
self.add_assumption(ks, cf, colname, overridetype, validator_class)
def do_source(self, parsed):
"""
SOURCE [cqlsh only]
@ -2067,41 +1938,7 @@ class Shell(cmd.Cmd):
text = '%s:%d:%s' % (self.stdin.name, self.lineno, text)
self.writeresult(text, color, newline=newline, out=sys.stderr)
def add_assumption(self, ksname, cfname, colname, valtype, valclass):
try:
v_info = self.schema_overrides[(ksname, cfname)]
except KeyError:
v_info = self.schema_overrides[(ksname, cfname)] = FakeCqlMetadata()
if valtype == 'names':
v_info.default_name_type = valclass
elif valtype == 'values':
v_info.default_value_type = valclass
elif valtype == 'colvalues':
v_info.value_types[colname] = valclass
class FakeCqlMetadata:
def __init__(self):
self.name_types = {}
self.value_types = {}
self.default_name_type = None
self.default_value_type = None
class OverrideableSchemaDecoder(cql.decoders.SchemaDecoder):
def __init__(self, schema, overrides=None):
cql.decoders.SchemaDecoder.__init__(self, schema)
self.apply_schema_overrides(overrides)
def apply_schema_overrides(self, overrides):
if overrides is None:
return
if overrides.default_name_type is not None:
self.schema.default_name_type = overrides.default_name_type
if overrides.default_value_type is not None:
self.schema.default_value_type = overrides.default_value_type
self.schema.name_types.update(overrides.name_types)
self.schema.value_types.update(overrides.value_types)
class ErrorHandlingSchemaDecoder(OverrideableSchemaDecoder):
class ErrorHandlingSchemaDecoder(cql.decoders.SchemaDecoder):
def name_decode_error(self, err, namebytes, expectedtype):
return DecodeError(namebytes, err, expectedtype)

View File

@ -26,9 +26,6 @@ class TestCqlshCommands(BaseTestCase):
def tearDown(self):
pass
def test_assume(self):
pass
def test_show(self):
pass

View File

@ -95,7 +95,7 @@ class TestCqlshCompletion_CQL2(CqlshCompletionCase):
module = cqlsh.cqlhandling
def test_complete_on_empty_string(self):
self.trycompletions('', choices=('?', 'ALTER', 'ASSUME', 'BEGIN', 'CAPTURE', 'CONSISTENCY',
self.trycompletions('', choices=('?', 'ALTER', 'BEGIN', 'CAPTURE', 'CONSISTENCY',
'COPY', 'CREATE', 'DEBUG', 'DELETE', 'DESC', 'DESCRIBE',
'DROP', 'HELP', 'INSERT', 'SELECT', 'SHOW', 'SOURCE',
'TRACING', 'TRUNCATE', 'UPDATE', 'USE', 'exit', 'quit'))
@ -178,7 +178,7 @@ class TestCqlshCompletion_CQL3final(TestCqlshCompletion_CQL2):
module = cqlsh.cql3handling
def test_complete_on_empty_string(self):
self.trycompletions('', choices=('?', 'ALTER', 'ASSUME', 'BEGIN', 'CAPTURE', 'CONSISTENCY',
self.trycompletions('', choices=('?', 'ALTER', 'BEGIN', 'CAPTURE', 'CONSISTENCY',
'COPY', 'CREATE', 'DEBUG', 'DELETE', 'DESC', 'DESCRIBE',
'DROP', 'GRANT', 'HELP', 'INSERT', 'LIST', 'REVOKE',
'SELECT', 'SHOW', 'SOURCE', 'TRACING', 'TRUNCATE', 'UPDATE',

View File

@ -894,28 +894,6 @@ class TestCqlshOutput(BaseTestCase):
self.assertRegexpMatches(output, '^Connected to .* at %s:%d\.$'
% (re.escape(TEST_HOST), TEST_PORT))
def test_show_assumptions_output(self):
expected_output = '\nUSE %s;\n\n' % quote_name('', get_test_keyspace())
with testrun_cqlsh(tty=True) as c:
output = c.cmd_and_response('show assumptions')
self.assertEqual(output, 'No overrides.\n')
c.cmd_and_response('assume dynamic_values VALUES aRe uuid;')
expected_output += 'ASSUME dynamic_values VALUES ARE uuid;\n'
output = c.cmd_and_response('show assumptions')
self.assertEqual(output, expected_output + '\n')
c.cmd_and_response('Assume has_all_types names arE float;')
expected_output += 'ASSUME has_all_types NAMES ARE float;\n'
output = c.cmd_and_response('show assumptions')
self.assertEqual(output, expected_output + '\n')
c.cmd_and_response('assume twenty_rows_table ( b ) values are decimal;')
expected_output += 'ASSUME twenty_rows_table(b) VALUES ARE decimal;\n'
output = c.cmd_and_response('show assumptions')
self.assertEqual(output, expected_output + '\n')
def test_eof_prints_newline(self):
with testrun_cqlsh(tty=True) as c:
c.send(CONTROL_D)