From 6560bfc24ce516e9fe568ca4012d91aefa4a8bb3 Mon Sep 17 00:00:00 2001 From: Adam Holmberg Date: Fri, 19 Feb 2016 14:03:08 -0600 Subject: [PATCH] cqle: make the distinction btw collections and containers Makes the DML update query treat tuples as simple values, rather than special container types. --- cassandra/cqlengine/columns.py | 80 ++++++++++++++++++---------------- cassandra/cqlengine/query.py | 3 -- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index 45da2fce..623e086a 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -607,7 +607,7 @@ class Decimal(Column): return self.validate(value) -class BaseContainerColumn(Column): +class BaseCollectionColumn(Column): """ Base Container type for collection-like columns. @@ -630,10 +630,10 @@ class BaseContainerColumn(Column): instances.append(inst) self.types = instances - super(BaseContainerColumn, self).__init__(**kwargs) + super(BaseCollectionColumn, self).__init__(**kwargs) def validate(self, value): - value = super(BaseContainerColumn, self).validate(value) + value = super(BaseCollectionColumn, self).validate(value) # It is dangerous to let collections have more than 65535. # See: https://issues.apache.org/jira/browse/CASSANDRA-5428 if value is not None and len(value) > 65535: @@ -652,6 +652,45 @@ class BaseContainerColumn(Column): return self.types +class Tuple(BaseCollectionColumn): + """ + Stores a fixed-length set of positional values + + http://docs.datastax.com/en/cql/3.1/cql/cql_reference/tupleType.html + """ + def __init__(self, *args, **kwargs): + """ + :param args: column types representing tuple composition + """ + if not args: + raise ValueError("Tuple must specify at least one inner type") + super(Tuple, self).__init__(args, **kwargs) + self.db_type = 'tuple<{0}>'.format(', '.join(typ.db_type for typ in self.types)) + + def validate(self, value): + val = super(Tuple, self).validate(value) + if val is None: + return + if len(val) > len(self.types): + raise ValidationError("Value %r has more fields than tuple definition (%s)" % + (val, ', '.join(t for t in self.types))) + return tuple(t.validate(v) for t, v in zip(self.types, val)) + + def to_python(self, value): + if value is None: + return tuple() + return tuple(t.to_python(v) for t, v in zip(self.types, value)) + + def to_database(self, value): + if value is None: + return + return tuple(t.to_database(v) for t, v in zip(self.types, value)) + + +class BaseContainerColumn(BaseCollectionColumn): + pass + + class Set(BaseContainerColumn): """ Stores a set of unordered, unique values @@ -787,41 +826,6 @@ class Map(BaseContainerColumn): return dict((self.key_col.to_database(k), self.value_col.to_database(v)) for k, v in value.items()) -class Tuple(BaseContainerColumn): - """ - Stores a fixed-length set of positional values - - http://docs.datastax.com/en/cql/3.1/cql/cql_reference/tupleType.html - """ - def __init__(self, *args, **kwargs): - """ - :param args: column types representing tuple composition - """ - if not args: - raise ValueError("Tuple must specify at least one inner type") - super(Tuple, self).__init__(args, **kwargs) - self.db_type = 'tuple<{0}>'.format(', '.join(typ.db_type for typ in self.types)) - - def validate(self, value): - val = super(Tuple, self).validate(value) - if val is None: - return - if len(val) > len(self.types): - raise ValidationError("Value %r has more fields than tuple definition (%s)" % - (val, ', '.join(t for t in self.types))) - return tuple(t.validate(v) for t, v in zip(self.types, val)) - - def to_python(self, value): - if value is None: - return tuple() - return tuple(t.to_python(v) for t, v in zip(self.types, value)) - - def to_database(self, value): - if value is None: - return - return tuple(t.to_database(v) for t, v in zip(self.types, value)) - - class UDTValueManager(BaseValueManager): @property def changed(self): diff --git a/cassandra/cqlengine/query.py b/cassandra/cqlengine/query.py index c1d07b45..4d033442 100644 --- a/cassandra/cqlengine/query.py +++ b/cassandra/cqlengine/query.py @@ -1151,11 +1151,9 @@ class DMLQuery(object): val = getattr(self.instance, name, None) val_mgr = self.instance._values[name] - # don't update something that is null if val is None: continue - # don't update something if it hasn't changed if not val_mgr.changed and not isinstance(col, columns.Counter): continue @@ -1173,7 +1171,6 @@ class DMLQuery(object): else: raise RuntimeError - # do the stuff clause = klass(col.db_field_name, val, previous=val_mgr.previous_value, column=col) if clause.get_context_size() > 0: