From 931decd84576e4ec61af317424ed683c4576f02a Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 27 Jan 2007 01:40:26 +0000 Subject: [PATCH] - eager relation to an inheriting mapper wont fail if no rows returned for the relationship. --- CHANGES | 2 ++ lib/sqlalchemy/orm/mapper.py | 9 ++--- test/orm/inheritance5.py | 68 ++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index dc47d49787..6fdd407136 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,8 @@ for many-to-one relationships to polymorphic unions that did not contain the base table [ticket:439]. the lazy/eager clause adaption to the selectable will match up on straight column names (i.e. its a more liberal policy) + - eager relation to an inheriting mapper wont fail if no rows returned for + the relationship. - oracle: - when returning "rowid" as the ORDER BY column or in use with ROW_NUMBER OVER, oracle dialect checks the selectable its being applied to and will switch to diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index df09402bf7..4cdf62227d 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1157,10 +1157,11 @@ class Mapper(object): if self.polymorphic_on is not None: discriminator = row[self.polymorphic_on] - mapper = self.polymorphic_map[discriminator] - if mapper is not self: - row = self.translate_row(mapper, row) - return mapper._instance(context, row, result=result) + if discriminator is not None: + mapper = self.polymorphic_map[discriminator] + if mapper is not self: + row = self.translate_row(mapper, row) + return mapper._instance(context, row, result=result) # look in main identity map. if its there, we dont do anything to it, # including modifying any of its related items lists, as its already diff --git a/test/orm/inheritance5.py b/test/orm/inheritance5.py index af1a4918ce..4a90772b44 100644 --- a/test/orm/inheritance5.py +++ b/test/orm/inheritance5.py @@ -301,6 +301,74 @@ class RelationTest4(testbase.AssertMixin): car1 = session.query(Car).options(eagerload('employee')).get(car1.car_id) assert str(car1.employee) == "Engineer E4, status X" +class RelationTest5(testbase.AssertMixin): + def setUpAll(self): + global metadata, people, engineers, managers, cars + metadata = BoundMetaData(testbase.db) + people = Table('people', metadata, + Column('person_id', Integer, primary_key=True), + Column('name', String(50)), + Column('type', String(50))) + + engineers = Table('engineers', metadata, + Column('person_id', Integer, ForeignKey('people.person_id'), primary_key=True), + Column('status', String(30))) + + managers = Table('managers', metadata, + Column('person_id', Integer, ForeignKey('people.person_id'), primary_key=True), + Column('longer_status', String(70))) + + cars = Table('cars', metadata, + Column('car_id', Integer, primary_key=True), + Column('owner', Integer, ForeignKey('people.person_id'))) + metadata.create_all() + def tearDownAll(self): + metadata.drop_all() + def tearDown(self): + clear_mappers() + for t in metadata.table_iterator(reverse=True): + t.delete().execute() + + def testeagerempty(self): + """an easy one...test parent object with child relation to an inheriting mapper, using eager loads, + works when there are no child objects present""" + class Person(object): + def __init__(self, **kwargs): + for key, value in kwargs.iteritems(): + setattr(self, key, value) + def __repr__(self): + return "Ordinary person %s" % self.name + class Engineer(Person): + def __repr__(self): + return "Engineer %s, status %s" % (self.name, self.status) + class Manager(Person): + def __repr__(self): + return "Manager %s, status %s" % (self.name, self.longer_status) + class Car(object): + def __init__(self, **kwargs): + for key, value in kwargs.iteritems(): + setattr(self, key, value) + def __repr__(self): + return "Car number %d" % self.car_id + + person_mapper = mapper(Person, people, polymorphic_on=people.c.type, polymorphic_identity='person') + engineer_mapper = mapper(Engineer, engineers, inherits=person_mapper, polymorphic_identity='engineer') + manager_mapper = mapper(Manager, managers, inherits=person_mapper, polymorphic_identity='manager') + car_mapper = mapper(Car, cars, properties= {'manager':relation(manager_mapper, lazy=False)}) + + sess = create_session() + car1 = Car() + car2 = Car() + car2.manager = Manager() + sess.save(car1) + sess.save(car2) + sess.flush() + sess.clear() + + carlist = sess.query(Car).select() + assert carlist[0].manager is None + assert carlist[1].manager.person_id == car2.manager.person_id + if __name__ == "__main__": testbase.main() \ No newline at end of file -- 2.47.2