mirror of https://github.com/apache/cassandra
cqlsh: Remove ASSUME command
patch by Aleksey Yeschenko; reviewed by Brandon Williams for CASSANDRA-5331
This commit is contained in:
parent
effdb08b34
commit
207cdf3013
|
|
@ -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
|
||||
|
|
|
|||
3
NEWS.txt
3
NEWS.txt
|
|
@ -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
171
bin/cqlsh
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@ class TestCqlshCommands(BaseTestCase):
|
|||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_assume(self):
|
||||
pass
|
||||
|
||||
def test_show(self):
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue