cqlsh: make it possible to describe thrift CFs; patch by Aleksey Yeschenko, reviewed by Jonathan Ellis for CASSANDRA-4827
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/9210d577 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/9210d577 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/9210d577 Branch: refs/heads/cassandra-1.2 Commit: 9210d5776c26ca7f64ff896100890eb640ed2fe1 Parents: cb45b41 Author: Aleksey Yeschenko <alek...@apache.org> Authored: Mon Dec 10 18:01:32 2012 +0300 Committer: Aleksey Yeschenko <alek...@apache.org> Committed: Mon Dec 10 18:04:10 2012 +0300 ---------------------------------------------------------------------- CHANGES.txt | 1 + pylib/cqlshlib/cql3handling.py | 93 +++++++++++++++++++++------------- 2 files changed, 58 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/9210d577/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index b92984d..301afd2 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -11,6 +11,7 @@ Merged from 1.1 * reduce log spam from invalid counter shards (CASSANDRA-5026) * Improve schema propagation performance (CASSANDRA-5025) * Fix for IndexHelper.IndexFor throws OOB Exception (CASSANDRA-5030) + * cqlsh: make it possible to describe thrift CFs (CASSANDRA-4827) 1.2-beta3 http://git-wip-us.apache.org/repos/asf/cassandra/blob/9210d577/pylib/cqlshlib/cql3handling.py ---------------------------------------------------------------------- diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py index 3c24114..0089f12 100644 --- a/pylib/cqlshlib/cql3handling.py +++ b/pylib/cqlshlib/cql3handling.py @@ -1403,7 +1403,7 @@ class CqlTableDef: colname_type = UTF8Type column_class = CqlColumnDef - """True if this CF has compact storage""" + """True if this CF has compact storage (isn't a CQL3 table)""" compact_storage = False """Names of all columns which are part of the primary key, whether or not @@ -1446,48 +1446,75 @@ class CqlTableDef: setattr(cf, attr, json.loads(getattr(cf, attr))) except AttributeError: pass - if not cf.key_aliases: - if cf.key_alias: - cf.key_aliases = [cf.key_alias.decode('ascii')] - else: - cf.key_aliases = [u'key'] - cf.partition_key_components = cf.key_aliases - cf.primary_key_components = cf.key_aliases + list(cf.column_aliases) cf.partition_key_validator = lookup_casstype(cf.key_validator) - cf.default_validator = lookup_casstype(cf.default_validator) cf.comparator = lookup_casstype(cf.comparator) + cf.default_validator = lookup_casstype(cf.default_validator) cf.coldefs = coldefs - cf.parse_types() + cf.compact_storage = cf.is_compact_storage() + cf.key_aliases = cf.get_key_aliases() + cf.partition_key_components = cf.key_aliases + cf.column_aliases = cf.get_column_aliases() + cf.primary_key_components = cf.key_aliases + list(cf.column_aliases) + cf.columns = cf.get_columns() return cf + # not perfect, but good enough; please read CFDefinition constructor comments + # returns False if we are dealing with a CQL3 table, True otherwise. + # 'compact' here means 'needs WITH COMPACT STORAGE option for CREATE TABLE in CQL3'. def is_compact_storage(self): if not issubclass(self.comparator, CompositeType): return True for subtype in self.comparator.subtypes: if issubclass(subtype, ColumnToCollectionType): return False - return bool(len(self.comparator.subtypes) == len(self.column_aliases)) + if len(self.column_aliases) == len(self.comparator.subtypes) - 1: + if self.comparator.subtypes[-1] is UTF8Type: + return False + return True - def parse_types(self): - self.compact_storage = self.is_compact_storage() + def get_key_aliases(self): + if not issubclass(self.partition_key_validator, CompositeType): + return self.key_aliases or [u'key'] + expected = len(self.partition_key_validator.subtypes) + # key, key2, key3, ..., keyN + aliases = [u'key'] + [ u'key' + str(i) for i in range(2, expected + 1) ] + # append the missing (non-renamed) aliases (if any) + return self.key_aliases + aliases[len(self.key_aliases):] + + def get_column_aliases(self): + # CQL3 table + if not self.compact_storage: + return self.column_aliases + if not issubclass(self.comparator, CompositeType): + # static cf + if self.coldefs: + return [] + else: + return self.column_aliases or [u'column1'] + expected = len(self.comparator.subtypes) + # column1, column2, column3, ..., columnN + aliases = [ u'column' + str(i) for i in range(1, expected + 1) ] + # append the missing (non-renamed) aliases (if any) + return self.column_aliases + aliases[len(self.column_aliases):] + + def get_columns(self): if self.compact_storage: - self.columns = self.parse_types_compact() + return self.get_columns_compact() else: - self.columns = self.parse_types_dynamic() + return self.get_columns_cql3() - def parse_types_compact(self): + # dense composite or dynamic cf or static cf (technically not compact). + def get_columns_compact(self): if issubclass(self.partition_key_validator, CompositeType): partkey_types = self.partition_key_validator.subtypes else: partkey_types = [self.partition_key_validator] - if len(partkey_types) != len(self.key_aliases): - warn(UnexpectedTableStructure("Compact storage CF key-validator-types %r is not" - " the same length as its key_aliases %r" - % (partkey_types, self.key_aliases))) + partkey_cols = map(self.column_class, self.partition_key_components, partkey_types) + if len(self.column_aliases) == 0: if self.comparator is not UTF8Type: warn(UnexpectedTableStructure("Compact storage CF %s has no column aliases," - " but comparator is not UTF8Type.")) + " but comparator is not UTF8Type." % (self,))) colalias_types = [] elif issubclass(self.comparator, CompositeType): colalias_types = self.comparator.subtypes @@ -1497,8 +1524,6 @@ class CqlTableDef: warn(UnexpectedTableStructure("Compact storage CF comparator-types %r is not" " the same length as its column_aliases %r" % (colalias_types, self.column_aliases))) - - partkey_cols = map(self.column_class, self.partition_key_components, partkey_types) colalias_cols = map(self.column_class, self.column_aliases, colalias_types) if self.value_alias is not None: @@ -1510,24 +1535,22 @@ class CqlTableDef: value_cols = [] else: value_cols = [self.column_class(self.value_alias, self.default_validator)] + elif self.value_alias is None and not self.coldefs: + value_cols = [self.column_class("value", self.default_validator)] else: value_cols = map(self.column_class.from_layout, self.coldefs) value_cols.sort(key=lambda c: c.name) return partkey_cols + colalias_cols + value_cols - def parse_types_dynamic(self): - if not issubclass(self.comparator, CompositeType): - warn(UnexpectedTableStructure("Dynamic storage CF comparator is %r, not" - " composite" % (self.comparator,))) + # sparse composite (CQL3 table). + def get_columns_cql3(self): if issubclass(self.partition_key_validator, CompositeType): partkey_types = self.partition_key_validator.subtypes else: partkey_types = [self.partition_key_validator] - if len(partkey_types) != len(self.key_aliases): - warn(UnexpectedTableStructure("Dynamic storage CF key-validator-types %r " - "is not the same length as its key_aliases %r" - % (partkey_types, self.key_aliases))) + partkey_cols = map(self.column_class, self.partition_key_components, partkey_types) + for subtype in self.comparator.subtypes[:-1]: if issubclass(subtype, ColumnToCollectionType): warn(UnexpectedTableStructure("ColumnToCollectionType found, but not in " @@ -1537,14 +1560,12 @@ class CqlTableDef: # all this information should be available in schema_columns coltypes.pop(-1) if len(coltypes) != len(self.column_aliases) + 1 or coltypes[-1] is not UTF8Type: - warn(UnexpectedTableStructure("Dynamic storage CF does not have UTF8Type" + warn(UnexpectedTableStructure("CQL3 CF does not have UTF8Type" " added to comparator")) - colalias_types = coltypes[:-1] - partkey_cols = map(self.column_class, self.partition_key_components, partkey_types) - colalias_cols = map(self.column_class, self.column_aliases, colalias_types) + colalias_cols = map(self.column_class, self.column_aliases, coltypes[:-1]) if self.value_alias is not None: - warn(UnexpectedTableStructure("Dynamic storage CF has a value_alias (%r)" + warn(UnexpectedTableStructure("CQL3 CF has a value_alias (%r)" % (self.value_alias,))) value_cols = map(self.column_class.from_layout, self.coldefs) value_cols.sort(key=lambda c: c.name)