]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- mapper() will ignore non-configured foreign keys
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 7 May 2011 15:54:53 +0000 (11:54 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 7 May 2011 15:54:53 +0000 (11:54 -0400)
to unrelated tables when determining inherit
condition between parent and child class.
This is equivalent to behavior already
applied to declarative.  [ticket:2153]

CHANGES
lib/sqlalchemy/ext/declarative.py
lib/sqlalchemy/orm/mapper.py
test/orm/inheritance/test_basic.py

diff --git a/CHANGES b/CHANGES
index 25da1e7d89e61cc1c812799c6e485a5c0129be33..d3ce0e9102728f96591a8ce4ea4761ee4d023534 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -37,6 +37,12 @@ CHANGES
     of that with no cols in the sub-sub class 
     in the join condition.  [ticket:2149]
 
+  - mapper() will ignore non-configured foreign keys
+    to unrelated tables when determining inherit
+    condition between parent and child class.
+    This is equivalent to behavior already 
+    applied to declarative.  [ticket:2153]
+
 - sql
   - Fixed bug whereby if FetchedValue was passed
     to column server_onupdate, it would not
index 8f5cf5a78c08c54494e3a19bfc5d77dfdd7a68c1..70080e9c7ef4e35a469df143dfa21862fdc6fe39 100755 (executable)
@@ -1096,14 +1096,6 @@ def _as_declarative(cls, classname, dict_):
         inherited_mapper = class_mapper(mapper_args['inherits'],
                                             compile=False)
         inherited_table = inherited_mapper.local_table
-        if 'inherit_condition' not in mapper_args and table is not None:
-            # figure out the inherit condition with relaxed rules
-            # about nonexistent tables, to allow for ForeignKeys to
-            # not-yet-defined tables (since we know for sure that our
-            # parent table is defined within the same MetaData)
-            mapper_args['inherit_condition'] = sql_util.join_condition(
-                mapper_args['inherits'].__table__, table,
-                ignore_nonexistent_tables=True)
 
         if table is None:
             # single table inheritance.
index 07be0b746e52cc7ba811a79d0e0c43e9c9fd4a50..e9caa6da59675c936b69ffce6bffa3965bbd3b85 100644 (file)
@@ -256,7 +256,8 @@ class Mapper(object):
                         # want (allows test/inheritance.InheritTest4 to pass)
                         self.inherit_condition = sqlutil.join_condition(
                                                     self.inherits.local_table,
-                                                    self.local_table)
+                                                    self.local_table,
+                                                    ignore_nonexistent_tables=True)
                     self.mapped_table = sql.join(
                                                 self.inherits.mapped_table, 
                                                 self.local_table,
index cccc1453f262551889eab8d17ccd37fb3388076b..074451c94c8c06441d18abadcec5e1f0db93cb0d 100644 (file)
@@ -1389,6 +1389,90 @@ class NoPKOnSubTableWarningTest(testing.TestBase):
         mc = mapper(C, child, inherits=P, primary_key=[parent.c.id])
         eq_(mc.primary_key, (parent.c.id,))
 
+class InhCondTest(testing.TestBase):
+    def test_inh_cond_ignores_others(self):
+        metadata = MetaData()
+        base_table = Table("base", metadata,
+            Column("id", Integer, primary_key=True)
+        )
+        derived_table = Table("derived", metadata,
+            Column("id", Integer, ForeignKey("base.id"), primary_key=True),
+            Column("owner_id", Integer, ForeignKey("owner.owner_id"))
+        )
+
+        class Base(object):
+            pass
+
+        class Derived(Base):
+            pass
+
+        mapper(Base, base_table)
+        # succeeds, despite "owner" table not configured yet
+        m2 = mapper(Derived, derived_table, 
+                    inherits=Base)
+        assert m2.inherit_condition.compare(
+                    base_table.c.id==derived_table.c.id
+                )
+
+    def test_inh_cond_fails_notfound(self):
+        metadata = MetaData()
+        base_table = Table("base", metadata,
+            Column("id", Integer, primary_key=True)
+        )
+        derived_table = Table("derived", metadata,
+            Column("id", Integer, primary_key=True),
+        )
+
+        class Base(object):
+            pass
+
+        class Derived(Base):
+            pass
+
+        mapper(Base, base_table)
+        assert_raises_message(
+            sa_exc.ArgumentError,
+            "Can't find any foreign key relationships between "
+            "'base' and 'derived'.",
+            mapper,
+            Derived, derived_table,  inherits=Base
+        )
+
+    def test_inh_cond_fails_separate_metas(self):
+        m1 = MetaData()
+        m2 = MetaData()
+        base_table = Table("base", m1,
+            Column("id", Integer, primary_key=True)
+        )
+        derived_table = Table("derived", m2,
+            Column("id", Integer, ForeignKey('base.id'), 
+                primary_key=True),
+        )
+
+        class Base(object):
+            pass
+
+        class Derived(Base):
+            pass
+
+        mapper(Base, base_table)
+
+        # this used to be "can't resolve foreign key base.id",
+        # but with the flag on, we just get "can't find".  this is
+        # the less-than-ideal case that prevented us from doing this
+        # for mapper(), not just declarative, in the first place.  
+        # there is no case where the failure would be silent - 
+        # there is either a single join condition between the two tables 
+        # or there's not.
+        assert_raises_message(
+            sa_exc.ArgumentError,
+            "Can't find any foreign key relationships between "
+            "'base' and 'derived'.",
+            mapper,
+            Derived, derived_table,  inherits=Base
+        )
+
+
 class PKDiscriminatorTest(_base.MappedTest):
     @classmethod
     def define_tables(cls, metadata):