diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-09-04 12:12:46 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-09-28 13:27:54 -0400 |
commit | 6ce0d644db60ce6ea89eb15a76e078c4fa1a9066 (patch) | |
tree | f800bc5e1c308eae078e732c834d8eca501461cb /lib/sqlalchemy/orm/mapper.py | |
parent | 52e8545b2df312898d46f6a5b119675e8d0aa956 (diff) | |
download | sqlalchemy-6ce0d644db60ce6ea89eb15a76e078c4fa1a9066.tar.gz |
warn or deprecate for auto-aliasing in joins
An extra layer of warning messages has been added to the functionality
of :meth:`_orm.Query.join` and the ORM version of
:meth:`_sql.Select.join`, where a few places where "automatic aliasing"
continues to occur will now be called out as a pattern to avoid, mostly
specific to the area of joined table inheritance where classes that share
common base tables are being joined together without using explicit aliases.
One case emits a legacy warning for a pattern that's not recommended,
the other case is fully deprecated.
The automatic aliasing within ORM join() which occurs for overlapping
mapped tables does not work consistently with all APIs such as
``contains_eager()``, and rather than continue to try to make these use
cases work everywhere, replacing with a more user-explicit pattern
is clearer, less prone to bugs and simplifies SQLAlchemy's internals
further.
The warnings include links to the errors.rst page where each pattern is
demonstrated along with the recommended pattern to fix.
* Improved the exception message generated when configuring a mapping with
joined table inheritance where the two tables either have no foreign key
relationships set up, or where they have multiple foreign key relationships
set up. The message is now ORM specific and includes context that the
:paramref:`_orm.Mapper.inherit_condition` parameter may be needed
particularly for the ambiguous foreign keys case.
* Add explicit support in the _expect_warnings() assertion for nested
_expect_warnings calls
* generalize the NoCache fixture, which we also need to catch warnings
during compilation consistently
* generalize the __str__() method for the HasCode mixin so all warnings
and errors include the code link in their string
Fixes: #6974
Change-Id: I84ed79ba2112c39eaab7973b6d6f46de7fa80842
Diffstat (limited to 'lib/sqlalchemy/orm/mapper.py')
-rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 5eee134d5..7f111b237 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1011,9 +1011,52 @@ class Mapper( # immediate table of the inherited mapper, not its # full table which could pull in other stuff we don't # want (allows test/inheritance.InheritTest4 to pass) - self.inherit_condition = sql_util.join_condition( - self.inherits.local_table, self.local_table - ) + try: + self.inherit_condition = sql_util.join_condition( + self.inherits.local_table, self.local_table + ) + except sa_exc.NoForeignKeysError as nfe: + assert self.inherits.local_table is not None + assert self.local_table is not None + util.raise_( + sa_exc.NoForeignKeysError( + "Can't determine the inherit condition " + "between inherited table '%s' and " + "inheriting " + "table '%s'; tables have no " + "foreign key relationships established. " + "Please ensure the inheriting table has " + "a foreign key relationship to the " + "inherited " + "table, or provide an " + "'on clause' using " + "the 'inherit_condition' mapper argument." + % ( + self.inherits.local_table.description, + self.local_table.description, + ) + ), + replace_context=nfe, + ) + except sa_exc.AmbiguousForeignKeysError as afe: + assert self.inherits.local_table is not None + assert self.local_table is not None + util.raise_( + sa_exc.AmbiguousForeignKeysError( + "Can't determine the inherit condition " + "between inherited table '%s' and " + "inheriting " + "table '%s'; tables have more than one " + "foreign key relationship established. " + "Please specify the 'on clause' using " + "the 'inherit_condition' mapper argument." + % ( + self.inherits.local_table.description, + self.local_table.description, + ) + ), + replace_context=afe, + ) self.persist_selectable = sql.join( self.inherits.persist_selectable, self.local_table, |