From cdf727aeb258b24ca3ee1e52b19dd862ada8c249 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 20 Jul 2011 18:03:35 -0400 Subject: [PATCH] - Fixed bug whereby the source clause used by query.join() would be inconsistent if against a column expression that combined multiple entities together. [ticket:2197] --- CHANGES | 6 ++++ lib/sqlalchemy/orm/query.py | 3 +- test/orm/test_froms.py | 65 ++++++++++++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index d4804c1c18..679f2c2594 100644 --- a/CHANGES +++ b/CHANGES @@ -32,6 +32,12 @@ CHANGES _with_invoke_all_eagers() which selects old/new behavior [ticket:2213] + - Fixed bug whereby the source clause + used by query.join() would be inconsistent + if against a column expression that combined + multiple entities together. [ticket:2197] + Also in 0.6.9 + - Fixed bug whereby if a mapped class redefined __hash__() or __eq__() to something non-standard, which is a supported use case diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index a3901868a8..1b6b8986cc 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -2861,7 +2861,8 @@ class _ColumnEntity(_QueryEntity): def setup_entity(self, entity, mapper, adapter, from_obj, is_aliased_class, with_polymorphic): - self.selectable = from_obj + if 'selectable' not in self.__dict__: + self.selectable = from_obj self.froms.add(from_obj) def corresponds_to(self, entity): diff --git a/test/orm/test_froms.py b/test/orm/test_froms.py index 0a2617a6b5..b762721aff 100644 --- a/test/orm/test_froms.py +++ b/test/orm/test_froms.py @@ -941,6 +941,7 @@ class InstancesTest(QueryTest, AssertsCompiledSQL): class MixedEntitiesTest(QueryTest, AssertsCompiledSQL): + __dialect__ = 'default' def test_values(self): Address, users, User = (self.classes.Address, @@ -1014,8 +1015,7 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL): self.assert_compile( q, "SELECT foobar.id AS foobar_id, " - "foobar.name AS foobar_name FROM users AS foobar", - use_default_dialect=True + "foobar.name AS foobar_name FROM users AS foobar" ) @testing.fails_on('mssql', 'FIXME: unknown') @@ -1297,7 +1297,7 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL): "orders.description AS orders_description, " "'q' AS foo FROM orders WHERE " "orders.description = :description_1) AS " - "anon_1", use_default_dialect=True) + "anon_1") eq_( q.all(), [(3, u'order 3', 'q')] @@ -1400,8 +1400,7 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL): ' AS addresses_email_address FROM users, ' 'addresses WHERE users.id = :id_1 AND ' 'addresses.user_id = users.id ORDER BY ' - 'users.name', - use_default_dialect=True) + 'users.name') def test_multi_columns(self): @@ -1522,6 +1521,62 @@ class MixedEntitiesTest(QueryTest, AssertsCompiledSQL): assert q.all() == expected sess.expunge_all() + def test_expression_selectable_matches_mzero(self): + User, Address = self.classes.User, self.classes.Address + + ua = aliased(User) + aa = aliased(Address) + s = create_session() + for crit, j, exp in [ + (User.id + Address.id, User.addresses, + "SELECT users.id + addresses.id AS anon_1 " + "FROM users JOIN addresses ON users.id = " + "addresses.user_id" + ), + (User.id + Address.id, Address.user, + "SELECT users.id + addresses.id AS anon_1 " + "FROM addresses JOIN users ON users.id = " + "addresses.user_id" + ), + (Address.id + User.id, User.addresses, + "SELECT addresses.id + users.id AS anon_1 " + "FROM users JOIN addresses ON users.id = " + "addresses.user_id" + ), + (User.id + aa.id, (aa, User.addresses), + "SELECT users.id + addresses_1.id AS anon_1 " + "FROM users JOIN addresses AS addresses_1 " + "ON users.id = addresses_1.user_id" + ), + ]: + q = s.query(crit) + mzero = q._mapper_zero() + assert mzero.mapped_table is q._entity_zero().selectable + q = q.join(j) + self.assert_compile(q, exp) + + for crit, j, exp in [ + (ua.id + Address.id, ua.addresses, + "SELECT users_1.id + addresses.id AS anon_1 " + "FROM users AS users_1 JOIN addresses " + "ON users_1.id = addresses.user_id"), + (ua.id + aa.id, (aa, ua.addresses), + "SELECT users_1.id + addresses_1.id AS anon_1 " + "FROM users AS users_1 JOIN addresses AS " + "addresses_1 ON users_1.id = addresses_1.user_id"), + (ua.id + aa.id, (ua, aa.user), + "SELECT users_1.id + addresses_1.id AS anon_1 " + "FROM addresses AS addresses_1 JOIN " + "users AS users_1 " + "ON users_1.id = addresses_1.user_id") + ]: + q = s.query(crit) + mzero = q._mapper_zero() + assert mzero._AliasedClass__alias is q._entity_zero().selectable + q = q.join(j) + self.assert_compile(q, exp) + + class SelectFromTest(QueryTest, AssertsCompiledSQL): run_setup_mappers = None -- 2.39.5