Skip to content

Commit 8edc203

Browse files
committed
docs: Better document cursors
1 parent 7088e97 commit 8edc203

File tree

3 files changed

+76
-6
lines changed

3 files changed

+76
-6
lines changed

asyncpg/connection.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ async def _get_statement(self, query, timeout):
121121
return state
122122

123123
def cursor(self, query, *args, prefetch=None, timeout=None):
124+
"""Return a *cursor factory* for the specified query.
125+
126+
:param args: Query arguments.
127+
:param int prefetch: The number of rows the *cursor iterator*
128+
will prefetch (defaults to ``50``.)
129+
:param float timeout: Optional timeout in seconds.
130+
131+
:return: A :class:`~cursor.CursorFactory` object.
132+
"""
124133
return cursor.CursorFactory(self, query, None, args,
125134
prefetch, timeout)
126135

asyncpg/prepared_stmt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def get_attributes(self):
4343

4444
def cursor(self, *args, prefetch=None,
4545
timeout=None) -> cursor.CursorFactory:
46-
"""Return a *cursor interface* for the prepared statement.
46+
"""Return a *cursor factory* for the prepared statement.
4747
4848
:param args: Query arguments.
4949
:param int prefetch: The number of rows the *cursor iterator*

docs/api/index.rst

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,17 +139,78 @@ provided by asyncpg supports *asynchronous iteration* via the ``async for``
139139
statement, and also a way to read row chunks and skip forward over the
140140
result set.
141141

142+
To iterate over a cursor using a connection object use
143+
:meth:`Conection.cursor() <asyncpg.connection.Connection.cursor>`.
144+
To make the iteration efficient, the cursor will prefetch records to
145+
reduce the number of queries sent to the server:
146+
147+
.. code-block:: python
148+
149+
async def iterate(con: Connection):
150+
async with con.transaction():
151+
# Postgres requires non-scrollable cursors to be created
152+
# and used in a transaction.
153+
async for record in con.cursor('SELECT generate_series(0, 100)'):
154+
print(record)
155+
156+
Or, alternatively, you can iterate over the cursor manually (cursor
157+
won't be prefetching any rows):
158+
159+
.. code-block:: python
160+
161+
async def iterate(con: Connection):
162+
async with con.transaction():
163+
# Postgres requires non-scrollable cursors to be created
164+
# and used in a transaction.
165+
166+
async with con.transaction():
167+
# Create a Cursor object
168+
cur = await con.cursor('SELECT generate_series(0, 100)')
169+
170+
# Move the cursor 10 rows forward
171+
await cur.forward(10)
172+
173+
# Fetch one row and print it
174+
print(await cur.fetchrow())
175+
176+
# Fetch a list of 5 rows and print it
177+
print(await cur.fetch(5))
178+
179+
It's also possible to create cursors from prepared statements:
180+
181+
.. code-block:: python
182+
183+
async def iterate(con: Connection):
184+
# Create a prepared statement that will accept one argument
185+
stmt = await con.prepare('SELECT generate_series(0, $1)')
186+
187+
async with con.transaction():
188+
# Postgres requires non-scrollable cursors to be created
189+
# and used in a transaction.
190+
191+
# Execute the prepared statement passing `10` as the
192+
# argument -- that will generate a series or records
193+
# from 0..10. Iterate over all of them and print every
194+
# record.
195+
async for record in stmt.cursor(10):
196+
print(record)
197+
198+
142199
.. note::
143200

144-
Cursors created by a call to :meth:`PreparedStatement.cursor()` are
145-
*non-scrollable*: they can only be read forwards. To create a scrollable
201+
Cursors created by a call to
202+
:meth:`Conection.cursor() <asyncpg.connection.Connection.cursor>` or
203+
:meth:`PreparedStatement.cursor() <asyncpg.prepared_stmt.PreparedStatement.cursor>`
204+
are *non-scrollable*: they can only be read forwards. To create a scrollable
146205
cursor, use the ``DECLARE ... SCROLL CURSOR`` SQL statement directly.
147206

148207
.. warning::
149208

150-
Cursors created by a call to :meth:`PreparedStatement.cursor()`
151-
cannot be used outside of a transaction. Any such attempt will result
152-
in :exc:`~asyncpg.exceptions.InterfaceError`.
209+
Cursors created by a call to
210+
:meth:`Conection.cursor() <asyncpg.connection.Connection.cursor>` or
211+
:meth:`PreparedStatement.cursor() <asyncpg.prepared_stmt.PreparedStatement.cursor>`
212+
cannot be used outside of a transaction. Any such attempt will result in
213+
:exc:`~asyncpg.exceptions.InterfaceError`.
153214

154215
To create a cursor usable outside of a transaction, use the
155216
``DECLARE ... CURSOR WITH HOLD`` SQL statement directly.

0 commit comments

Comments
 (0)