Skip to content

Commit 17b1a52

Browse files
committed
Add a one_or_zero method; #19
The one method is too complex for this common case, it turns out. :-/
1 parent c37b7c4 commit 17b1a52

File tree

1 file changed

+53
-17
lines changed

1 file changed

+53
-17
lines changed

postgres.py

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,20 @@
2929
>>> db.run("INSERT INTO foo VALUES ('baz')")
3030
>>> db.run("INSERT INTO foo VALUES ('buz')")
3131
32+
Use :py:meth:`~postgres.Postgres.all` to fetch all results:
33+
34+
>>> db.all("SELECT * FROM foo ORDER BY bar")
35+
[{'bar': 'baz'}, {'bar': 'buz'}]
36+
3237
Use :py:meth:`~postgres.Postgres.one` to fetch exactly one result:
3338
3439
>>> db.one("SELECT * FROM foo WHERE bar='baz'")
3540
{'bar': 'baz'}
3641
42+
Use :py:meth:`~postgres.Postgres.one_or_zero` to fetch one result or
43+
:py:class:`None`:
3744
38-
Use :py:meth:`~postgres.Postgres.all` to fetch all results:
39-
40-
>>> db.all("SELECT * FROM foo ORDER BY bar")
41-
[{'bar': 'baz'}, {'bar': 'buz'}]
45+
>>> db.one("SELECT * FROM foo WHERE bar='blam'")
4246
4347
4448
Bind Parameters
@@ -272,6 +276,7 @@ def __init__(self, url, minconn=1, maxconn=10, \
272276
raise ValueError("strict_one must be True, False, or None.")
273277
self.strict_one = strict_one
274278

279+
275280
def run(self, sql, parameters=None):
276281
"""Execute a query and discard any results.
277282
@@ -288,6 +293,34 @@ def run(self, sql, parameters=None):
288293
with self.get_cursor() as cursor:
289294
cursor.execute(sql, parameters)
290295

296+
297+
def all(self, sql, parameters=None):
298+
"""Execute a query and return all results.
299+
300+
:param unicode sql: the SQL statement to execute
301+
:param parameters: the bind parameters for the SQL statement
302+
:type parameters: dict or tuple
303+
:returns: :py:class:`list` of rows
304+
305+
>>> for row in db.all("SELECT bar FROM foo"):
306+
... print(row["bar"])
307+
...
308+
baz
309+
buz
310+
311+
"""
312+
with self.get_cursor() as cursor:
313+
cursor.execute(sql, parameters)
314+
return cursor.fetchall()
315+
316+
def rows(self, *a, **kw):
317+
318+
# This is for backwards compatibility, see #16. It is stubbed instead
319+
# of aliased to avoid showing up in our docs via sphinx autodoc.
320+
321+
return self.all(*a, **kw)
322+
323+
291324
def one(self, sql, parameters=None, strict=None):
292325
"""Execute a query and return a single result.
293326
@@ -335,31 +368,34 @@ def one(self, sql, parameters=None, strict=None):
335368

336369
return cursor.fetchone()
337370

338-
def all(self, sql, parameters=None):
339-
"""Execute a query and return all results.
371+
def one_or_zero(self, sql, parameters=None):
372+
"""Execute a query and return a single result or :py:class:`None`.
340373
341374
:param unicode sql: the SQL statement to execute
342375
:param parameters: the bind parameters for the SQL statement
343376
:type parameters: dict or tuple
344-
:returns: :py:class:`list` of rows
377+
:returns: a single row or :py:const:`None`
378+
:raises: :py:exc:`~postgres.TooFew` or :py:exc:`~postgres.TooMany`
345379
346-
>>> for row in db.all("SELECT bar FROM foo"):
347-
... print(row["bar"])
380+
Use this for the common case where there should only be one record, but
381+
it may not exist yet.
382+
383+
>>> row = db.one_or_zero("SELECT * FROM foo WHERE bar='blam'")
384+
>>> if row is None:
385+
... print("No blam yet.")
348386
...
349-
baz
350-
buz
387+
No blam yet.
351388
352389
"""
353390
with self.get_cursor() as cursor:
354391
cursor.execute(sql, parameters)
355-
return cursor.fetchall()
356392

357-
def rows(self, *a, **kw):
358-
359-
# This is for backwards compatibility, see #16. It is stubbed instead
360-
# of aliased to avoid showing up in our docs via sphinx autodoc.
393+
if cursor.rowcount < 0:
394+
raise TooFew(cursor.rowcount)
395+
elif cursor.rowcount > 1:
396+
raise TooMany(cursor.rowcount)
361397

362-
return self.all(*a, **kw)
398+
return cursor.fetchone()
363399

364400

365401
def get_cursor(self, *a, **kw):

0 commit comments

Comments
 (0)