Hi there, Michael Bayer wrote: > I would say it should > be called in any case, rows or not, and the result object provided. > Just provide a patch and we're GTG.
Done. The patch is attached. I can commit it myself if it looks all right. > I wonder if a before_ hook should be provided as well. I don't know myself; Laurence, if you're listening in perhaps you'd care to comment? Regards, Martijn --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Index: test/orm/session.py =================================================================== --- test/orm/session.py (revision 5241) +++ test/orm/session.py (working copy) @@ -898,7 +898,9 @@ log.append('after_begin') def after_attach(self, session, instance): log.append('after_attach') - + def after_bulk_operation(self, session, result): + log.append('after_bulk_operation') + sess = create_session(extension = MyExt()) u = User(name='u1') sess.add(u) @@ -920,12 +922,21 @@ log = [] sess.commit() assert log == ['before_commit', 'after_commit'] + + log = [] + sess.query(User).delete() + assert log == ['after_begin', 'after_bulk_operation'] + + log = [] + sess.query(User).update({'name': 'foo'}) + assert log == ['after_bulk_operation'] log = [] sess = create_session(autocommit=False, extension=MyExt(), bind=testing.db) conn = sess.connection() assert log == ['after_begin'] + @testing.resolve_artifact_names def test_before_flush(self): """test that the flush plan can be affected during before_flush()""" Index: lib/sqlalchemy/orm/query.py =================================================================== --- lib/sqlalchemy/orm/query.py (revision 5241) +++ lib/sqlalchemy/orm/query.py (working copy) @@ -1347,6 +1347,9 @@ if identity_key in session.identity_map: session._remove_newly_deleted(attributes.instance_state(session.identity_map[identity_key])) + for ext in session.extensions: + ext.after_bulk_operation(session, result) + return result.rowcount def update(self, values, synchronize_session='expire'): @@ -1441,6 +1444,9 @@ if identity_key in session.identity_map: session.expire(session.identity_map[identity_key], values.keys()) + for ext in session.extensions: + ext.after_bulk_operation(session, result) + return result.rowcount def _compile_context(self, labels=True): Index: lib/sqlalchemy/orm/interfaces.py =================================================================== --- lib/sqlalchemy/orm/interfaces.py (revision 5241) +++ lib/sqlalchemy/orm/interfaces.py (working copy) @@ -307,6 +307,15 @@ This is called after an add, delete or merge. """ + def after_bulk_operation(self, session, result): + """Execute after a bulk operation to the session. + + This is called after a session.query().delete() and + session.query().update(). + + 'result' is the result object returned from the bulk operation. + """ + class MapperProperty(object): """Manage the relationship of a ``Mapper`` to a single class attribute, as well as that attribute as it appears on individual