summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2011-07-30 12:12:32 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2011-07-30 12:12:32 -0400
commitde0e2724c5a85586e98f524bba85b69e3ae6a21e (patch)
treef79df2135ac6a4734e35cd296670730f6c9db62f
parenta45da117889edba7ec0906d3af3fff7d83e5373a (diff)
downloadsqlalchemy-de0e2724c5a85586e98f524bba85b69e3ae6a21e.tar.gz
- Fixed bug where query.join() + aliased=True
from a joined-inh structure to itself on relationship() with join condition on the child table would convert the lead entity into the joined one inappropriately. [ticket:2234] Also in 0.6.9.
-rw-r--r--CHANGES7
-rw-r--r--lib/sqlalchemy/orm/query.py2
-rw-r--r--test/orm/inheritance/test_query.py112
3 files changed, 120 insertions, 1 deletions
diff --git a/CHANGES b/CHANGES
index 9a39c613e..59139fd99 100644
--- a/CHANGES
+++ b/CHANGES
@@ -38,6 +38,13 @@ CHANGES
a fix for multiply-nested any()/has() constructs
against a joined table structure. [ticket:2195]
+ - Fixed bug where query.join() + aliased=True
+ from a joined-inh structure to itself on
+ relationship() with join condition on the child
+ table would convert the lead entity into the
+ joined one inappropriately. [ticket:2234]
+ Also in 0.6.9.
+
- Fixed regression from 0.6 where Session.add()
against an object which contained None in a
collection would raise an internal exception.
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index a3b13abb2..d9c67d56c 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -1535,7 +1535,7 @@ class Query(object):
# which is intended to wrap a the right side in a subquery,
# ensure that columns retrieved from this target in the result
# set are also adapted.
- if aliased_entity:
+ if aliased_entity and not create_aliases:
self.__mapper_loads_polymorphically_with(
right_mapper,
ORMAdapter(
diff --git a/test/orm/inheritance/test_query.py b/test/orm/inheritance/test_query.py
index 23052f997..2560d2284 100644
--- a/test/orm/inheritance/test_query.py
+++ b/test/orm/inheritance/test_query.py
@@ -1083,7 +1083,119 @@ class SelfReferentialJ2JTest(fixtures.MappedTest):
[m1]
)
+class SelfReferentialJ2JSelfTest(fixtures.MappedTest):
+ run_setup_mappers = 'once'
+
+ @classmethod
+ def define_tables(cls, metadata):
+ people = Table('people', metadata,
+ Column('person_id', Integer,
+ primary_key=True, test_needs_autoincrement=True),
+ Column('name', String(50)),
+ Column('type', String(30)))
+
+ engineers = Table('engineers', metadata,
+ Column('person_id', Integer,
+ ForeignKey('people.person_id'), primary_key=True),
+ Column('reports_to_id', Integer,
+ ForeignKey('engineers.person_id'))
+ )
+
+
+ @classmethod
+ def setup_mappers(cls):
+ engineers, people = (cls.tables.engineers,
+ cls.tables.people)
+
+ mapper(Person, people, polymorphic_on=people.c.type,
+ polymorphic_identity='person')
+
+ mapper(Engineer, engineers, inherits=Person,
+ polymorphic_identity='engineer', properties={
+ 'reports_to':relationship(Engineer,
+ primaryjoin=engineers.c.person_id==engineers.c.reports_to_id,
+ backref='engineers',
+ remote_side=engineers.c.person_id)
+ })
+ def _two_obj_fixture(self):
+ e1 = Engineer(name='wally')
+ e2 = Engineer(name='dilbert',
+ reports_to=e1)
+ sess = Session()
+ sess.add_all([e1, e2])
+ sess.commit()
+ return sess
+
+ def _five_obj_fixture(self):
+ sess =Session()
+ e1, e2, e3, e4, e5 = [
+ Engineer(name='e%d' % (i + 1)) for i in xrange(5)
+ ]
+ e3.reports_to=e1
+ e4.reports_to=e2
+ sess.add_all([e1, e2, e3, e4, e5])
+ sess.commit()
+ return sess
+
+ def test_has(self):
+ sess = self._two_obj_fixture()
+
+ eq_(
+ sess.query(Engineer).
+ filter(Engineer.reports_to.has(Engineer.name=='wally')).
+ first(),
+ Engineer(name='dilbert'))
+
+ def test_join_explicit_alias(self):
+ sess = self._five_obj_fixture()
+
+ ea = aliased(Engineer)
+ eq_(
+ sess.query(Engineer).
+ join(ea, Engineer.engineers).
+ filter(Engineer.name=='e1').all(),
+ [Engineer(name='e1')]
+ )
+
+ def test_join_aliased_flag_one(self):
+ sess = self._two_obj_fixture()
+
+ eq_(
+ sess.query(Engineer).
+ join('reports_to', aliased=True).
+ filter(Engineer.name=='wally').first(),
+ Engineer(name='dilbert')
+ )
+
+ def test_join_aliased_flag_two(self):
+ sess = self._five_obj_fixture()
+
+ eq_(
+ sess.query(Engineer).
+ join(Engineer.engineers, aliased=True).
+ filter(Engineer.name=='e4').all(),
+ [Engineer(name='e2')]
+ )
+
+
+ def test_relationship_compare(self):
+ sess = self._five_obj_fixture()
+
+ eq_(
+ sess.query(Engineer).
+ join(Engineer.engineers, aliased=True).
+ filter(Engineer.reports_to==None).all(),
+ []
+ )
+
+ e1 = sess.query(Engineer).filter_by(name='e1').one()
+ eq_(
+ sess.query(Engineer).
+ join(Engineer.engineers, aliased=True).
+ filter(Engineer.reports_to==e1).all(),
+ [e1]
+ )
class M2MFilterTest(fixtures.MappedTest):
run_setup_mappers = 'once'