32
32
>>> db.run("INSERT INTO foo VALUES ('buz', 42)")
33
33
>>> db.run("INSERT INTO foo VALUES ('bit', 537)")
34
34
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
+
35
42
Use :py:meth:`~postgres.Postgres.all` to run SQL and fetch all results:
36
43
37
44
>>> db.all("SELECT * FROM foo ORDER BY bar")
38
45
[Record(bar='bit', baz=537), Record(bar='buz', baz=42)]
39
46
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
-
47
47
If your queries return one column then you get just the value or a list of
48
48
values instead of a record or list of records:
49
49
50
- >>> db.one_or_zero ("SELECT baz FROM foo WHERE bar='buz'")
50
+ >>> db.one ("SELECT baz FROM foo WHERE bar='buz'")
51
51
42
52
52
>>> db.all("SELECT baz FROM foo ORDER BY bar")
53
53
[537, 42]
65
65
against `SQL injection`_. (This is inspired by old-style Python string
66
66
formatting, but it is not the same.)
67
67
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"})
69
69
Record(bar='buz', baz=42)
70
70
71
71
Never build SQL strings out of user input!
77
77
++++++++++++++++
78
78
79
79
Eighty 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
84
84
:py:mod:`postgres` is a :py:mod:`psycopg2` `connection pool
85
85
<http://initd.org/psycopg/docs/pool.html>`_ that we configure and manage for
86
86
you. Everything in :py:mod:`postgres`, both the simple API and the context
@@ -294,27 +294,28 @@ class Postgres(object):
294
294
:py:mod:`psycopg2` behavior, which is to return tuples. Whatever default
295
295
you set here, you can override that default on a per-call basis by passing
296
296
: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
299
298
:py:meth:`~postgres.Postgres.get_transaction`.
300
299
301
300
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
318
319
319
320
"""
320
321
@@ -366,73 +367,7 @@ def run(self, sql, parameters=None, *a, **kw):
366
367
txn .execute (sql , parameters )
367
368
368
369
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 , \
436
371
* a , ** kw ):
437
372
"""Execute a query and return a single result or a default value.
438
373
@@ -453,12 +388,12 @@ def one_or_zero(self, sql, parameters=None, record_type=None, zero=None, \
453
388
Use this for the common case where there should only be one record, but
454
389
it may not exist yet.
455
390
456
- >>> db.one_or_zero ("SELECT * FROM foo WHERE bar='buz'")
391
+ >>> db.one ("SELECT * FROM foo WHERE bar='buz'")
457
392
Record(bar='buz', baz=42)
458
393
459
394
If the record doesn't exist, we return :py:class:`None`:
460
395
461
- >>> record = db.one_or_zero ("SELECT * FROM foo WHERE bar='blam'")
396
+ >>> record = db.one ("SELECT * FROM foo WHERE bar='blam'")
462
397
>>> if record is None:
463
398
... print("No blam yet.")
464
399
...
@@ -467,7 +402,7 @@ def one_or_zero(self, sql, parameters=None, record_type=None, zero=None, \
467
402
If you pass :py:attr:`zero` we'll return that instead of
468
403
:py:class:`None`:
469
404
470
- >>> db.one_or_zero ("SELECT * FROM foo WHERE bar='blam'", zero=False)
405
+ >>> db.one ("SELECT * FROM foo WHERE bar='blam'", zero=False)
471
406
False
472
407
473
408
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, \
481
416
482
417
>>> db.default_cursor_factory
483
418
<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
+ ... )
487
422
{'bar': 'buz', 'baz': 42}
488
423
489
424
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, \
494
429
:py:attr:`record_type`:
495
430
496
431
>>> 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
+ ... )
501
436
('buz', 42)
502
437
503
438
If the query result has only one column, then we dereference that for
504
439
you.
505
440
506
- >>> db.one_or_zero ("SELECT baz FROM foo WHERE bar='buz'")
441
+ >>> db.one ("SELECT baz FROM foo WHERE bar='buz'")
507
442
42
508
443
509
444
And if the dereferenced value is :py:class:`None`, we return the value
510
445
of :py:attr:`zero`:
511
446
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)
513
448
0
514
449
515
450
Dereferencing will use :py:meth:`.values` if it exists on the record,
516
451
so it should work for both mappings and sequences.
517
452
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
+ ... )
522
457
0
523
458
524
459
"""
@@ -537,12 +472,78 @@ def one_or_zero(self, sql, parameters=None, record_type=None, zero=None, \
537
472
return out
538
473
539
474
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
+
540
541
def _some (self , sql , parameters , lo , hi , record_type , * a , ** kw ):
541
542
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. :^)
546
547
547
548
with self .get_transaction (record_type = record_type , * a , ** kw ) as txn :
548
549
txn .execute (sql , parameters )
@@ -620,9 +621,9 @@ def register_model(self, ModelSubclass):
620
621
if getattr (ModelSubclass , 'typname' , None ) is None :
621
622
raise NoTypeSpecified (ModelSubclass )
622
623
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
+ )
626
627
if n < 1 :
627
628
# Could be more than one since we don't constrain by typnamespace.
628
629
# XXX What happens then?
0 commit comments