From: Mike Bayer Date: Sat, 7 May 2011 15:54:53 +0000 (-0400) Subject: - mapper() will ignore non-configured foreign keys X-Git-Tag: rel_0_6_8~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=739671e0c97f914c069de290fa24ed75d3cb376f;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] --- diff --git a/CHANGES b/CHANGES index 25da1e7d89..d3ce0e9102 100644 --- 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 diff --git a/lib/sqlalchemy/ext/declarative.py b/lib/sqlalchemy/ext/declarative.py index 8f5cf5a78c..70080e9c7e 100755 --- a/lib/sqlalchemy/ext/declarative.py +++ b/lib/sqlalchemy/ext/declarative.py @@ -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. diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 07be0b746e..e9caa6da59 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -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, diff --git a/test/orm/inheritance/test_basic.py b/test/orm/inheritance/test_basic.py index cccc1453f2..074451c94c 100644 --- a/test/orm/inheritance/test_basic.py +++ b/test/orm/inheritance/test_basic.py @@ -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):