Skip to content

Commit 5874c27

Browse files
author
James William Pye
committed
Bring documentation up-to-date with the new APIs.
Organize COPY into the statement section as it makes less sense now that cursors are primarily for random access.
1 parent bb7f3ee commit 5874c27

8 files changed

Lines changed: 150 additions & 105 deletions

File tree

README

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ developers working with PostgreSQL.
1212
Installation
1313
------------
1414

15-
Installation should be as simple as::
15+
Installation *should* be as simple as::
1616

1717
$ python3.0 ./setup.py install
1818

@@ -28,9 +28,6 @@ Basic Driver Usage
2828
Using PG-API is recommended as it provides more utility for the user. However, a
2929
DB-API 2.0 driver is provided: `postgresql.driver.dbapi20`.
3030

31-
Sample PG-API Code
32-
^^^^^^^^^^^^^^^^^^
33-
3431
>>> import postgresql
3532
>>> db = postgresql.open('pq://user:password@host:port/database')
3633
>>> get_table = db.prepare("select * from information_schema.tables where table_name = $1")
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
##
2+
# copyright 2009, James William Pye
3+
# http://python.projects.postgresql.org
4+
##
5+
r"""
6+
Changes
7+
=======
8+
9+
0.8.0 released on 2009-04-02
10+
----------------------------
11+
12+
Differences from the original pg/python projects.
13+
14+
* Integrate projects into a single package. Remove "codenames".
15+
* pg_greentrunk evolved into PG-API, postgresql.api.
16+
* Add new execution methods to statement objects: chunks, rows, declare.
17+
* Refactor connection negotiation code to use a generator. (xact3.Negotiation)
18+
* Remove sixbit confusion from postgresql.exceptions.
19+
* Integrate fcrypt module for crypt authentication.
20+
* Remove pytz dependency, always use UTC for timestamptz.
21+
* Remove netaddr dependency.
22+
* Improve DB-API interface by allowing subjective paramstyle. (psycopg2 compat)
23+
* Provide autocommit support on DB-API connections.
24+
* Add support for binary numeric.
25+
* Add proper support for sslmode and connect_timeout.
26+
* Conditionally DECLARE certain cursors WITH HOLD when outside of blocks.
27+
* Add typed support for fetches from db.cursor_from_id().
28+
* Change the test infrastructure to automatically create a cluster.
29+
"""
30+
__docformat__ = 'reStructuredText'
31+
if __name__ == '__main__':
32+
import sys
33+
if (sys.argv + [None])[1] == 'dump':
34+
sys.stdout.write(__doc__)
35+
else:
36+
try:
37+
help(__package__ + '.index')
38+
except NameError:
39+
help(__name__)

postgresql/documentation/clientparameters.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,15 @@
146146
``prompt_title``
147147
Additional title to use if a prompt is requested. This can also be specified
148148
in the ``parameters`` as the ``prompt_title`` key. This *augments* the IRI
149-
display on the prompt. Defaults to ``''``.
149+
display on the prompt. Defaults to an empty string, ``''``.
150150
151151
The resolution process is effected by the contents of the given ``parameters``.
152152
Notable keywords:
153153
154154
``prompt_password``
155155
If present in the given parameters, the user will be prompted for the using
156-
the given ``getpass`` function. This disables the pgpassfile lookup process.
156+
the given ``getpass`` function. This disables the password file lookup
157+
process.
157158
158159
``prompt_title``
159160
This states a default prompt title to use. If the ``prompt_title`` keyword

postgresql/documentation/driver.py

Lines changed: 97 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
2020
.. note::
2121
PostgreSQL versions 8.1 and earlier do not support standard conforming
22-
strings. A warning will be raised whenever a connection is established to a
23-
server that does not support standard conforming strings.
22+
strings. A warning will be raised whenever a connection is established to a
23+
server that does not support standard conforming strings.
2424
2525
The following identifiers are regularly used as shorthands for significant
2626
interface elements:
@@ -153,16 +153,16 @@
153153
The driver, `postgresql.driver.default` provides a set of connectors for making
154154
a connection:
155155
156-
``driver.host``
156+
``postgresql.driver.default.host(...)``
157157
Provides a ``getaddrinfo()`` abstraction for establishing a connection.
158158
159-
``driver.ip4``
159+
``postgresql.driver.default.ip4(...)``
160160
Connect to a single IPv4 addressed host.
161161
162-
``driver.ip6``
162+
``postgresql.driver.default.ip6(...)``
163163
Connect to a single IPv6 addressed host.
164164
165-
``driver.unix``
165+
``postgresql.driver.default.unix(...)``
166166
Connect to a single unix domain socket.
167167
168168
``host`` is the usual connector used to establish a connection::
@@ -257,20 +257,6 @@
257257
Revocation list file path. [Currently not checked.]
258258
259259
260-
Connection Failures
261-
-------------------
262-
263-
If a connection cannot be established, a
264-
`postgresql.exceptions.ClientCannotConnectError` will be raised.
265-
266-
This exception carries the cause of the failures. However, in situations
267-
involving ``Host`` connectors and ``'prefer'`` or ``'allow'`` ``sslmode``'s,
268-
multiple attempts may be made before the exception is thrown. Therefore,
269-
multiple exception conditions may have contributed to the ultimate
270-
failure of the connection, and reliance on ``__context__`` or ``__cause__`` to
271-
provide this information is inappropriate.
272-
273-
274260
Connections
275261
===========
276262
@@ -438,7 +424,7 @@
438424
Consider the data contained in ``c`` from above, 'hello world!'. To get at this
439425
data directly from the ``__call__(...)`` method, it looks something like::
440426
441-
>>> ps().read()[0][0]
427+
>>> ps()[0][0]
442428
443429
To simplify access to simple data, the ``first`` method will simply return
444430
the "first" of the result set::
@@ -660,6 +646,77 @@
660646
appropriate encoding.
661647
662648
649+
COPY Statements
650+
---------------
651+
652+
`postgresql.driver` transparently supports PostgreSQL's COPY command. To the
653+
user, COPY will act exactly like other statements that produce tuples; COPY
654+
tuples, however, are `bytes` objects. The only distinction in usability is that
655+
the COPY *should* be completed before other actions take place on the
656+
connection--this is important when a COPY is invoked via ``rows()`` or
657+
``chunks()``.
658+
659+
In situations where other actions are invoked during a ``COPY TO STDOUT``, the
660+
entire result set of the COPY will be read. However, no error will be raised so
661+
long as there is enough memory available, so it is *very* desirable to avoid
662+
doing other actions on the connection while a COPY is active.
663+
664+
In situations where other actions are invoked during a ``COPY FROM STDIN``, a
665+
COPY failure error will occur. The driver manages the connection state in such
666+
a way that will purposefully cause the error as the COPY was inappropriately
667+
interrupted. This not usually a problem as the ``load(...)`` method must
668+
complete the COPY command before returning.
669+
670+
Copy data is always transferred using ``bytes`` objects. Even in cases where the
671+
COPY is not in ``BINARY`` mode. Any needed encoding transformations *must* be
672+
made the caller. This is done to avoid any unnecessary overhead by default::
673+
674+
>>> ps = db.prepare("COPY (SELECT i FROM generate_series(0, 99) AS g(i)) TO STDOUT")
675+
>>> r = ps()
676+
>>> len(r)
677+
100
678+
>>> r[0]
679+
b'0\n'
680+
>>> r[-1]
681+
b'99\n'
682+
683+
Of course, invoking a statement that way will ready the entire result-set into
684+
memory, which is not usually desirable for COPY. Using the ``chunks(...)``
685+
iterator is the fastest way to move data::
686+
687+
>>> ci = ps.chunks()
688+
>>> import sys
689+
>>> for rowset in ps.chunks():
690+
... sys.stdout.buffer.writelines(rowset)
691+
...
692+
<Lots of Data>
693+
694+
``COPY FROM STDIN`` commands are supported via
695+
`postgresql.api.PreparedStatement.load`. Each invocation to ``load``
696+
is a single invocation of COPY. ``load`` takes an iterable of COPY lines
697+
to send to the server::
698+
699+
>>> db.execute("""
700+
... CREATE TABLE sample_copy (
701+
... sc_number int,
702+
... sc_text text
703+
... );
704+
... """)
705+
>>> copyin = db.prepare('COPY sample_copy FROM STDIN')
706+
>>> copyin.load([
707+
... b'123\tone twenty three\n',
708+
... b'350\ttree fitty\n',
709+
... ])
710+
711+
The ``load()`` method is trained to identify chunk iterators so that direct
712+
transfers from a source database to a destination database could be
713+
made in a streaming fashion::
714+
715+
>>> copyout = src.prepare('COPY atable TO STDOUT')
716+
>>> copyin = dst.prepare('COPY atable FROM STDIN')
717+
>>> copyin.load(copyout.chunks())
718+
719+
663720
Cursors
664721
=======
665722
@@ -801,19 +858,19 @@
801858
... EXTRACT(years FROM AGE(employee_dob)) AS age
802859
... ORDER BY age ASC
803860
... """)
804-
>>> snapshot = emps_by_age.declare()
861+
>>> c = emps_by_age.declare()
805862
>>> # seek to the end, ``2`` works as well.
806-
>>> snapshot.seek(0, 'FROM_END')
863+
>>> c.seek(0, 'FROM_END')
807864
>>> # scroll back one, ``1`` works as well.
808-
>>> snapshot.seek(-1, 'RELATIVE')
865+
>>> c.seek(-1, 'RELATIVE')
809866
>>> # and back to the beginning again
810-
>>> snapshot.seek(0)
867+
>>> c.seek(0)
811868
812869
Additionally, scrollable cursors support backward fetches by specifying the
813870
direction keyword argument::
814871
815-
>>> snapshot.seek(0, 2)
816-
>>> snapshot.read(1, 'BACKWARD')
872+
>>> c.seek(0, 2)
873+
>>> c.read(1, 'BACKWARD')
817874
818875
819876
Cursor Direction
@@ -851,57 +908,6 @@
851908
>>> c.read(10, 'BACKWARD') == reverse_c.read(10, 'BACKWARD')
852909
853910
854-
COPY
855-
====
856-
857-
`postgresql.driver` transparently supports PostgreSQL's COPY command. To the
858-
user, COPY will act exactly like other statements that produce tuples; COPY
859-
tuples, however, are `bytes` objects. The only distinction in usability is that
860-
the COPY *should* be completed before other actions take place on the
861-
connection--this is important when a COPY is invoked via ``rows()`` or
862-
``chunks()``.
863-
864-
In situations where other actions are invoked during a ``COPY TO STDOUT``, the
865-
entire result set of the COPY will be read. However, no error will be raised so
866-
long as there is enough memory available, so it is *very* desirable to avoid
867-
doing other actions on the connection while a COPY is active.
868-
869-
In situations where other actions are invoked during a ``COPY FROM STDIN``, a
870-
COPY failure error will occur. The driver manages the connection state in such
871-
a way that will purposefully cause the error as the COPY was inappropriately
872-
interrupted. This not usually a problem as the ``load(...)`` method must
873-
complete the COPY command before returning.
874-
875-
Copy data is always transferred using ``bytes`` objects. Even in cases where the
876-
COPY is not in ``BINARY`` mode. Any needed encoding transformations *must* be
877-
made the caller. This is done to avoid any unnecessary overhead by default.
878-
879-
``COPY FROM STDIN`` commands are supported via
880-
`postgresql.api.PreparedStatement.load`. Each invocation to ``load``
881-
is a single invocation of COPY. ``load`` takes an iterable of COPY lines
882-
to send to the server::
883-
884-
>>> db.execute("""
885-
... CREATE TABLE sample_copy (
886-
... sc_number int,
887-
... sc_text text
888-
... );
889-
... """)
890-
>>> copyin = db.prepare('COPY sample_copy FROM STDIN')
891-
>>> copyin.load([
892-
... b'123\tone twenty three\n',
893-
... b'350\ttree fitty\n',
894-
... ])
895-
896-
Copy cursors and the load interface was designed to be used together so that
897-
direct transfers from a source database to a destination database could be
898-
made in a streaming fashion::
899-
900-
>>> copyout = src.prepare('COPY atable TO STDOUT')
901-
>>> copyin = dst.prepare('COPY atable FROM STDIN')
902-
>>> copyin.load(copyout.chunks())
903-
904-
905911
Rows
906912
====
907913
@@ -1146,13 +1152,11 @@
11461152
... $body$;
11471153
... """)
11481154
>>> srfcomposite = db.proc('srfcomposite()')
1149-
>>> c = srfcomposite()
1150-
>>> c
1151-
<postgresql.driver.pq3.DeclaredCursor object>
1152-
>>> c.read(1)
1153-
[(900, 'sample text')]
1154-
>>> r = c.read(1)[0]
1155-
>>> r['i'], r['t']
1155+
>>> r = srfcomposite()
1156+
>>> next(r)
1157+
(900, 'sample text')
1158+
>>> v = next(r)
1159+
>>> v['i'], v['t']
11561160
(450, 'more sample text')
11571161
11581162
@@ -1220,13 +1224,11 @@
12201224
in a way that cannot be formed around single, sequential blocks of code.
12211225
Generally, using these methods require additional work to be performed by the
12221226
code that is managing the transaction.
1223-
If usage of these direct, instructional methods is necessary, there is one
1224-
important factor to keep in mind:
1225-
1226-
* If the database is in an error state when a block's commit() is executed,
1227-
an implicit rollback will occur. The transaction object will simply follow
1228-
instructions and issue the ``COMMIT`` statement, and it will succeed without
1229-
exception.
1227+
If usage of these direct, instructional methods is necessary, it is important to
1228+
note that if the database is in an error state when a *transaction block's*
1229+
commit() is executed, an implicit rollback will occur. The transaction object
1230+
will simply follow instructions and issue the ``COMMIT`` statement, and it will
1231+
succeed without exception.
12301232
12311233
12321234
Error Control
@@ -1325,9 +1327,9 @@
13251327
Traceback (most recent call last):
13261328
...
13271329
postgresql.exceptions.ActiveTransactionError: COMMIT PREPARED cannot run inside a transaction block
1330+
CAUSE: The prepared transaction was not prepared prior to the block's exit.
13281331
CODE: 25001
13291332
SEVERITY: ERROR
1330-
INTERFACE: The prepared transaction was not prepared prior to the block's exit.
13311333
LOCATION: File 'xact.c', line 2648, in PreventTransactionChain
13321334
13331335
@@ -1360,8 +1362,8 @@
13601362
postgresql.exceptions.UndefinedObjectError: ...
13611363
13621364
This allows recovery operations to identify the existence of the prepared
1363-
transaction. Global transaction managers should trap this exception in order to
1364-
identify how to proceed.
1365+
transaction. Transaction managers should trap this exception in order to
1366+
determine how to proceed.
13651367
13661368
13671369
Settings

postgresql/documentation/gotchas.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
2525
To avoid this problem from ever happening, set the `client_encoding` early.
2626
Furthermore, it is probably best to never change the `client_encoding` as the
27-
driver automatically makes the necessary tranformation to Python strings.
27+
driver automatically makes the necessary transformation to Python strings.
2828
2929
3030
The user and password is correct, but does it not work when using `postgresql.driver`
@@ -73,7 +73,7 @@
7373
is not an string, it will fail to unpack the row or pack the appropriate data for
7474
the element or attribute.
7575
76-
In most cases issues related to this can be avoided with exlicit casts to text.
76+
In most cases issues related to this can be avoided with explicit casts to text.
7777
'''
7878

7979
__docformat__ = 'reStructuredText'

postgresql/documentation/index.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
py-postgresql
88
=============
99
10-
py-postgresql is a project dedicated to improving Python interfaces to
10+
py-postgresql is a project dedicated to improving the Python interfaces to
1111
PostgreSQL.
1212
1313
At its core, py-postgresql provides a PG-API, `postgresql.api`, and
@@ -32,6 +32,10 @@
3232
Gotchas
3333
`postgresql.documentation.gotchas`
3434
35+
Changes
36+
`postgresql.documentation.changes`
37+
38+
3539
------------------
3640
Sample PG-API Code
3741
------------------

0 commit comments

Comments
 (0)