class AbstractCassandraStore(object): def __init__(self, cluster, keyspace, table): self._client = CassandraClient(cluster, keyspace) self._table = table @property def table(self): return self._table @property def keyspace(self): return self._client.keyspace @property def client(self): return self._client def prepare_statement(self, query): return self._client.prepare_statement(query) def execute(self, query_or_statement, parameters=None, timeout=None): return self._client.execute(query_or_statement, parameters, timeout) def delete_all(self): self.execute("TRUNCATE %s" % self.table)
class CassandraUpdateApplier(AbstractUpdateApplier): def __init__(self, cassandra_cluster, settings): document_store = CassandraDocumentStore(cassandra_cluster, settings.cassandra_id_column_name, settings.cassandra_timestamp_column_name) super(CassandraUpdateApplier, self).__init__(document_store) self._cassandra_client = CassandraClient(cassandra_cluster) def _check_namespace_and_table_exists(self, identifier): if not self._cassandra_client.keyspace_exists(identifier.namespace): raise InvalidSchemaException(identifier=identifier, message="Keyspace does not exist on Cassandra.") if not self._cassandra_client.table_exists(identifier.namespace, identifier.table): raise InvalidSchemaException(identifier=identifier, message="Table does not exist on Cassandra.")
class CassandraUpdateApplier(AbstractUpdateApplier): def __init__(self, cassandra_cluster, settings): document_store = CassandraDocumentStore( cassandra_cluster, settings.cassandra_id_column_name, settings.cassandra_timestamp_column_name) super(CassandraUpdateApplier, self).__init__(document_store) self._cassandra_client = CassandraClient(cassandra_cluster) def _check_namespace_and_table_exists(self, identifier): if not self._cassandra_client.keyspace_exists(identifier.namespace): raise InvalidSchemaException( identifier=identifier, message="Keyspace does not exist on Cassandra.") if not self._cassandra_client.table_exists(identifier.namespace, identifier.table): raise InvalidSchemaException( identifier=identifier, message="Table does not exist on Cassandra.")
def __init__(self, cluster, keyspace, table): self._client = CassandraClient(cluster, keyspace) self._table = table
def __init__(self, cluster, id_column_name=_DEFAULT_ID_COLUMN_NAME, timestamp_column_name=_DEFAULT_TIMESTAMP_COLUMN_NAME): self._client = CassandraClient(cluster) self._id_column_name = id_column_name self._timestamp_column_name = timestamp_column_name
class CassandraDocumentStore(object): def __init__(self, cluster, id_column_name=_DEFAULT_ID_COLUMN_NAME, timestamp_column_name=_DEFAULT_TIMESTAMP_COLUMN_NAME): self._client = CassandraClient(cluster) self._id_column_name = id_column_name self._timestamp_column_name = timestamp_column_name def read(self, identifier): statement = self._client.prepare_statement( """ SELECT * FROM %s.%s WHERE %s=%s """ % (identifier.namespace, identifier.table, self._id_column_name, identifier.key) ) rows = self._client.execute(statement) return self._to_document(identifier, rows) def create(self, document): identifier = document.identifier statement = self._client.prepare_statement( """ INSERT INTO %s.%s (%s,%s,%s) VALUES (%s,?,%s) """ % (identifier.namespace, identifier.table, self._id_column_name, self._timestamp_column_name, self.__get_field_names_for_insert_cql_string(document), identifier.key, self.__get_question_marks_string(document)) ) arguments = [self.__get_timestamp(document)] arguments.extend(self.__get_field_values(document, statement)) self._client.execute(statement, arguments) def update(self, document): identifier = document.identifier statement = self._client.prepare_statement( """ UPDATE %s.%s SET %s=?,%s WHERE %s=%s """ % (identifier.namespace, identifier.table, self._timestamp_column_name, self.__get_field_names_for_update_cql_string(document), self._id_column_name, identifier.key) ) arguments = [self.__get_timestamp(document)] arguments.extend(self.__get_field_values(document, statement)) self._client.execute(statement, arguments) def delete(self, identifier): statement = self._client.prepare_statement( """ DELETE FROM %s.%s WHERE %s=%s """ % (identifier.namespace, identifier.table, self._id_column_name, identifier.key) ) self._client.execute(statement) @classmethod def __get_timestamp(cls, document): return TimestampUtil.seconds_to_milliseconds(document.timestamp) @classmethod def __get_field_names_for_insert_cql_string(cls, document): names = [] for field in document.fields: names.append(field.name) return ",".join(names) @classmethod def __get_field_names_for_update_cql_string(cls, document): names = [] for field in document.fields: names.append("%s=?" % field.name) return ",".join(names) @classmethod def __get_question_marks_string(cls, document): question_marks = [] for _ in document.fields: question_marks.append("?") return ",".join(question_marks) @classmethod def __get_column_types(cls, statement): types = dict() for metadata in statement.column_metadata: types[metadata[2].lower()] = metadata[3] return types @classmethod def __get_field_values(cls, document, statement): column_types = cls.__get_column_types(statement) values = [] for field in document.fields: value = cls.__serialize_field_value(field.value, column_types[field.name.lower()]) values.append(value) return values @classmethod def __serialize_field_value(cls, value, column_type): if isinstance(value, str) or isinstance(value, unicode): if column_type == cassandra.cqltypes.DecimalType: return Decimal(value) if column_type == cassandra.cqltypes.UUIDType: return UUID(value) if column_type == cassandra.cqltypes.TimeUUIDType: return UUID(value) if column_type == cassandra.cqltypes.DateType: return arrow.get(value) return value def _to_document(self, identifier, rows): if len(rows) == 0: return None elif len(rows) > 1: raise InvalidSchemaException(identifier=identifier, message=("More than one row found for entity on Cassandra. " + "Please make sure the schema has a single primary key column with name '%s'. ") % self._id_column_name) row = rows[0] if not hasattr(row, self._timestamp_column_name): raise InvalidSchemaException(identifier=identifier, message=("No timestamp column found for entity on Cassandra. " + "Please make sure the schema has a timestamp column with name '%s'. ") % self._timestamp_column_name) document = Document() document.identifier = identifier timestamp = attrgetter(self._timestamp_column_name)(row) if timestamp: document.timestamp = arrow.get(timestamp).float_timestamp for field_name in row.__dict__: if field_name != self._timestamp_column_name and field_name != self._id_column_name: field_value = attrgetter(field_name)(row) document.add_field(field_name, field_value) return document
def __init__(self, cassandra_cluster, settings): document_store = CassandraDocumentStore(cassandra_cluster, settings.cassandra_id_column_name, settings.cassandra_timestamp_column_name) super(CassandraUpdateApplier, self).__init__(document_store) self._cassandra_client = CassandraClient(cassandra_cluster)
def __init__(self, cassandra_cluster, settings): document_store = CassandraDocumentStore( cassandra_cluster, settings.cassandra_id_column_name, settings.cassandra_timestamp_column_name) super(CassandraUpdateApplier, self).__init__(document_store) self._cassandra_client = CassandraClient(cassandra_cluster)
def cassandra_client(cassandra_cluster): return CassandraClient(cassandra_cluster)