示例#1
0
    def test_statement(self):
        ist = InsertStatement('table', None)
        ist.add_assignment_clause(AssignmentClause('a', 'b'))
        ist.add_assignment_clause(AssignmentClause('c', 'd'))

        self.assertEqual(six.text_type(ist),
                         'INSERT INTO table ("a", "c") VALUES (%(0)s, %(1)s)')
示例#2
0
 def test_rendering(self):
     us = UpdateStatement('table')
     us.add_assignment_clause(AssignmentClause('a', 'b'))
     us.add_assignment_clause(AssignmentClause('c', 'd'))
     us.add_where_clause(WhereClause('a', EqualsOperator(), 'x'))
     self.assertEqual(
         six.text_type(us),
         'UPDATE table SET "a" = %(0)s, "c" = %(1)s WHERE "a" = %(2)s',
         six.text_type(us))
示例#3
0
 def test_context_update(self):
     us = UpdateStatement('table')
     us.add_assignment_clause(AssignmentClause('a', 'b'))
     us.add_assignment_clause(AssignmentClause('c', 'd'))
     us.add_where_clause(WhereClause('a', EqualsOperator(), 'x'))
     us.update_context_id(3)
     self.assertEqual(
         six.text_type(us),
         'UPDATE table SET "a" = %(4)s, "c" = %(5)s WHERE "a" = %(3)s')
     self.assertEqual(us.get_context(), {'4': 'b', '5': 'd', '3': 'x'})
示例#4
0
    def test_context_update(self):
        ist = InsertStatement('table', None)
        ist.add_assignment_clause(AssignmentClause('a', 'b'))
        ist.add_assignment_clause(AssignmentClause('c', 'd'))

        ist.update_context_id(4)
        self.assertEqual(six.text_type(ist),
                         'INSERT INTO table ("a", "c") VALUES (%(4)s, %(5)s)')
        ctx = ist.get_context()
        self.assertEqual(ctx, {'4': 'b', '5': 'd'})
示例#5
0
    def save(self):
        """
        Creates / updates a row.
        This is a blind insert call.
        All validation and cleaning needs to happen
        prior to calling this.
        """
        if self.instance is None:
            raise CQLEngineException("DML Query intance attribute is None")
        assert type(self.instance) == self.model

        nulled_fields = set()
        if self.instance._has_counter or self.instance._can_update():
            if self.instance._has_counter:
                warn(
                    "'create' and 'save' actions on Counters are deprecated. A future version will disallow this. Use the 'update' mechanism instead."
                )
            return self.update()
        else:
            insert = InsertStatement(self.column_family_name,
                                     ttl=self._ttl,
                                     timestamp=self._timestamp,
                                     if_not_exists=self._if_not_exists)
            static_save_only = False if len(
                self.instance._clustering_keys) == 0 else True
            for name, col in self.instance._clustering_keys.items():
                static_save_only = static_save_only and col._val_is_null(
                    getattr(self.instance, name, None))
            for name, col in self.instance._columns.items():
                if static_save_only and not col.static and not col.partition_key:
                    continue
                val = getattr(self.instance, name, None)
                if col._val_is_null(val):
                    if self.instance._values[name].changed:
                        nulled_fields.add(col.db_field_name)
                    continue
                insert.add_assignment_clause(
                    AssignmentClause(
                        col.db_field_name,
                        col.to_database(getattr(self.instance, name, None))))

        # skip query execution if it's empty
        # caused by pointless update queries
        if not insert.is_empty:
            self._execute(insert)
        # delete any nulled columns
        if not static_save_only:
            self._delete_null_columns()
示例#6
0
 def test_additional_rendering(self):
     us = UpdateStatement('table', ttl=60)
     us.add_assignment_clause(AssignmentClause('a', 'b'))
     us.add_where_clause(WhereClause('a', EqualsOperator(), 'x'))
     self.assertIn('USING TTL 60', six.text_type(us))
示例#7
0
 def test_context(self):
     us = UpdateStatement('table')
     us.add_assignment_clause(AssignmentClause('a', 'b'))
     us.add_assignment_clause(AssignmentClause('c', 'd'))
     us.add_where_clause(WhereClause('a', EqualsOperator(), 'x'))
     self.assertEqual(us.get_context(), {'0': 'b', '1': 'd', '2': 'x'})
示例#8
0
    def update(self, **values):
        """
        Performs an update on the row selected by the queryset. Include values to update in the
        update like so:

        .. code-block:: python

            Model.objects(key=n).update(value='x')

        Passing in updates for columns which are not part of the model will raise a ValidationError.

        Per column validation will be performed, but instance level validation will not
        (i.e., `Model.validate` is not called).  This is sometimes referred to as a blind update.

        For example:

        .. code-block:: python

            class User(Model):
                id = Integer(primary_key=True)
                name = Text()

            setup(["localhost"], "test")
            sync_table(User)

            u = User.create(id=1, name="jon")

            User.objects(id=1).update(name="Steve")

            # sets name to null
            User.objects(id=1).update(name=None)


        Also supported is blindly adding and removing elements from container columns,
        without loading a model instance from Cassandra.

        Using the syntax `.update(column_name={x, y, z})` will overwrite the contents of the container, like updating a
        non container column. However, adding `__<operation>` to the end of the keyword arg, makes the update call add
        or remove items from the collection, without overwriting then entire column.

        Given the model below, here are the operations that can be performed on the different container columns:

        .. code-block:: python

            class Row(Model):
                row_id      = columns.Integer(primary_key=True)
                set_column  = columns.Set(Integer)
                list_column = columns.List(Integer)
                map_column  = columns.Map(Integer, Integer)

        :class:`~cqlengine.columns.Set`

        - `add`: adds the elements of the given set to the column
        - `remove`: removes the elements of the given set to the column


        .. code-block:: python

            # add elements to a set
            Row.objects(row_id=5).update(set_column__add={6})

            # remove elements to a set
            Row.objects(row_id=5).update(set_column__remove={4})

        :class:`~cqlengine.columns.List`

        - `append`: appends the elements of the given list to the end of the column
        - `prepend`: prepends the elements of the given list to the beginning of the column

        .. code-block:: python

            # append items to a list
            Row.objects(row_id=5).update(list_column__append=[6, 7])

            # prepend items to a list
            Row.objects(row_id=5).update(list_column__prepend=[1, 2])


        :class:`~cqlengine.columns.Map`

        - `update`: adds the given keys/values to the columns, creating new entries if they didn't exist, and overwriting old ones if they did

        .. code-block:: python

            # add items to a map
            Row.objects(row_id=5).update(map_column__update={1: 2, 3: 4})
        """
        if not values:
            return

        nulled_columns = set()
        us = UpdateStatement(self.column_family_name,
                             where=self._where,
                             ttl=self._ttl,
                             timestamp=self._timestamp,
                             transactions=self._transaction)
        for name, val in values.items():
            col_name, col_op = self._parse_filter_arg(name)
            col = self.model._columns.get(col_name)
            # check for nonexistant columns
            if col is None:
                raise ValidationError("{}.{} has no column named: {}".format(
                    self.__module__, self.model.__name__, col_name))
            # check for primary key update attempts
            if col.is_primary_key:
                raise ValidationError(
                    "Cannot apply update to primary key '{}' for {}.{}".format(
                        col_name, self.__module__, self.model.__name__))

            # we should not provide default values in this use case.
            val = col.validate(val)

            if val is None:
                nulled_columns.add(col_name)
                continue

            # add the update statements
            if isinstance(col, columns.Counter):
                # TODO: implement counter updates
                raise NotImplementedError
            elif isinstance(col, (columns.List, columns.Set, columns.Map)):
                if isinstance(col, columns.List):
                    klass = ListUpdateClause
                elif isinstance(col, columns.Set):
                    klass = SetUpdateClause
                elif isinstance(col, columns.Map):
                    klass = MapUpdateClause
                else:
                    raise RuntimeError
                us.add_assignment_clause(
                    klass(col_name, col.to_database(val), operation=col_op))
            else:
                us.add_assignment_clause(
                    AssignmentClause(col_name, col.to_database(val)))

        if us.assignments:
            self._execute(us)

        if nulled_columns:
            ds = DeleteStatement(self.column_family_name,
                                 fields=nulled_columns,
                                 where=self._where)
            self._execute(ds)
示例#9
0
    def update(self):
        """
        updates a row.
        This is a blind update call.
        All validation and cleaning needs to happen
        prior to calling this.
        """
        if self.instance is None:
            raise CQLEngineException("DML Query intance attribute is None")
        assert type(self.instance) == self.model
        null_clustering_key = False if len(
            self.instance._clustering_keys) == 0 else True
        static_changed_only = True
        statement = UpdateStatement(self.column_family_name,
                                    ttl=self._ttl,
                                    timestamp=self._timestamp,
                                    transactions=self._transaction)
        for name, col in self.instance._clustering_keys.items():
            null_clustering_key = null_clustering_key and col._val_is_null(
                getattr(self.instance, name, None))
        # get defined fields and their column names
        for name, col in self.model._columns.items():
            # if clustering key is null, don't include non static columns
            if null_clustering_key and not col.static and not col.partition_key:
                continue
            if not col.is_primary_key:
                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

                static_changed_only = static_changed_only and col.static
                if isinstance(col,
                              (columns.BaseContainerColumn, columns.Counter)):
                    # get appropriate clause
                    if isinstance(col, columns.List):
                        klass = ListUpdateClause
                    elif isinstance(col, columns.Map):
                        klass = MapUpdateClause
                    elif isinstance(col, columns.Set):
                        klass = SetUpdateClause
                    elif isinstance(col, columns.Counter):
                        klass = CounterUpdateClause
                    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:
                        statement.add_assignment_clause(clause)
                else:
                    statement.add_assignment_clause(
                        AssignmentClause(col.db_field_name,
                                         col.to_database(val)))

        if statement.get_context_size() > 0 or self.instance._has_counter:
            for name, col in self.model._primary_keys.items():
                # only include clustering key if clustering key is not null, and non static columns are changed to avoid cql error
                if (null_clustering_key
                        or static_changed_only) and (not col.partition_key):
                    continue
                statement.add_where_clause(
                    WhereClause(col.db_field_name, EqualsOperator(),
                                col.to_database(getattr(self.instance, name))))
            self._execute(statement)

        if not null_clustering_key:
            self._delete_null_columns()
 def test_insert_tuple(self):
     ac = AssignmentClause('a', 'b')
     ac.set_context_id(10)
     self.assertEqual(ac.insert_tuple(), ('a', 10))
示例#11
0
 def test_insert_tuple(self):
     ac = AssignmentClause('a', 'b')
     ac.set_context_id(10)
     self.assertEqual(ac.insert_tuple(), ('a', 10))
示例#12
0
文件: cql.py 项目: sfgxuan/curd
def assignment_clauses_from_data(data):
    assignment_clauses = []
    for k, v in data.items():
        assignment_clauses.append(AssignmentClause(k, v))
    return assignment_clauses
示例#13
0
 def test_additional_rendering(self):
     ist = InsertStatement('table', ttl=60)
     ist.add_assignment_clause(AssignmentClause('a', 'b'))
     ist.add_assignment_clause(AssignmentClause('c', 'd'))
     self.assertIn('USING TTL 60', six.text_type(ist))
 def test_insert_tuple(self):
     ac = AssignmentClause("a", "b")
     ac.set_context_id(10)
     self.assertEqual(ac.insert_tuple(), ("a", 10))