send me a reproducing test case, or at least let me see your mappings. in particular, dont mix a mapping on a table that is also used as "secondary" in a many-to-many relationship.
On Apr 17, 2007, at 5:47 PM, chris e wrote: > > I'm not sure why. But when I do a delete/sql alchemy seems to be > running the save/delete operation twice. Could this be related to a > circular dependency in UOW that is undetected?? When deleting this is > causing the following error because the database delete is done twice: > > sqlalchemy.exceptions.ConcurrentModificationError: Updated rowcount 0 > does not match number of objects updated > > > To fix this I added the following, but it is a serious hack, and > probably needs to be addressed in the unit of work code, but I'm not > sure where to look. Code below. I am on 0.3.5, however I tested > against 0.3.6 as well and this bug appears to be present there as > well. > > > in orm.unitofwork.UnitOfWork > > def _remove_deleted(self, obj): > if hasattr(obj, "_instance_key"): > > # ADDED > # ignore key errors if the item has already been > deleted > try : > del self.identity_map[obj._instance_key] > except KeyError: > pass > try: > self.deleted.remove(obj) > except KeyError: > pass > try: > self.new.remove(obj) > except KeyError: > pass > > > > in orm.mapper.Mapper > > > def delete_obj(self, objects, uowtransaction): > """issue DELETE statements for a list of objects. > > this is called within the context of a UOWTransaction during a > flush operation.""" > > if self.__should_log_debug: > self.__log_debug("delete_obj() start") > > connection = uowtransaction.transaction.connection(self) > > [self.extension.before_delete(self, connection, obj) for obj > in objects] > deleted_objects = util.Set() > for table in self.tables.sort(reverse=True): > if not self._has_pks(table): > continue > delete = [] > for obj in objects: > > # ADDED > # 4/17/07 > # this prevents items from being deleted twice > if hasattr(obj, '_has_been_deleted_') : > continue > > params = {} > if not hasattr(obj, "_instance_key"): > continue > else: > delete.append(params) > for col in self.pks_by_table[table]: > params[col.key] = self.get_attr_by_column(obj, > col) > if self.version_id_col is not None: > params[self.version_id_col.key] = > self.get_attr_by_column(obj, self.version_id_col) > deleted_objects.add(obj) > if len(delete): > def comparator(a, b): > for col in self.pks_by_table[table]: > x = cmp(a[col.key],b[col.key]) > if x != 0: > return x > return 0 > delete.sort(comparator) > clause = sql.and_() > for col in self.pks_by_table[table]: > clause.clauses.append(col == > sql.bindparam(col.key, type=col.type)) > if self.version_id_col is not None: > clause.clauses.append(self.version_id_col == > sql.bindparam(self.version_id_col.key, type=self.version_id_col.type)) > statement = table.delete(clause) > c = connection.execute(statement, delete) > if c.supports_sane_rowcount() and c.rowcount != > len(delete): > raise > exceptions.ConcurrentModificationError("Updated rowcount %d does not > match number of objects updated %d" % (c.cursor.rowcount, > len(delete))) > > # ADDED > # this prevents items from being deleted twice > for obj in deleted_objects : > obj._has_been_deleted_ = True > [self.extension.after_delete(self, connection, obj) for obj in > deleted_objects] > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---