summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/selectable.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/sql/selectable.py')
-rw-r--r--lib/sqlalchemy/sql/selectable.py81
1 files changed, 72 insertions, 9 deletions
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index c78b1ec57..9440fc48b 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -4391,13 +4391,41 @@ class Select(
and apply generatively, returning the newly resulting
:class:`_expression.Select`.
- .. versionchanged:: 1.4 :meth:`_expression.Select.join` now modifies
- the FROM list of the :class:`.Select` object in place, rather than
- implicitly producing a subquery.
+ E.g.::
+
+ stmt = select(user_table).join(address_table, user_table.c.id == address_table.c.user_id)
+
+ The above statement generages SQL similar to::
+
+ SELECT user.id, user.name FROM user JOIN address ON user.id = address.user_id
+
+ .. versionchanged:: 1.4 :meth:`_expression.Select.join` now creates
+ a :class:`_sql.Join` object between a :class:`_sql.FromClause`
+ source that is within the FROM clause of the existing SELECT,
+ and a given target :class:`_sql.FromClause`, and then adds
+ this :class:`_sql.Join` to the FROM clause of the newly generated
+ SELECT statement. This is completely reworked from the behavior
+ in 1.3, which would instead create a subquery of the entire
+ :class:`_expression.Select` and then join that subquery to the
+ target.
+
+ This is a **backwards incompatible change** as the previous behavior
+ was mostly useless, producing an unnamed subquery rejected by
+ most databases in any case. The new behavior is modeled after
+ that of the very successful :meth:`_orm.Query.join` method in the
+ ORM, in order to support the functionality of :class:`_orm.Query`
+ being available by using a :class:`_sql.Select` object with an
+ :class:`_orm.Session`.
+
+ See the notes for this change at :ref:`change_select_join`.
+
:param target: target table to join towards
- :param onclause: ON clause of the join.
+ :param onclause: ON clause of the join. If omitted, an ON clause
+ is generated automatically based on the :class:`_schema.ForeignKey`
+ linkages between the two tables, if one can be unambiguously
+ determined, otherwise an error is raised.
:param isouter: if True, generate LEFT OUTER join. Same as
:meth:`_expression.Select.outerjoin`.
@@ -4408,7 +4436,9 @@ class Select(
:meth:`_expression.Select.join_from`
- """
+ :meth:`_expression.Select.outerjoin`
+
+ """ # noqa: E501
target = coercions.expect(
roles.JoinTargetRole, target, apply_propagate_attrs=self
)
@@ -4422,11 +4452,22 @@ class Select(
def join_from(
self, from_, target, onclause=None, isouter=False, full=False
):
- r"""Create a SQL JOIN against this :class:`_expresson.Select`
+ r"""Create a SQL JOIN against this :class:`_expression.Select`
object's criterion
and apply generatively, returning the newly resulting
:class:`_expression.Select`.
+ E.g.::
+
+ stmt = select(user_table, address_table).join_from(
+ user_table, address_table, user_table.c.id == address_table.c.user_id
+ )
+
+ The above statement generages SQL similar to::
+
+ SELECT user.id, user.name, address.id, address.email, address.user_id
+ FROM user JOIN address ON user.id = address.user_id
+
.. versionadded:: 1.4
:param from\_: the left side of the join, will be rendered in the
@@ -4446,7 +4487,8 @@ class Select(
:meth:`_expression.Select.join`
- """
+ """ # noqa: E501
+
# note the order of parsing from vs. target is important here, as we
# are also deriving the source of the plugin (i.e. the subject mapper
# in an ORM query) which should favor the "from_" over the "target"
@@ -4470,8 +4512,29 @@ class Select(
Parameters are the same as that of :meth:`_expression.Select.join`.
.. versionchanged:: 1.4 :meth:`_expression.Select.outerjoin` now
- modifies the FROM list of the :class:`.Select` object in place,
- rather than implicitly producing a subquery.
+ creates a :class:`_sql.Join` object between a
+ :class:`_sql.FromClause` source that is within the FROM clause of
+ the existing SELECT, and a given target :class:`_sql.FromClause`,
+ and then adds this :class:`_sql.Join` to the FROM clause of the
+ newly generated SELECT statement. This is completely reworked
+ from the behavior in 1.3, which would instead create a subquery of
+ the entire
+ :class:`_expression.Select` and then join that subquery to the
+ target.
+
+ This is a **backwards incompatible change** as the previous behavior
+ was mostly useless, producing an unnamed subquery rejected by
+ most databases in any case. The new behavior is modeled after
+ that of the very successful :meth:`_orm.Query.join` method in the
+ ORM, in order to support the functionality of :class:`_orm.Query`
+ being available by using a :class:`_sql.Select` object with an
+ :class:`_orm.Session`.
+
+ See the notes for this change at :ref:`change_select_join`.
+
+ .. seealso::
+
+ :meth:`_expression.Select.join`
"""
return self.join(target, onclause=onclause, isouter=True, full=full,)