@@ -74,16 +74,23 @@ you must use :class:`PostgresqlExtDatabase`.
7474
7575.. _psycopg2-vs-psycopg3 :
7676
77- psycopg2 versus psycopg3
78- ------------------------
77+ psycopg2 vs psycopg3
78+ --------------------
7979
80- Peewee supports both drivers and uses psycopg2 when both are installed,
81- unless ``prefer_psycopg3 `` is given. Queries generated by peewee behave
82- identically on either. The difference is in how hand-written SQL is bound:
83- psycopg2 interpolates parameters into the query string on the client,
84- psycopg3 sends the query and parameters separately and Postgres binds them.
85- Server-side binding only accepts parameters in value positions of a single
86- plannable statement:
80+ Peewee supports both drivers, and will use whichever is installed. If **both **
81+ psycopg2 and psycopg(3) are installed, Peewee defaults to psycopg2 unless
82+ ``prefer_psycopg3=True `` is specified:
83+
84+ .. code-block :: python
85+
86+ # If both psycopg2 and psycopg3 are installed, use psycopg3.
87+ db = PostgresqlDatabase(' peewee_test' , prefer_psycopg3 = True )
88+
89+ Queries generated by peewee behave identically on either. The difference is in
90+ how hand-written SQL is bound: psycopg2 interpolates parameters into the query
91+ string on the client, while psycopg3 sends the query and parameters separately
92+ and Postgres binds them. psycopg3's server-side binding only accepts parameters
93+ in value positions within a single query:
8794
8895.. code-block :: python
8996
@@ -103,8 +110,8 @@ passing psycopg's ``ClientCursor``:
103110
104111 import psycopg
105112
106- db = PostgresqlExtDatabase (' my_app' , prefer_psycopg3 = True ,
107- cursor_factory = psycopg.ClientCursor)
113+ db = PostgresqlDatabase (' my_app' , prefer_psycopg3 = True ,
114+ cursor_factory = psycopg.ClientCursor)
108115
109116 In exchange, psycopg3 automatically promotes frequently-executed queries to
110117server-side prepared statements, skipping repeated parse and plan overhead.
@@ -985,18 +992,17 @@ For more information, see the `Postgres full-text search docs <https://www.postg
985992Server-Side Cursors
986993-------------------
987994
988- For large result sets, server-side (named) cursors stream rows from the server
989- rather than loading the entire result into memory. Rows are fetched
995+ For large result sets, server-side (or named) cursors stream rows from the
996+ server rather than loading the entire result into memory. Rows are fetched
990997transparently from the server as you iterate. A regular cursor, by contrast,
991- buffers the complete result set on the client at execute time, even when
992- iterating with :meth: `~BaseQuery.iterator `.
998+ buffers the complete result set on the client at execute time.
993999
9941000Refer to your driver documentation for details:
9951001
9961002* `psycopg2 server-side cursors <https://www.psycopg.org/docs/usage.html#server-side-cursors >`__
9971003* `psycopg3 server-side cursors <https://www.psycopg.org/psycopg3/docs/advanced/cursors.html#server-side-cursors >`__
9981004
999- To use server-side (or named) cursors, you must be using :class: `PostgresqlExtDatabase `.
1005+ To use server-side cursors, you must be using :class: `PostgresqlExtDatabase `.
10001006
10011007Wrap any SELECT query with :func: `ServerSide `:
10021008
@@ -1019,30 +1025,40 @@ Wrap any SELECT query with :func:`ServerSide`:
10191025
10201026 Rows are fetched from the server in batches of ``array_size ``, which defaults
10211027to the driver's ``itersize `` (2000 with psycopg2, 100 with psycopg3). For
1022- large scans specify ``array_size `` explicitly.
1028+ large scans specify ``array_size `` explicitly:
1029+
1030+ .. code-block :: python
10231031
1024- A named cursor is ordinarily bound to a transaction and is destroyed when the
1025- transaction ends. Declaring it ``WITH HOLD `` lets it outlive the transaction.
1026- The server pays for this at commit by copying the cursor's remaining rows
1027- into temporary storage, and later fetches read from that copy. Peewee
1028- connections autocommit, so a ``WITH HOLD `` cursor opened outside a
1032+ for page_view in ServerSide(large_query, array_size = 1000 ):
1033+ # Do something interesting.
1034+ pass
1035+
1036+ Ordinarily, a server-side cursor is bound to a transaction and is destroyed when the
1037+ transaction ends. To use a server-side cursor outside a transaction, it must be
1038+ declared ``WITH HOLD ``, which has a couple consequences:
1039+
1040+ * Server has to copy the cursor's rows into temporary storage upon commit, so
1041+ subsequent fetches read from the frozen copy.
1042+ * Cursor must be exhausted or explicitly closed in order to release the held
1043+ resources.
1044+
1045+ Peewee connections autocommit, so a ``WITH HOLD `` cursor opened outside a
10291046transaction is committed at once and materializes the entire result set
10301047before the first row arrives. Inside a transaction nothing is copied and
10311048rows stream on demand.
10321049
1033- Peewee declares ``WITH HOLD `` only when it has to. With psycopg3, a cursor
1034- opened inside a transaction is a plain named cursor. It streams, commit is
1035- instant, and the cursor ends with the transaction. Iterating after the
1036- transaction closes raises ``InvalidCursorName ``. psycopg2 does not allow
1037- plain named cursors on autocommit connections, so peewee always declares
1038- ``WITH HOLD `` there. Inside a transaction such a cursor streams all the same,
1039- but if it is still open when the transaction commits, the remaining rows are
1040- copied and the cursor survives.
1041-
1042- Iterate inside a transaction when you can. Use a cursor with no transaction
1043- when the iteration is too long to hold one open, and accept the up-front
1044- materialization. When the result fits in client memory, a regular cursor is
1045- simpler still.
1050+ Peewee declares ``WITH HOLD `` only when it has to:
1051+
1052+ * psycopg3: server-side cursors opened inside a transaction do not specify
1053+ ``WITH HOLD ``. The cursor streams normally and the cursor ends with the
1054+ transaction. Iterating after the transaction closes will raise ``InvalidCursorName ``.
1055+ * psycopg2 does not allow server-side cursors on autocommit connections, so
1056+ peewee always declares ``WITH HOLD `` on psycopg2. Inside a transaction such a
1057+ cursor streams normally, but if it is still open when the transaction
1058+ commits, the remaining rows are copied and the cursor and resources survive.
1059+
1060+ Use server-side cursors inside a transaction whenever possible. When the result
1061+ fits in client memory, a regular (non-server-side) cursor is preferable.
10461062
10471063.. list-table ::
10481064 :header-rows: 1
0 commit comments