def __setitem__(self, key, value): key_column = self._sqldict.child_key_column.column for validator in self._sqldict.child_key_column.validators: validator.check(self._dbobj, self._sqldict.child_key_column, key) key_literal = self._sqldict.child_key_column.sql_literal_class( self._sqldict.child_key_column.__convert__(key)) value_column = self._sqldict.child_value_column.column for validator in self._sqldict.child_value_column.validators: validator.check(self._dbobj, self._sqldict.child_value_column, value) value_literal = self._sqldict.child_value_column.sql_literal_class( self._sqldict.child_value_column.__convert__(value)) if self.has_key(key): if self[key] != value: where = sql.where.and_(self._sqldict.child_where(self._dbobj), sql.where(key_column, "=", key_literal)) command = sql.update(self._sqldict.child_relation, where, { str(value_column): value_literal }) else: command = None else: command = sql.insert( self._sqldict.child_relation, ( self._sqldict.child_key, key_column, value_column, ), ( self._dbobj.__primary_key__.sql_literal(), key_literal, value_literal, ) ) if command is not None: self._dbobj.__ds__().execute(command) dict.__setitem__(self, key, value)
def insert(self, dbobj, dont_select=False, cursor=None): """ @param dbobj: The dbobj to be inserted (must not be created by a select statement. @param dont_select: Do not perform a SELECT query for those columns whoes values are provided by the backend, either through AUTO_INCREMENT mechanisms or default column values. """ if dbobj.__is_stored__(): raise ObjectAlreadyInserted(repr(dbobj)) sql_columns = [] sql_values = [] for property in dbobj.__dbproperties__(): if property.isset(dbobj) and property.column not in sql_columns: update_expression = property.update_expression(dbobj) if update_expression is not None: sql_columns.append(property.column) sql_values.append(update_expression) if len(sql_columns) == 0: raise DBObjContainsNoData( "Please set at least one of the attributes of this dbobj") statement = sql.insert(dbobj.__relation__, sql_columns, sql_values) self.execute(statement) dbobj.__insert__(self) if dbobj.__primary_key__ is not None and not dont_select: self.select_after_insert(dbobj) return cursor
def __set__(self, dbobj, new_values): self.check_dbobj(dbobj) if new_values is None: raise ValueError("You cannot set a sqltuple to None, sorry.") # Convert each of the values in the new tuple to the # child_column's type and run its validators on each of them. new = [] for value in new_values: value = self.child_column.__convert__(value) for validator in self.child_column.validators: validator.check(dbobj, self, value) new.append(value) # Let's see if it's just an addition of values. In that case # we'll not delete anything, just create a couple of INSERT # statements. if self.isset(dbobj): dont_delete = True old = getattr(dbobj, self.data_attribute_name()) if len(old) <= len(new): for o, n in zip(old, new): if o != n: dont_delete = False break else: old = () dont_delete = False if dont_delete: to_insert = new[len(old):] else: to_insert = new dbobj.__ds__().execute(sql.delete(self.child_relation, self.child_where(dbobj))) for value in to_insert: if value is None: literal = sql.NULL else: literal = self.child_column.sql_literal_class(value) dbobj.__ds__().execute( sql.insert(self.child_relation, ( self.child_key, self.child_column.column, ), ( dbobj.__primary_key__.sql_literal(), literal, ) )) setattr(dbobj, self.data_attribute_name(), tuple(new))
def append(self, *new_child_objects): """ Appends new child objects to the parent's many2many dbproperty. """ for dbobj in new_child_objects: if not isinstance(dbobj, self.child_class()): msg = "This relationship can only handle %s" % \ repr(self.child_class()) raise TypeError(msg) if not dbobj.__is_stored__(): # The many2many relationship will insert fresh objects # into the database. self.ds().insert(dbobj) # insert a row into the link_relation command = sql.insert(self.relationship.link_relation, ( self.relationship.parent_link_column(self.dbobj), self.relationship.child_link_column(), ), ( self.relationship.parent_own_key( self.dbobj).sql_literal(self.dbobj), self.relationship.child_own_key().sql_literal(dbobj), )) self.ds().execute(command)
def __set__(self, dbobj, new_dict): if new_dict is None: raise ValueError("You cannot set a sqldict to None, sorry.") self.check_dbobj(dbobj) if self.isset(dbobj): # We have a new version of the dict in memory and can compare # values against it. old_dict = getattr(dbobj, self.data_attribute_name()) old_dict.update(new_dict) new_keys = set(new_dict.keys()) old_keys = set(old_dict.keys()) obsolete_keys = old_keys.difference(new_keys) for key in obsolete_keys: old_dict[key] else: if dbobj.__ds__(): raise ValueError("Can’t initialize a sqldict on " "dbobject creation, only after insert().") # Convert each of the keys and values in the new dict to the # appropriate types and run the validators on each of the values. new = {} for key, value in new_dict.items(): key = self.child_key_column.__convert__(key) value = self.child_value_column.__convert__(value) for validator in self.child_key_column.validators: validator.check(dbobj, self, key) for validator in self.child_value_column.validators: validator.check(dbobj, self, value) new[key] = value # Delete the rows currently in the database dbobj.__ds__().execute(sql.delete(self.child_relation, self.child_where(dbobj))) # And insert new ones for key, value in new.items(): key_literal = self.child_key_column.sql_literal_class( self.child_key_column.__convert__(key)) if value is None: value_literal = sql.NULL else: value_literal = self.child_value_column.sql_literal_class( self.child_value_column.__convert__(value)) query = sql.insert( self.child_relation, ( self.child_key, self.child_key_column.column, self.child_value_column.column, ), ( dbobj.__primary_key__.sql_literal(), key_literal, value_literal, ) ) dbobj.__ds__().execute(query) setattr(dbobj, self.data_attribute_name(), self.sqldict_dict(self, dbobj, new))