From: Mike Bayer Date: Thu, 30 Dec 2010 17:14:32 +0000 (-0500) Subject: - A little more verbiage to the "primaryjoin" error, X-Git-Tag: rel_0_7b1~105 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=74b7bd4365c429425dd944c3dee8681a1ca6abdb;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - A little more verbiage to the "primaryjoin" error, in an unusual condition that the join condition "works" for viewonly but doesn't work for non-viewonly, and foreign_keys wasn't used - adds "foreign_keys" to the suggestion. Also add "foreign_keys" to the suggestion for the generic "direction" error. --- diff --git a/CHANGES b/CHANGES index 2a6bb1e797..0878133e7d 100644 --- a/CHANGES +++ b/CHANGES @@ -83,6 +83,13 @@ CHANGES improves the generation of joined-inheritance "load expired row" behavior. [ticket:1992] + - A little more verbiage to the "primaryjoin" error, + in an unusual condition that the join condition + "works" for viewonly but doesn't work for non-viewonly, + and foreign_keys wasn't used - adds "foreign_keys" to + the suggestion. Also add "foreign_keys" to the + suggestion for the generic "direction" error. + - sql - Fixed operator precedence rules for multiple chains of a single non-associative operator. diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index c7aa0eeea4..0057f5a41b 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -828,16 +828,29 @@ class RelationshipProperty(StrategizedProperty): if not self.viewonly and criterion_as_pairs(join_condition, consider_as_foreign_keys=self._user_defined_foreign_keys, any_operator=True): - raise sa_exc.ArgumentError("Could not locate any " - "equated, locally mapped column pairs for %s " - "condition '%s' on relationship %s. For more " - "relaxed rules on join conditions, the " - "relationship may be marked as viewonly=True." - % ( + + err = "Could not locate any "\ + "foreign-key-equated, locally mapped column "\ + "pairs for %s "\ + "condition '%s' on relationship %s." % ( primary and 'primaryjoin' or 'secondaryjoin', join_condition, self - )) + ) + + if not self._user_defined_foreign_keys: + err += " Ensure that the "\ + "referencing Column objects have a "\ + "ForeignKey present, or are otherwise part "\ + "of a ForeignKeyConstraint on their parent "\ + "Table, or specify the foreign_keys parameter "\ + "to this relationship." + + err += " For more "\ + "relaxed rules on join conditions, the "\ + "relationship may be marked as viewonly=True." + + raise sa_exc.ArgumentError(err) else: if self._user_defined_foreign_keys: raise sa_exc.ArgumentError("Could not determine " @@ -864,7 +877,8 @@ class RelationshipProperty(StrategizedProperty): "referencing Column objects have a " "ForeignKey present, or are otherwise part " "of a ForeignKeyConstraint on their parent " - "Table." + "Table, or specify the foreign_keys parameter " + "to this relationship." % ( primary and 'primaryjoin' or 'secondaryjoin', join_condition, diff --git a/test/orm/test_relationships.py b/test/orm/test_relationships.py index 4234068373..39480d79fd 100644 --- a/test/orm/test_relationships.py +++ b/test/orm/test_relationships.py @@ -1949,8 +1949,43 @@ class InvalidRelationshipEscalationTest(_base.MappedTest): assert_raises_message( sa.exc.ArgumentError, - "Could not locate any equated, locally mapped column pairs " - "for primaryjoin condition", sa.orm.configure_mappers) + "Could not locate any foreign-key-equated, " + "locally mapped column pairs for primaryjoin " + "condition 'foos.id > bars.fid' on relationship " + "Foo.bars. For more relaxed rules on join " + "conditions, the relationship may be marked as viewonly=True.", + sa.orm.configure_mappers) + + @testing.resolve_artifact_names + def test_no_equated_wo_fks_works_on_relaxed(self): + # very unique - the join between parent/child + # has no fks, but there is an fk join between two other + # tables in the join condition, for those users that try creating + # these big-long-string-of-joining-many-tables primaryjoins. + # in this case we don't get eq_pairs, but we hit the "works if viewonly" + # rule. so here we add another clause regarding "try foreign keys". + mapper(Foo, foos, properties={ + 'bars':relationship(Bar, + primaryjoin=and_( + bars_with_fks.c.fid==foos_with_fks.c.id, + foos_with_fks.c.id==foos.c.id, + ) + )}) + mapper(Bar, bars_with_fks) + + assert_raises_message( + sa.exc.ArgumentError, + "Could not locate any foreign-key-equated, locally mapped " + "column pairs for primaryjoin condition " + "'bars_with_fks.fid = foos_with_fks.id AND " + "foos_with_fks.id = foos.id' on relationship Foo.bars. " + "Ensure that the referencing Column objects have a " + "ForeignKey present, or are otherwise part of a " + "ForeignKeyConstraint on their parent Table, or specify " + "the foreign_keys parameter to this relationship. For " + "more relaxed rules on join conditions, the relationship " + "may be marked as viewonly=True.", + sa.orm.configure_mappers) @testing.resolve_artifact_names def test_ambiguous_fks(self): @@ -2031,8 +2066,12 @@ class InvalidRelationshipEscalationTest(_base.MappedTest): assert_raises_message( sa.exc.ArgumentError, - "Could not locate any equated, locally mapped column pairs " - "for primaryjoin condition", sa.orm.configure_mappers) + "Could not locate any foreign-key-equated, " + "locally mapped column pairs for primaryjoin " + "condition 'foos.id > foos.fid' on relationship " + "Foo.foos. For more relaxed rules on join " + "conditions, the relationship may be marked as viewonly=True.", + sa.orm.configure_mappers) @testing.resolve_artifact_names def test_no_equated_viewonly(self): @@ -2301,8 +2340,15 @@ class InvalidRelationshipEscalationTestM2M(_base.MappedTest): mapper(Bar, bars) assert_raises_message( sa.exc.ArgumentError, - "Could not locate any equated, locally mapped column pairs for " - "primaryjoin condition ", + r"Could not locate any foreign-key-equated, locally mapped " + "column pairs for primaryjoin condition 'foos.id > " + "foobars_with_fks.fid' on relationship Foo.bars. Ensure " + "that the referencing Column objects have a ForeignKey " + "present, or are otherwise part of a ForeignKeyConstraint " + "on their parent Table, or specify the foreign_keys " + "parameter to this relationship. For more relaxed " + "rules on join conditions, the relationship may be marked " + "as viewonly=True.", configure_mappers) sa.orm.clear_mappers() @@ -2352,7 +2398,7 @@ class InvalidRelationshipEscalationTestM2M(_base.MappedTest): assert_raises_message( sa.exc.ArgumentError, - "Could not locate any equated, locally mapped column pairs for " + "Could not locate any foreign-key-equated, locally mapped column pairs for " "secondaryjoin condition", sa.orm.configure_mappers) class ActiveHistoryFlagTest(_fixtures.FixtureTest):