From 7d0c5f72f9e6bd811f741c6f553e81b4093c252f Mon Sep 17 00:00:00 2001 From: Ants Aasma Date: Mon, 20 Apr 2009 15:00:41 +0000 Subject: [PATCH] Query.update() and Query.delete() should turn off eagerloads. Fixes #1378. --- CHANGES | 3 +++ lib/sqlalchemy/orm/query.py | 4 +++ test/orm/query.py | 51 +++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/CHANGES b/CHANGES index a2dfd7af74..c5fde33cd5 100644 --- a/CHANGES +++ b/CHANGES @@ -41,6 +41,9 @@ CHANGES owned by an object being deleted would not be set to None if the relation() was self-referential. [ticket:1376] + - Fixed Query.update() and Query.delete() failures with eagerloaded + relations. [ticket:1378] + - schema - Added a quote_schema() method to the IdentifierPreparer class so that dialects can override how schemas get handled. This diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 9dba9edad4..e8169faa2e 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -1549,6 +1549,8 @@ class Query(object): if synchronize_session not in [False, 'evaluate', 'fetch']: raise sa_exc.ArgumentError("Valid strategies for session synchronization are False, 'evaluate' and 'fetch'") + self = self.enable_eagerloads(False) + context = self._compile_context() if len(context.statement.froms) != 1 or not isinstance(context.statement.froms[0], schema.Table): raise sa_exc.ArgumentError("Only deletion via a single table query is currently supported") @@ -1643,6 +1645,8 @@ class Query(object): if synchronize_session not in [False, 'evaluate', 'expire']: raise sa_exc.ArgumentError("Valid strategies for session synchronization are False, 'evaluate' and 'expire'") + self = self.enable_eagerloads(False) + context = self._compile_context() if len(context.statement.froms) != 1 or not isinstance(context.statement.froms[0], schema.Table): raise sa_exc.ArgumentError("Only update via a single table query is currently supported") diff --git a/test/orm/query.py b/test/orm/query.py index 1d13a6c459..11d3377e8a 100644 --- a/test/orm/query.py +++ b/test/orm/query.py @@ -2792,10 +2792,18 @@ class UpdateDeleteTest(_base.MappedTest): Column('id', Integer, primary_key=True), Column('name', String(32)), Column('age', Integer)) + + Table('documents', metadata, + Column('id', Integer, primary_key=True), + Column('user_id', None, ForeignKey('users.id')), + Column('title', String(32))) def setup_classes(self): class User(_base.ComparableEntity): pass + + class Document(_base.ComparableEntity): + pass @testing.resolve_artifact_names def insert_data(self): @@ -2805,10 +2813,21 @@ class UpdateDeleteTest(_base.MappedTest): dict(id=3, name='jill', age=29), dict(id=4, name='jane', age=37), ]) + + @testing.resolve_artifact_names + def insert_documents(self): + documents.insert().execute([ + dict(id=1, user_id=1, title='foo'), + dict(id=2, user_id=1, title='bar'), + dict(id=3, user_id=2, title='baz'), + ]) @testing.resolve_artifact_names def setup_mappers(self): mapper(User, users) + mapper(Document, documents, properties={ + 'user': relation(User, lazy=False, backref=backref('documents', lazy=True)) + }) @testing.resolve_artifact_names def test_delete(self): @@ -2990,5 +3009,37 @@ class UpdateDeleteTest(_base.MappedTest): rowcount = sess.query(User).filter(User.age > 26).delete(synchronize_session=False) self.assertEquals(rowcount, 3) + @testing.resolve_artifact_names + def test_update_with_eager_relations(self): + self.insert_documents() + + sess = create_session(bind=testing.db, autocommit=False) + + foo,bar,baz = sess.query(Document).order_by(Document.id).all() + sess.query(Document).filter(Document.user_id == 1).update({'title': Document.title+Document.title}, synchronize_session='evaluate') + + eq_([foo.title, bar.title, baz.title], ['foofoo','barbar', 'baz']) + eq_(sess.query(Document.title).order_by(Document.id).all(), zip(['foofoo','barbar', 'baz'])) + + @testing.resolve_artifact_names + def test_update_with_explicit_eagerload(self): + sess = create_session(bind=testing.db, autocommit=False) + + john,jack,jill,jane = sess.query(User).order_by(User.id).all() + sess.query(User).options(eagerload(User.documents)).filter(User.age > 29).update({'age': User.age - 10}, synchronize_session='expire') + + eq_([john.age, jack.age, jill.age, jane.age], [25,37,29,27]) + eq_(sess.query(User.age).order_by(User.id).all(), zip([25,37,29,27])) + + @testing.resolve_artifact_names + def test_delete_with_eager_relations(self): + self.insert_documents() + + sess = create_session(bind=testing.db, autocommit=False) + + sess.query(Document).filter(Document.user_id == 1).delete(synchronize_session=False) + + eq_(sess.query(Document.title).all(), zip(['baz'])) + if __name__ == '__main__': testenv.main() -- 2.47.2