]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- eager relation to an inheriting mapper wont fail if no rows returned for
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 27 Jan 2007 01:40:26 +0000 (01:40 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 27 Jan 2007 01:40:26 +0000 (01:40 +0000)
the relationship.

CHANGES
lib/sqlalchemy/orm/mapper.py
test/orm/inheritance5.py

diff --git a/CHANGES b/CHANGES
index dc47d4978741082015832d3486ff8b7be9554f4b..6fdd40713646931facf34cee6d7fb0677de03ddc 100644 (file)
--- 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 
index df09402bf73d3bf2b863a7f1608b73c82c89e776..4cdf62227d65c6b1021e921f477ec8d66926e537 100644 (file)
@@ -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
index af1a4918ce0ce8bf5dfed9675bdb97a5f7d6e543..4a90772b443795a648a15311917325d8233a9e05 100644 (file)
@@ -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