diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-08-20 10:28:16 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-08-20 11:27:47 -0400 |
commit | 680baea6b83c497e862f3f0ade28e11940cfd895 (patch) | |
tree | c38f17898e5fa30f19bf4881f21b934cbd6bb316 | |
parent | 5c4a74fc13ca28983706a76ab02ffe09d89d1dbf (diff) | |
download | sqlalchemy-680baea6b83c497e862f3f0ade28e11940cfd895.tar.gz |
heads up that execute(query).first() can't apply LIMIT 1
Fixes: #6914
Change-Id: I5de9843dd3723c017b94b705fc009b883737ede1
-rw-r--r-- | doc/build/changelog/migration_20.rst | 35 | ||||
-rw-r--r-- | lib/sqlalchemy/engine/result.py | 11 |
2 files changed, 42 insertions, 4 deletions
diff --git a/doc/build/changelog/migration_20.rst b/doc/build/changelog/migration_20.rst index 71939f44f..e6c9e2952 100644 --- a/doc/build/changelog/migration_20.rst +++ b/doc/build/changelog/migration_20.rst @@ -1229,6 +1229,24 @@ following the table, and may include additional notes not summarized here. * - :: + session.query(User).\ + filter_by(name='some user').first() + + + - :: + + session.execute( + select(User). + filter_by(name="some user"). + limit(1) + ).scalars().first() + + - :ref:`migration_20_unify_select` + + :meth:`_engine.Result.first` + + * - :: + session.query(User).options( joinedload(User.addresses) ).all() @@ -1362,6 +1380,9 @@ Legacy code examples are illustrated below:: user = session.query(User).filter_by(name='some user').one() # becomes legacy use case + user = session.query(User).filter_by(name='some user').first() + + # becomes legacy use case user = session.query(User).get(5) # becomes legacy use case @@ -1422,6 +1443,11 @@ Below are some examples of how to migrate to :func:`_sql.select`:: select(User).filter_by(name="some user") ).scalar_one() + # for first(), no LIMIT is applied automatically; add limit(1) if LIMIT + # is desired on the query + user = session.execute( + select(User).filter_by(name="some user").limit(1) + ).scalars().first() # get() moves to the Session directly user = session.get(User, 5) @@ -1846,21 +1872,22 @@ As is the case described at :ref:`migration_20_query_from_self`, the from sqlalchemy.orm import aliased - subquery = session.query(User).filter(User.id == 5).subquery() + subquery = session.query(User).filter(User.name.like("%somename%")).subquery() ua = aliased(User, subquery) - user = session.query(ua).first() + user = session.query(ua).order_by(ua.id).first() Using :term:`2.0 style`:: from sqlalchemy.orm import aliased - subquery = select(User).where(User.id == 5).subquery() + subquery = select(User).where(User.name.like("%somename%")).subquery() ua = aliased(User, subquery) - user = session.execute(select(ua)).scalars().first() + # note that LIMIT 1 is not automatically supplied, if needed + user = session.execute(select(ua).order_by(ua.id).limit(1)).scalars().first() **Discussion** diff --git a/lib/sqlalchemy/engine/result.py b/lib/sqlalchemy/engine/result.py index 60474c0ed..3c2e682be 100644 --- a/lib/sqlalchemy/engine/result.py +++ b/lib/sqlalchemy/engine/result.py @@ -1054,6 +1054,17 @@ class Result(_WithKeys, ResultInternal): column of the first row, use the :meth:`.Result.scalar` method, or combine :meth:`.Result.scalars` and :meth:`.Result.first`. + Additionally, in contrast to the behavior of the legacy ORM + :meth:`_orm.Query.first` method, **no limit is applied** to the + SQL query which was invoked to produce this :class:`_engine.Result`; + for a DBAPI driver that buffers results in memory before yielding + rows, all rows will be sent to the Python process and all but + the first row will be discarded. + + .. seealso:: + + :ref:`migration_20_unify_select` + :return: a :class:`.Row` object, or None if no rows remain. |