From: Mike Bayer Date: Thu, 30 Dec 2010 17:20:03 +0000 (-0500) Subject: - A little more verbiage to the "primaryjoin" error, X-Git-Tag: rel_0_6_6~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=306c6412d33999032a9697bab79298ad6c5caaa2;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 2a1e21753e..50216efe79 100644 --- a/CHANGES +++ b/CHANGES @@ -68,6 +68,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 7ca57d3a4a..3d80cc4984 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -1085,16 +1085,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 " @@ -1121,7 +1134,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 5033a84fe6..7a94f4f384 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.compile_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.compile_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.compile_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.compile_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.compile_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 ", + "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.", sa.orm.compile_mappers) sa.orm.clear_mappers() @@ -2352,8 +2398,12 @@ class InvalidRelationshipEscalationTestM2M(_base.MappedTest): assert_raises_message( sa.exc.ArgumentError, - "Could not locate any equated, locally mapped column pairs for " - "secondaryjoin condition", sa.orm.compile_mappers) + "Could not locate any foreign-key-equated, locally mapped " + "column pairs for secondaryjoin condition 'foobars.bid <= " + "bars.id' on relationship Foo.bars. For more relaxed " + "rules on join conditions, the relationship may be marked " + "as viewonly=True.", + sa.orm.compile_mappers) class ActiveHistoryFlagTest(_fixtures.FixtureTest): run_inserts = None