|
8 | 8 | from sqlalchemy.engine import Engine, Connection
|
9 | 9 | from sqlalchemy.sql import schema
|
10 | 10 |
|
| 11 | +from .exceptions import MultipleResultsFound, NoResultFound |
11 | 12 | from .transaction import GinoTransaction
|
12 | 13 |
|
13 | 14 |
|
@@ -179,8 +180,8 @@ class GinoConnection:
|
179 | 180 | Represents an actual database connection.
|
180 | 181 |
|
181 | 182 | This is the root of all query API like :meth:`all`, :meth:`first`,
|
182 |
| - :meth:`scalar` or :meth:`status`, those on engine or query are simply |
183 |
| - wrappers of methods in this class. |
| 183 | + :meth:`one`, :meth:`one_or_none`, :meth:`scalar` or :meth:`status`, |
| 184 | + those on engine or query are simply wrappers of methods in this class. |
184 | 185 |
|
185 | 186 | Usually instances of this class are created by :meth:`.GinoEngine.acquire`.
|
186 | 187 |
|
@@ -323,6 +324,50 @@ async def first(self, clause, *multiparams, **params):
|
323 | 324 | result = self._execute(clause, multiparams, params)
|
324 | 325 | return await result.execute(one=True)
|
325 | 326 |
|
| 327 | + async def one_or_none(self, clause, *multiparams, **params): |
| 328 | + """ |
| 329 | + Runs the given query in database, returns at most one result. |
| 330 | +
|
| 331 | + If the query returns no result, this method will return ``None``. |
| 332 | + If the query returns multiple results, this method will raise |
| 333 | + :class:`~gino.exceptions.MultipleResultsFound`. |
| 334 | +
|
| 335 | + See :meth:`all` for common query comments. |
| 336 | +
|
| 337 | + """ |
| 338 | + result = self._execute(clause, multiparams, params) |
| 339 | + ret = await result.execute() |
| 340 | + |
| 341 | + if ret is None or len(ret) == 0: |
| 342 | + return None |
| 343 | + |
| 344 | + if len(ret) == 1: |
| 345 | + return ret[0] |
| 346 | + |
| 347 | + raise MultipleResultsFound('Multiple rows found for one_or_none().') |
| 348 | + |
| 349 | + async def one(self, clause, *multiparams, **params): |
| 350 | + """ |
| 351 | + Runs the given query in database, returns exactly one result. |
| 352 | +
|
| 353 | + If the query returns no result, this method will raise |
| 354 | + :class:`~gino.exceptions.NoResultFound`. |
| 355 | + If the query returns multiple results, this method will raise |
| 356 | + :class:`~gino.exceptions.MultipleResultsFound`. |
| 357 | +
|
| 358 | + See :meth:`all` for common query comments. |
| 359 | +
|
| 360 | + """ |
| 361 | + try: |
| 362 | + ret = await self.one_or_none(clause, *multiparams, **params) |
| 363 | + except MultipleResultsFound: |
| 364 | + raise MultipleResultsFound('Multiple rows found for one().') |
| 365 | + |
| 366 | + if ret is None: |
| 367 | + raise NoResultFound('No row was found for one().') |
| 368 | + |
| 369 | + return ret |
| 370 | + |
326 | 371 | async def scalar(self, clause, *multiparams, **params):
|
327 | 372 | """
|
328 | 373 | Runs the given query in database, returns the first result.
|
@@ -696,6 +741,22 @@ async def first(self, clause, *multiparams, **params):
|
696 | 741 | async with self.acquire(reuse=True) as conn:
|
697 | 742 | return await conn.first(clause, *multiparams, **params)
|
698 | 743 |
|
| 744 | + async def one_or_none(self, clause, *multiparams, **params): |
| 745 | + """ |
| 746 | + Runs :meth:`~.GinoConnection.one_or_none`, See :meth:`.all`. |
| 747 | +
|
| 748 | + """ |
| 749 | + async with self.acquire(reuse=True) as conn: |
| 750 | + return await conn.one_or_none(clause, *multiparams, **params) |
| 751 | + |
| 752 | + async def one(self, clause, *multiparams, **params): |
| 753 | + """ |
| 754 | + Runs :meth:`~.GinoConnection.one`, See :meth:`.all`. |
| 755 | +
|
| 756 | + """ |
| 757 | + async with self.acquire(reuse=True) as conn: |
| 758 | + return await conn.one(clause, *multiparams, **params) |
| 759 | + |
699 | 760 | async def scalar(self, clause, *multiparams, **params):
|
700 | 761 | """
|
701 | 762 | Runs :meth:`~.GinoConnection.scalar`, See :meth:`.all`.
|
|
0 commit comments