cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From brandonwilli...@apache.org
Subject git commit: Add missing file
Date Fri, 27 Apr 2012 22:14:46 GMT
Updated Branches:
  refs/heads/cassandra-1.1 b81f5723e -> c5ad288c9


Add missing file


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/c5ad288c
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/c5ad288c
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/c5ad288c

Branch: refs/heads/cassandra-1.1
Commit: c5ad288c9119e4eda9e60fbb6d998e6a5fbd716b
Parents: b81f572
Author: Brandon Williams <brandonwilliams@apache.org>
Authored: Fri Apr 27 17:14:33 2012 -0500
Committer: Brandon Williams <brandonwilliams@apache.org>
Committed: Fri Apr 27 17:14:33 2012 -0500

----------------------------------------------------------------------
 pylib/cqlshlib/cql3handling.py |  210 +++++++++++++++++++++++++++++++++++
 1 files changed, 210 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/c5ad288c/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
new file mode 100644
index 0000000..9d27f44
--- /dev/null
+++ b/pylib/cqlshlib/cql3handling.py
@@ -0,0 +1,210 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import re
+from warnings import warn
+from .cqlhandling import cql_typename, cql_escape
+
+try:
+    import json
+except ImportError:
+    import simplejson as json
+
+class UnexpectedTableStructure(UserWarning):
+    def __init__(self, msg):
+        self.msg = msg
+
+    def __str__(self):
+        return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
+
+keywords = set((
+    'select', 'from', 'where', 'and', 'key', 'insert', 'update', 'with',
+    'limit', 'using', 'consistency', 'one', 'quorum', 'all', 'any',
+    'local_quorum', 'each_quorum', 'two', 'three', 'use', 'count', 'set',
+    'begin', 'apply', 'batch', 'truncate', 'delete', 'in', 'create',
+    'keyspace', 'schema', 'columnfamily', 'table', 'index', 'on', 'drop',
+    'primary', 'into', 'values', 'timestamp', 'ttl', 'alter', 'add', 'type',
+    'compact', 'storage', 'order', 'by', 'asc', 'desc'
+))
+
+columnfamily_options = (
+    'comment',
+    'bloom_filter_fp_chance',
+    'caching',
+    'read_repair_chance',
+    # 'local_read_repair_chance',   -- not yet a valid cql option
+    'gc_grace_seconds',
+    'min_compaction_threshold',
+    'max_compaction_threshold',
+    'replicate_on_write',
+    'compaction_strategy_class',
+)
+
+columnfamily_map_options = (
+    ('compaction_strategy_options',
+        ()),
+    ('compression_parameters',
+        ('sstable_compression', 'chunk_length_kb', 'crc_check_chance')),
+)
+
+def cql3_escape_value(value):
+    return cql_escape(value)
+
+def cql3_escape_name(name):
+    return '"%s"' % name.replace('"', '""')
+
+valid_cql3_word_re = re.compile(r'^[a-z][0-9a-z_]*$', re.I)
+
+def is_valid_cql3_name(s):
+    return valid_cql3_word_re.match(s) is not None and s not in keywords
+
+def maybe_cql3_escape_name(name):
+    if is_valid_cql3_name(name):
+        return name
+    return cql3_escape_name(name)
+
+class CqlColumnDef:
+    index_name = None
+
+    def __init__(self, name, cqltype):
+        self.name = name
+        self.cqltype = cqltype
+
+    @classmethod
+    def from_layout(cls, layout):
+        c = cls(layout[u'column'], cql_typename(layout[u'validator']))
+        c.index_name = layout[u'index_name']
+        return c
+
+    def __str__(self):
+        indexstr = ' (index %s)' % self.index_name if self.index_name is not None else ''
+        return '<CqlColumnDef %r %r%s>' % (self.name, self.cqltype, indexstr)
+    __repr__ = __str__
+
+class CqlTableDef:
+    json_attrs = ('column_aliases', 'compaction_strategy_options', 'compression_parameters')
+    composite_type_name = 'org.apache.cassandra.db.marshal.CompositeType'
+    colname_type_name = 'org.apache.cassandra.db.marshal.UTF8Type'
+    column_class = CqlColumnDef
+    compact_storage = False
+
+    key_components = ()
+    columns = ()
+
+    def __init__(self, name):
+        self.name = name
+
+    @classmethod
+    def from_layout(cls, layout, coldefs):
+        cf = cls(name=layout[u'columnfamily'])
+        for attr, val in layout.items():
+            setattr(cf, attr.encode('ascii'), val)
+        for attr in cls.json_attrs:
+            try:
+                setattr(cf, attr, json.loads(getattr(cf, attr)))
+            except AttributeError:
+                pass
+        cf.key_components = [cf.key_alias.decode('ascii')] + list(cf.column_aliases)
+        cf.key_validator = cql_typename(cf.key_validator)
+        cf.default_validator = cql_typename(cf.default_validator)
+        cf.coldefs = coldefs
+        cf.parse_composite()
+        cf.check_assumptions()
+        return cf
+
+    def check_assumptions(self):
+        """
+        be explicit about assumptions being made; warn if not met. if some of
+        these are accurate but not the others, it's not clear whether the
+        right results will come out.
+        """
+
+        # assumption is that all valid CQL tables match the rules in the following table.
+        # if they don't, give a warning and try anyway, but there should be no expectation
+        # of success.
+        #
+        #                               non-null     non-empty     comparator is    entries
in
+        #                             value_alias  column_aliases    composite    schema_columns
+        #                            +----------------------------------------------------------
+        # composite, compact storage |    yes           yes           either           no
+        # composite, dynamic storage |    no            yes            yes             yes
+        # single-column primary key  |    no            no             no             either
+
+        if self.value_alias is not None:
+            # composite cf with compact storage
+            if len(self.coldefs) > 0:
+                warn(UnexpectedTableStructure(
+                        "expected compact storage CF (has value alias) to have no "
+                        "column definitions in system.schema_columns, but found %r"
+                        % (self.coldefs,)))
+            elif len(self.column_aliases) == 0:
+                warn(UnexpectedTableStructure(
+                        "expected compact storage CF (has value alias) to have "
+                        "column aliases, but found none"))
+        elif self.comparator.startswith(self.composite_type_name + '('):
+            # composite cf with dynamic storage
+            if len(self.column_aliases) == 0:
+                warn(UnexpectedTableStructure(
+                        "expected composite key CF to have column aliases, "
+                        "but found none"))
+            elif not self.comparator.endswith(self.colname_type_name + ')'):
+                warn(UnexpectedTableStructure(
+                        "expected non-compact composite CF to have %s as "
+                        "last component of composite comparator, but found %r"
+                        % (self.colname_type_name, self.comparator)))
+            elif len(self.coldefs) == 0:
+                warn(UnexpectedTableStructure(
+                        "expected non-compact composite CF to have entries in "
+                        "system.schema_columns, but found none"))
+        else:
+            # non-composite cf
+            if len(self.column_aliases) > 0:
+                warn(UnexpectedTableStructure(
+                        "expected non-composite CF to have no column aliases, "
+                        "but found %r." % (self.column_aliases,)))
+        num_subtypes = self.comparator.count(',') + 1
+        if self.compact_storage:
+            num_subtypes += 1
+        if len(self.key_components) != num_subtypes:
+            warn(UnexpectedTableStructure(
+                    "expected %r length to be %d, but it's %d. comparator=%r"
+                    % (self.key_components, num_subtypes, len(self.key_components), self.comparator)))
+
+    def parse_composite(self):
+        subtypes = [self.key_validator]
+        if self.comparator.startswith(self.composite_type_name + '('):
+            subtypenames = self.comparator[len(self.composite_type_name) + 1:-1]
+            subtypes.extend(map(cql_typename, subtypenames.split(',')))
+        else:
+            subtypes.append(cql_typename(self.comparator))
+
+        value_cols = []
+        if len(self.column_aliases) > 0:
+            if len(self.coldefs) > 0:
+                # composite cf, dynamic storage
+                subtypes.pop(-1)
+            else:
+                # composite cf, compact storage
+                self.compact_storage = True
+                value_cols = [self.column_class(self.value_alias, self.default_validator)]
+
+        keycols = map(self.column_class, self.key_components, subtypes)
+        normal_cols = map(self.column_class.from_layout, self.coldefs)
+        self.columns = keycols + value_cols + normal_cols
+
+    def __str__(self):
+        return '<%s %s.%s>' % (self.__class__.__name__, self.keyspace, self.name)
+    __repr__ = __str__


Mime
View raw message