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)