summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/context.py24
-rw-r--r--lib/sqlalchemy/orm/mapper.py49
-rw-r--r--lib/sqlalchemy/orm/util.py8
3 files changed, 78 insertions, 3 deletions
diff --git a/lib/sqlalchemy/orm/context.py b/lib/sqlalchemy/orm/context.py
index 85c736e12..45df57c5d 100644
--- a/lib/sqlalchemy/orm/context.py
+++ b/lib/sqlalchemy/orm/context.py
@@ -1951,6 +1951,18 @@ class ORMSelectCompileState(ORMCompileState, SelectState):
# make the right hand side target into an ORM entity
right = aliased(right_mapper, right_selectable)
+
+ util.warn_deprecated(
+ "An alias is being generated automatically against "
+ "joined entity %s for raw clauseelement, which is "
+ "deprecated and will be removed in a later release. "
+ "Use the aliased() "
+ "construct explicitly, see the linked example."
+ % right_mapper,
+ "1.4",
+ code="xaj1",
+ )
+
elif create_aliases:
# it *could* work, but it doesn't right now and I'd rather
# get rid of aliased=True completely
@@ -1975,6 +1987,18 @@ class ORMSelectCompileState(ORMCompileState, SelectState):
right = aliased(right, flat=True)
need_adapter = True
+ if not create_aliases:
+ util.warn(
+ "An alias is being generated automatically against "
+ "joined entity %s due to overlapping tables. This is a "
+ "legacy pattern which may be "
+ "deprecated in a later release. Use the "
+ "aliased(<entity>, flat=True) "
+ "construct explicitly, see the linked example."
+ % right_mapper,
+ code="xaj2",
+ )
+
if need_adapter:
assert right_mapper
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,
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index 01a8becc3..63a2774b3 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -1172,6 +1172,14 @@ def aliased(element, alias=None, name=None, flat=False, adapt_on_names=False):
:class:`_expression.Alias` is not
ORM-mapped in this case.
+ .. seealso::
+
+ :ref:`tutorial_orm_entity_aliases` - in the :ref:`unified_tutorial`
+
+ :ref:`orm_queryguide_orm_aliases` - in the :ref:`queryguide_toplevel`
+
+ :ref:`ormtutorial_aliases` - in the legacy :ref:`ormtutorial_toplevel`
+
:param element: element to be aliased. Is normally a mapped class,
but for convenience can also be a :class:`_expression.FromClause`
element.