From: Mike Bayer Date: Sat, 7 May 2011 15:52:14 +0000 (-0400) Subject: - mapper() will ignore non-configured foreign keys X-Git-Tag: rel_0_7_0~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7adcb1c7443265fc99d05714c964c795f0fe1c13;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - 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. --- diff --git a/CHANGES b/CHANGES index ebdca81b11..2a06242fe7 100644 --- 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 diff --git a/lib/sqlalchemy/ext/declarative.py b/lib/sqlalchemy/ext/declarative.py index 8ea76d7599..62a1170527 100755 --- a/lib/sqlalchemy/ext/declarative.py +++ b/lib/sqlalchemy/ext/declarative.py @@ -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. diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 53f8af0b4e..03f3e90db2 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -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, diff --git a/test/orm/inheritance/test_basic.py b/test/orm/inheritance/test_basic.py index 2d95e5f378..5b0deaf9d7 100644 --- a/test/orm/inheritance/test_basic.py +++ b/test/orm/inheritance/test_basic.py @@ -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): diff --git a/test/orm/test_mapper.py b/test/orm/test_mapper.py index 9929886ab3..604c92f417 100644 --- a/test/orm/test_mapper.py +++ b/test/orm/test_mapper.py @@ -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,