]> 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:52:14 +0000 (11:52 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 7 May 2011 15:52:14 +0000 (11:52 -0400)
to unrelated tables when determining inherit
condition between parent and child class.
This is equivalent to behavior already
applied to declarative.  [ticket:2153]
Also in 0.6.8.

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

diff --git a/CHANGES b/CHANGES
index ebdca81b118ae570a79ffd60c6edfc57315118e6..2a06242fe716df7c738bb95f24c65a0a0b7fb6c2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -33,6 +33,13 @@ CHANGES
     in the join condition.  [ticket:2149]
     Also in 0.6.8.
 
+  - 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]
+    Also in 0.6.8.
+
   - It is an error to call query.get() when the
     given entity is not a single, full class 
     entity or mapper (i.e. a column).  This is
index 8ea76d759925a419c49762757b7ce2aa775228d6..62a1170527a4da8620fcc78f5206b4083d7e021d 100755 (executable)
@@ -1058,14 +1058,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 53f8af0b4e67d9cfe2c22f6dba095d0a5dc233dd..03f3e90db2fcdfd92ebb12d00ce90e906b578117 100644 (file)
@@ -470,7 +470,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 2d95e5f378c0ab66c7196ecd56d78f5e84ff0f14..5b0deaf9d7802e92ba23119d902f402a6c52b7e7 100644 (file)
@@ -1507,6 +1507,89 @@ class NoPKOnSubTableWarningTest(fixtures.TestBase):
         mc = mapper(C, child, inherits=P, primary_key=[parent.c.id])
         eq_(mc.primary_key, (parent.c.id,))
 
+class InhCondTest(fixtures.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(fixtures.MappedTest):
     @classmethod
     def define_tables(cls, metadata):
index 9929886ab3f90294d311c3a166a50c7e1d704abc..604c92f4177b56c0bf683968176bf6ebe87eae16 100644 (file)
@@ -489,6 +489,8 @@ class MapperTest(_fixtures.FixtureTest):
             m3.identity_key_from_instance(AddressUser())
         )
 
+
+
     def test_illegal_non_primary(self):
         users, Address, addresses, User = (self.tables.users,
                                 self.classes.Address,