]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Query.one() raises either NoResultFound or MultipleResultsFound, [ticket:1034]
authorJason Kirtland <jek@discorporate.us>
Wed, 14 May 2008 20:44:16 +0000 (20:44 +0000)
committerJason Kirtland <jek@discorporate.us>
Wed, 14 May 2008 20:44:16 +0000 (20:44 +0000)
doc/build/content/ormtutorial.txt
lib/sqlalchemy/orm/exc.py
lib/sqlalchemy/orm/query.py
test/orm/query.py

index b9b598e64e661e4601f98481e275a586965a3805..411bf64ca174f92604c7d217cad67ddba82770d6 100644 (file)
@@ -460,7 +460,19 @@ The `all()`, `one()`, and `first()` methods of `Query` immediately issue SQL and
     WHERE users.name LIKE ? ORDER BY users.id 
      LIMIT 2 OFFSET 0
     ['%ed']
-    {stop}Multiple rows returned for one()
+    {stop}Multiple rows were found for one()
+
+    {python}
+    {sql}>>> try:
+    ...     user = query.filter(User.id == 99).one() 
+    ... except Exception, e: 
+    ...     print e
+    SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password 
+    FROM users 
+    WHERE users.name LIKE ? AND users.id = ? ORDER BY users.id 
+     LIMIT 2 OFFSET 0
+    ['%ed', 99]
+    {stop}No row was found for one()
 
 ### Using Literal SQL {@naqme=literal}
 
index 2d1d2b108e49446832b162516a3313aba64cc7d5..ea7efd3fb858fab99f07e5cc4fa905404ee55ee6 100644 (file)
@@ -24,6 +24,11 @@ class ObjectDeletedError(sa_exc.InvalidRequestError):
 class UnmappedColumnError(sa_exc.InvalidRequestError):
     """Mapping operation was requested on an unknown column."""
 
+class NoResultFound(sa_exc.InvalidRequestError):
+    """A database result was required but none was found."""
+
+class MultipleResultsFound(sa_exc.InvalidRequestError):
+    """A single database result was required but more than one were found."""
 
 # Legacy compat until 0.6.
 sa_exc.ConcurrentModificationError = ConcurrentModificationError
index 608f3f7344917189ba676e98f687af7358da44e1..47d00964d405cee9b64e4bf353d0425270cfa93b 100644 (file)
@@ -1045,22 +1045,29 @@ class Query(object):
                 return None
 
     def one(self):
-        """Return the first result, raising an exception unless exactly one row exists.
+        """Return exactly one result or raise an exception.
+
+        Raises ``sqlalchemy.orm.NoResultError`` if the query selects no rows.
+        Raisees ``sqlalchemy.orm.MultipleResultsError`` if multiple rows are
+        selected.
 
         This results in an execution of the underlying query.
 
         """
         if self._statement:
-            raise exceptions.InvalidRequestError("one() not available when from_statement() is used; use `first()` instead.")
-            
+            raise exceptions.InvalidRequestError(
+                "one() not available when from_statement() is used; "
+                "use `first()` instead.")
+
         ret = list(self[0:2])
 
         if len(ret) == 1:
             return ret[0]
         elif len(ret) == 0:
-            raise sa_exc.InvalidRequestError('No rows returned for one()')
+            raise orm_exc.NoResultFound("No row was found for one()")
         else:
-            raise sa_exc.InvalidRequestError('Multiple rows returned for one()')
+            raise orm_exc.MultipleResultsFound(
+                "Multiple rows were found for one()")
 
     def __iter__(self):
         context = self._compile_context()
index eb7a0f3d37205ded65619b5aa911debbf622b838..d2550427c276136dc8c87925505467f072f1f686 100644 (file)
@@ -10,6 +10,9 @@ from testlib import *
 from orm import _base
 from testlib import engines
 from testlib.fixtures import *
+from testlib import sa, testing
+from testlib.testing import eq_
+from orm import _fixtures
 
 from sqlalchemy.orm.util import join, outerjoin, with_parent
 
@@ -365,7 +368,7 @@ class FilterTest(QueryTest):
         assert [] == create_session().query(User)[0:0]
         
         
-    def test_onefilter(self):
+    def test_one_filter(self):
         assert [User(id=8), User(id=9)] == create_session().query(User).filter(User.name.endswith('ed')).all()
 
     def test_contains(self):
@@ -1436,6 +1439,58 @@ class MixedEntitiesTest(QueryTest):
         sess.clear()
 
 
+class ImmediateTest(_fixtures.FixtureTest):
+    run_inserts = 'once'
+    run_deletes = None
+
+    @testing.resolve_artifact_names
+    def setup_mappers(self):
+        mapper(Address, addresses)
+
+        mapper(User, users, properties=dict(
+            addresses=relation(Address)))
+
+    @testing.resolve_artifact_names
+    def test_one(self):
+        sess = create_session()
+
+        self.assertRaises(sa.orm.exc.NoResultFound,
+                          sess.query(User).filter(User.id == 99).one)
+
+        eq_(sess.query(User).filter(User.id == 7).one().id, 7)
+
+        self.assertRaises(sa.orm.exc.MultipleResultsFound,
+                          sess.query(User).one)
+
+        self.assertRaises(
+            sa.orm.exc.NoResultFound,
+            sess.query(User.id, User.name).filter(User.id == 99).one)
+
+        eq_(sess.query(User.id, User.name).filter(User.id == 7).one(),
+            (7, 'jack'))
+
+        self.assertRaises(sa.orm.exc.MultipleResultsFound,
+                          sess.query(User.id, User.name).one)
+
+        self.assertRaises(sa.orm.exc.NoResultFound,
+                          (sess.query(User, Address).
+                           join(User.addresses).
+                           filter(Address.id == 99)).one)
+
+        eq_((sess.query(User, Address).
+             join(User.addresses).
+             filter(Address.id == 4)).one(),
+            (User(id=8), Address(id=4)))
+
+        self.assertRaises(sa.orm.exc.MultipleResultsFound,
+                          sess.query(User, Address).join(User.addresses).one)
+
+
+    @testing.future
+    def test_getslice(self):
+        assert False
+
+
 class SelectFromTest(QueryTest):
     keep_mappers = False