From 3264433782034cf862e534ea6c9e07fd5531050c Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 11 Mar 2010 18:38:51 -0500 Subject: [PATCH] - query.scalar() now raises an exception if more than one row is returned. All other behavior remains the same. [ticket:1735] --- CHANGES | 4 ++++ lib/sqlalchemy/orm/query.py | 13 ++++++++++--- test/orm/test_query.py | 5 ++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 101c0223bd..4335efd8a3 100644 --- a/CHANGES +++ b/CHANGES @@ -109,6 +109,10 @@ CHANGES query.from_statement() raises an exception now instead of silently dropping those criterion. [ticket:1736] + - query.scalar() now raises an exception if more than one + row is returned. All other behavior remains the same. + [ticket:1735] + - sql - The most common result processors conversion function were moved to the new "processors" module. Dialect authors are diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 88945b9d07..d7b60dfa3c 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -1309,6 +1309,11 @@ class Query(object): def first(self): """Return the first result of this ``Query`` or None if the result doesn't contain any row. + + first() applies a limit of one within the generated SQL, so that + only one primary entity row is generated on the server side + (note this may consist of multiple result rows if eagerly loaded + collections are present). Calling ``first()`` results in an execution of the underlying query. @@ -1354,7 +1359,9 @@ class Query(object): "Multiple rows were found for one()") def scalar(self): - """Return the first element of the first result or None. + """Return the first element of the first result or None + if no rows present. If multiple rows are returned, + raises MultipleResultsFound. >>> session.query(Item).scalar() @@ -1371,11 +1378,11 @@ class Query(object): """ try: - ret = list(self)[0] + ret = self.one() if not isinstance(ret, tuple): return ret return ret[0] - except IndexError: + except orm_exc.NoResultFound: return None def __iter__(self): diff --git a/test/orm/test_query.py b/test/orm/test_query.py index 054d64d204..a2212851d4 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -2924,7 +2924,10 @@ class ImmediateTest(_fixtures.FixtureTest): eq_(sess.query(User.id).filter_by(id=0).scalar(), None) eq_(sess.query(User).filter_by(id=7).scalar(), sess.query(User).filter_by(id=7).one()) - + + assert_raises(sa.orm.exc.MultipleResultsFound, sess.query(User).scalar) + assert_raises(sa.orm.exc.MultipleResultsFound, sess.query(User.id, User.name).scalar) + @testing.resolve_artifact_names def test_value(self): sess = create_session() -- 2.47.3