3232 >>> db.run("INSERT INTO foo VALUES ('buz', 42)")
3333 >>> db.run("INSERT INTO foo VALUES ('bit', 537)")
3434
35+ Use :py:meth:`~postgres.Postgres.one` to run SQL and fetch one result or
36+ :py:class:`None`:
37+
38+ >>> db.one("SELECT * FROM foo WHERE bar='buz'")
39+ Record(bar='buz', baz=42)
40+ >>> db.one("SELECT * FROM foo WHERE bar='blam'")
41+
3542Use :py:meth:`~postgres.Postgres.all` to run SQL and fetch all results:
3643
3744 >>> db.all("SELECT * FROM foo ORDER BY bar")
3845 [Record(bar='bit', baz=537), Record(bar='buz', baz=42)]
3946
40- Use :py:meth:`~postgres.Postgres.one_or_zero` to run SQL and fetch one result
41- or :py:class:`None`:
42-
43- >>> db.one_or_zero("SELECT * FROM foo WHERE bar='buz'")
44- Record(bar='buz', baz=42)
45- >>> db.one_or_zero("SELECT * FROM foo WHERE bar='blam'")
46-
4747If your queries return one column then you get just the value or a list of
4848values instead of a record or list of records:
4949
50- >>> db.one_or_zero ("SELECT baz FROM foo WHERE bar='buz'")
50+ >>> db.one ("SELECT baz FROM foo WHERE bar='buz'")
5151 42
5252 >>> db.all("SELECT baz FROM foo ORDER BY bar")
5353 [537, 42]
6565against `SQL injection`_. (This is inspired by old-style Python string
6666formatting, but it is not the same.)
6767
68- >>> db.one_or_zero ("SELECT * FROM foo WHERE bar=%(bar)s", {"bar": "buz"})
68+ >>> db.one ("SELECT * FROM foo WHERE bar=%(bar)s", {"bar": "buz"})
6969 Record(bar='buz', baz=42)
7070
7171Never build SQL strings out of user input!
7777++++++++++++++++
7878
7979Eighty percent of your database usage should be covered by the simple
80- :py:meth:`~postgres.Postgres.run`, :py:meth:`~postgres.Postgres.all `,
81- :py:meth:`~postgres.Postgres.one_or_zero ` API introduced above. For the other
82- 20%, :py:mod:`postgres` provides two context managers for working at
83- increasingly lower levels of abstraction. The lowest level of abstraction in
80+ :py:meth:`~postgres.Postgres.run`, :py:meth:`~postgres.Postgres.one `,
81+ :py:meth:`~postgres.Postgres.all ` API introduced above. For the other 20%,
82+ :py:mod:`postgres` provides two context managers for working at increasingly
83+ lower levels of abstraction. The lowest level of abstraction in
8484:py:mod:`postgres` is a :py:mod:`psycopg2` `connection pool
8585<http://initd.org/psycopg/docs/pool.html>`_ that we configure and manage for
8686you. Everything in :py:mod:`postgres`, both the simple API and the context
@@ -294,27 +294,28 @@ class Postgres(object):
294294 :py:mod:`psycopg2` behavior, which is to return tuples. Whatever default
295295 you set here, you can override that default on a per-call basis by passing
296296 :py:attr:`record_type` or :py:attr:`cursor_factory` to
297- :py:meth:`~postgres.Postgres.all`,
298- :py:meth:`~postgres.Postgres.one_or_zero`, and
297+ :py:meth:`~postgres.Postgres.one`, :py:meth:`~postgres.Postgres.all`, and
299298 :py:meth:`~postgres.Postgres.get_transaction`.
300299
301300 The names in our simple API, :py:meth:`~postgres.Postgres.run`,
302- :py:meth:`~postgres.Postgres.all`, and
303- :py:meth:`~postgres.Postgres.one_or_zero`, were chosen to be short and
304- memorable, and to not conflict with the DB-API 2.0 :py:meth:`execute`,
305- :py:meth:`fetchall`, and :py:meth:`fetchone` methods, which have slightly
306- different semantics (under DB-API 2.0 you call :py:meth:`execute` on a
307- cursor and then call one of the :py:meth:`fetch*` methods on the same
308- cursor to retrieve records; with our simple API there is no second
309- :py:meth:`fetch` step). See `this ticket`_ for more of the rationale behind
310- these names. The context managers on this class are named starting with
311- :py:meth:`get_` to set them apart from the simple-case API. Note that when
312- working inside a block under one of the context managers, you're using
313- DB-API 2.0 (:py:meth:`execute` + :py:meth:`fetch*`), not our simple API
314- (:py:meth:`~postgres.Postgres.run`, :py:meth:`~postgres.Postgres.all`,
315- :py:meth:`~postgres.Postgres.one_or_zero`).
316-
317- .. _this ticket: https://github.com/gittip/postgres.py/issues/16
301+ :py:meth:`~postgres.Postgres.one`, and :py:meth:`~postgres.Postgres.all`,
302+ were chosen to be short and memorable, and to not directly conflict with
303+ the DB-API 2.0 :py:meth:`execute`, :py:meth:`fetchone`, and
304+ :py:meth:`fetchall` methods, which have slightly different semantics (under
305+ DB-API 2.0 you call :py:meth:`execute` on a cursor and then call one of the
306+ :py:meth:`fetch*` methods on the same cursor to retrieve records; with our
307+ simple API there is no second :py:meth:`fetch` step, and we also provide
308+ automatic dereferencing). See issues `16`_ and `20`_ for more of the
309+ rationale behind these names. The context managers on this class are named
310+ starting with :py:meth:`get_` to set them apart from the simple-case API.
311+ Note that when working inside a block under one of the context managers,
312+ you're using DB-API 2.0 (:py:meth:`execute` + :py:meth:`fetch*`, with no
313+ automatic dereferencing), not our simple API
314+ (:py:meth:`~postgres.Postgres.run`, :py:meth:`~postgres.Postgres.one`,
315+ :py:meth:`~postgres.Postgres.all`).
316+
317+ .. _16: https://github.com/gittip/postgres.py/issues/16
318+ .. _20: https://github.com/gittip/postgres.py/issues/20
318319
319320 """
320321
@@ -366,73 +367,7 @@ def run(self, sql, parameters=None, *a, **kw):
366367 txn .execute (sql , parameters )
367368
368369
369- def all (self , sql , parameters = None , record_type = None , * a , ** kw ):
370- """Execute a query and return all results.
371-
372- :param string sql: the SQL statement to execute
373- :param parameters: the bind parameters for the SQL statement
374- :type parameters: dict or tuple
375- :param record_type: the type of record to return
376- :type record_type: type or string
377- :param a: passed through to
378- :py:meth:`~postgres.Postgres.get_transaction`
379- :param kw: passed through to
380- :py:meth:`~postgres.Postgres.get_transaction`
381- :returns: :py:class:`list` of records or :py:class:`list` of single
382- values
383-
384- >>> db.all("SELECT * FROM foo ORDER BY bar")
385- [Record(bar='bit', baz=537), Record(bar='buz', baz=42)]
386-
387- You can use :py:attr:`record_type` to override the type associated with
388- the default :py:attr:`cursor_factory` for your
389- :py:class:`~postgres.Postgres` instance:
390-
391- >>> db.default_cursor_factory
392- <class 'psycopg2.extras.NamedTupleCursor'>
393- >>> db.all("SELECT * FROM foo ORDER BY bar", record_type=dict)
394- [{'bar': 'bit', 'baz': 537}, {'bar': 'buz', 'baz': 42}]
395-
396- That's a convenience so you don't have to go to the trouble of
397- remembering where :py:class:`~psycopg2.extras.RealDictCursor` lives and
398- importing it in order to get dictionaries back. If you do need more
399- control (maybe you have a custom cursor class), you can pass
400- :py:attr:`cursor_factory` explicitly, and that will override any
401- :py:attr:`record_type`:
402-
403- >>> from psycopg2.extensions import cursor
404- >>> db.all( "SELECT * FROM foo ORDER BY bar"
405- ... , record_type=dict
406- ... , cursor_factory=cursor
407- ... )
408- [('bit', 537), ('buz', 42)]
409-
410- If the query results in records with a single column, we return a list
411- of the values in that column rather than a list of records of values.
412-
413- >>> db.all("SELECT baz FROM foo ORDER BY bar")
414- [537, 42]
415-
416- This works for record types that are mappings (anything with a
417- :py:meth:`__len__` and a :py:meth:`values` method) as well those that
418- are sequences:
419-
420- >>> db.all("SELECT baz FROM foo ORDER BY bar", record_type=dict)
421- [537, 42]
422-
423- """
424- with self .get_transaction (record_type = record_type , * a , ** kw ) as txn :
425- txn .execute (sql , parameters )
426- recs = txn .fetchall ()
427- if recs and len (recs [0 ]) == 1 : # dereference
428- if hasattr (recs [0 ], 'values' ): # mapping
429- recs = [list (rec .values ())[0 ] for rec in recs ]
430- else : # sequence
431- recs = [rec [0 ] for rec in recs ]
432- return recs
433-
434-
435- def one_or_zero (self , sql , parameters = None , record_type = None , zero = None , \
370+ def one (self , sql , parameters = None , record_type = None , zero = None , \
436371 * a , ** kw ):
437372 """Execute a query and return a single result or a default value.
438373
@@ -453,12 +388,12 @@ def one_or_zero(self, sql, parameters=None, record_type=None, zero=None, \
453388 Use this for the common case where there should only be one record, but
454389 it may not exist yet.
455390
456- >>> db.one_or_zero ("SELECT * FROM foo WHERE bar='buz'")
391+ >>> db.one ("SELECT * FROM foo WHERE bar='buz'")
457392 Record(bar='buz', baz=42)
458393
459394 If the record doesn't exist, we return :py:class:`None`:
460395
461- >>> record = db.one_or_zero ("SELECT * FROM foo WHERE bar='blam'")
396+ >>> record = db.one ("SELECT * FROM foo WHERE bar='blam'")
462397 >>> if record is None:
463398 ... print("No blam yet.")
464399 ...
@@ -467,7 +402,7 @@ def one_or_zero(self, sql, parameters=None, record_type=None, zero=None, \
467402 If you pass :py:attr:`zero` we'll return that instead of
468403 :py:class:`None`:
469404
470- >>> db.one_or_zero ("SELECT * FROM foo WHERE bar='blam'", zero=False)
405+ >>> db.one ("SELECT * FROM foo WHERE bar='blam'", zero=False)
471406 False
472407
473408 We specifically don't support passing lambdas or other callables for
@@ -481,9 +416,9 @@ def one_or_zero(self, sql, parameters=None, record_type=None, zero=None, \
481416
482417 >>> db.default_cursor_factory
483418 <class 'psycopg2.extras.NamedTupleCursor'>
484- >>> db.one_or_zero ( "SELECT * FROM foo WHERE bar='buz'"
485- ... , record_type=dict
486- ... )
419+ >>> db.one ( "SELECT * FROM foo WHERE bar='buz'"
420+ ... , record_type=dict
421+ ... )
487422 {'bar': 'buz', 'baz': 42}
488423
489424 That's a convenience so you don't have to go to the trouble of
@@ -494,31 +429,31 @@ def one_or_zero(self, sql, parameters=None, record_type=None, zero=None, \
494429 :py:attr:`record_type`:
495430
496431 >>> from psycopg2.extensions import cursor
497- >>> db.one_or_zero ( "SELECT * FROM foo WHERE bar='buz'"
498- ... , record_type=dict
499- ... , cursor_factory=cursor
500- ... )
432+ >>> db.one ( "SELECT * FROM foo WHERE bar='buz'"
433+ ... , record_type=dict
434+ ... , cursor_factory=cursor
435+ ... )
501436 ('buz', 42)
502437
503438 If the query result has only one column, then we dereference that for
504439 you.
505440
506- >>> db.one_or_zero ("SELECT baz FROM foo WHERE bar='buz'")
441+ >>> db.one ("SELECT baz FROM foo WHERE bar='buz'")
507442 42
508443
509444 And if the dereferenced value is :py:class:`None`, we return the value
510445 of :py:attr:`zero`:
511446
512- >>> db.one_or_zero ("SELECT sum(baz) FROM foo WHERE bar='nope'", zero=0)
447+ >>> db.one ("SELECT sum(baz) FROM foo WHERE bar='nope'", zero=0)
513448 0
514449
515450 Dereferencing will use :py:meth:`.values` if it exists on the record,
516451 so it should work for both mappings and sequences.
517452
518- >>> db.one_or_zero ( "SELECT sum(baz) FROM foo WHERE bar='nope'"
519- ... , record_type=dict
520- ... , zero=0
521- ... )
453+ >>> db.one ( "SELECT sum(baz) FROM foo WHERE bar='nope'"
454+ ... , record_type=dict
455+ ... , zero=0
456+ ... )
522457 0
523458
524459 """
@@ -537,12 +472,78 @@ def one_or_zero(self, sql, parameters=None, record_type=None, zero=None, \
537472 return out
538473
539474
475+ def all (self , sql , parameters = None , record_type = None , * a , ** kw ):
476+ """Execute a query and return all results.
477+
478+ :param string sql: the SQL statement to execute
479+ :param parameters: the bind parameters for the SQL statement
480+ :type parameters: dict or tuple
481+ :param record_type: the type of record to return
482+ :type record_type: type or string
483+ :param a: passed through to
484+ :py:meth:`~postgres.Postgres.get_transaction`
485+ :param kw: passed through to
486+ :py:meth:`~postgres.Postgres.get_transaction`
487+ :returns: :py:class:`list` of records or :py:class:`list` of single
488+ values
489+
490+ >>> db.all("SELECT * FROM foo ORDER BY bar")
491+ [Record(bar='bit', baz=537), Record(bar='buz', baz=42)]
492+
493+ You can use :py:attr:`record_type` to override the type associated with
494+ the default :py:attr:`cursor_factory` for your
495+ :py:class:`~postgres.Postgres` instance:
496+
497+ >>> db.default_cursor_factory
498+ <class 'psycopg2.extras.NamedTupleCursor'>
499+ >>> db.all("SELECT * FROM foo ORDER BY bar", record_type=dict)
500+ [{'bar': 'bit', 'baz': 537}, {'bar': 'buz', 'baz': 42}]
501+
502+ That's a convenience so you don't have to go to the trouble of
503+ remembering where :py:class:`~psycopg2.extras.RealDictCursor` lives and
504+ importing it in order to get dictionaries back. If you do need more
505+ control (maybe you have a custom cursor class), you can pass
506+ :py:attr:`cursor_factory` explicitly, and that will override any
507+ :py:attr:`record_type`:
508+
509+ >>> from psycopg2.extensions import cursor
510+ >>> db.all( "SELECT * FROM foo ORDER BY bar"
511+ ... , record_type=dict
512+ ... , cursor_factory=cursor
513+ ... )
514+ [('bit', 537), ('buz', 42)]
515+
516+ If the query results in records with a single column, we return a list
517+ of the values in that column rather than a list of records of values.
518+
519+ >>> db.all("SELECT baz FROM foo ORDER BY bar")
520+ [537, 42]
521+
522+ This works for record types that are mappings (anything with a
523+ :py:meth:`__len__` and a :py:meth:`values` method) as well those that
524+ are sequences:
525+
526+ >>> db.all("SELECT baz FROM foo ORDER BY bar", record_type=dict)
527+ [537, 42]
528+
529+ """
530+ with self .get_transaction (record_type = record_type , * a , ** kw ) as txn :
531+ txn .execute (sql , parameters )
532+ recs = txn .fetchall ()
533+ if recs and len (recs [0 ]) == 1 : # dereference
534+ if hasattr (recs [0 ], 'values' ): # mapping
535+ recs = [list (rec .values ())[0 ] for rec in recs ]
536+ else : # sequence
537+ recs = [rec [0 ] for rec in recs ]
538+ return recs
539+
540+
540541 def _some (self , sql , parameters , lo , hi , record_type , * a , ** kw ):
541542
542- # This is undocumented (and largely untested) because I think it's a
543- # rare case where this is wanted directly. It was added to make one and
544- # one_or_zero DRY when we had one . Help yourself to it now that you've
545- # found it. :^)
543+ # This is undocumented because I think it's a rare case where this is
544+ # wanted directly. It was added to make one and one_or_zero DRY when we
545+ # had those two methods . Help yourself to _some now that you've found
546+ # it. :^)
546547
547548 with self .get_transaction (record_type = record_type , * a , ** kw ) as txn :
548549 txn .execute (sql , parameters )
@@ -620,9 +621,9 @@ def register_model(self, ModelSubclass):
620621 if getattr (ModelSubclass , 'typname' , None ) is None :
621622 raise NoTypeSpecified (ModelSubclass )
622623
623- n = self .one_or_zero ( "SELECT count(*) FROM pg_type WHERE typname=%s"
624- , (ModelSubclass .typname ,)
625- )
624+ n = self .one ( "SELECT count(*) FROM pg_type WHERE typname=%s"
625+ , (ModelSubclass .typname ,)
626+ )
626627 if n < 1 :
627628 # Could be more than one since we don't constrain by typnamespace.
628629 # XXX What happens then?
0 commit comments