summaryrefslogtreecommitdiffstats
path: root/docs/api/cursors.rst
blob: 9c5b4781391da7c890409d750179bdaa29787d4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
.. currentmodule:: psycopg

Cursor classes
==============

The `Cursor` and `AsyncCursor` classes are the main objects to send commands
to a PostgreSQL database session. They are normally created by the
connection's `~Connection.cursor()` method.

Using the `!name` parameter on `!cursor()` will create a `ServerCursor` or
`AsyncServerCursor`, which can be used to retrieve partial results from a
database.

A `Connection` can create several cursors, but only one at time can perform
operations, so they are not the best way to achieve parallelism (you may want
to operate with several connections instead). All the cursors on the same
connection have a view of the same session, so they can see each other's
uncommitted data.


The `!Cursor` class
-------------------

.. autoclass:: Cursor

    This class implements a `DBAPI-compliant interface`__. It is what the
    classic `Connection.cursor()` method returns. `AsyncConnection.cursor()`
    will create instead `AsyncCursor` objects, which have the same set of
    method but expose an `asyncio` interface and require `!async` and
    `!await` keywords to operate.

    .. __: dbapi-cursor_
    .. _dbapi-cursor: https://www.python.org/dev/peps/pep-0249/#cursor-objects


    Cursors behave as context managers: on block exit they are closed and
    further operation will not be possible. Closing a cursor will not
    terminate a transaction or a session though.

    .. attribute:: connection
        :type: Connection

        The connection this cursor is using.

    .. automethod:: close

        .. note::

            You can use::

                with conn.cursor() as cur:
                    ...

            to close the cursor automatically when the block is exited. See
            :ref:`usage`.

    .. autoattribute:: closed

    .. rubric:: Methods to send commands

    .. automethod:: execute

        :param query: The query to execute.
        :type query: `!str`, `!bytes`, `sql.SQL`, or `sql.Composed`
        :param params: The parameters to pass to the query, if any.
        :type params: Sequence or Mapping
        :param prepare: Force (`!True`) or disallow (`!False`) preparation of
            the query. By default (`!None`) prepare automatically. See
            :ref:`prepared-statements`.
        :param binary: Specify whether the server should return data in binary
            format (`!True`) or in text format (`!False`). By default
            (`!None`) return data as requested by the cursor's `~Cursor.format`.

        Return the cursor itself, so that it will be possible to chain a fetch
        operation after the call.

        See :ref:`query-parameters` for all the details about executing
        queries.

        .. versionchanged:: 3.1

            The `query` argument must be a `~typing.StringLiteral`. If you
            need to compose a query dynamically, please use `sql.SQL` and
            related objects.

            See :pep:`675` for details.

    .. automethod:: executemany

        :param query: The query to execute
        :type query: `!str`, `!bytes`, `sql.SQL`, or `sql.Composed`
        :param params_seq: The parameters to pass to the query
        :type params_seq: Sequence of Sequences or Mappings
        :param returning: If `!True`, fetch the results of the queries executed
        :type returning: `!bool`

        This is more efficient than performing separate queries, but in case of
        several :sql:`INSERT` (and with some SQL creativity for massive
        :sql:`UPDATE` too) you may consider using `copy()`.

        If the queries return data you want to read (e.g. when executing an
        :sql:`INSERT ... RETURNING` or a :sql:`SELECT` with a side-effect),
        you can specify `!returning=True`; the results will be available in
        the cursor's state and can be read using `fetchone()` and similar
        methods. Each input parameter will produce a separate result set: use
        `nextset()` to read the results of the queries after the first one.

        See :ref:`query-parameters` for all the details about executing
        queries.

        .. versionchanged:: 3.1

            - Added `!returning` parameter to receive query results.
            - Performance optimised by making use of the pipeline mode, when
              using libpq 14 or newer.

    .. automethod:: copy

        :param statement: The copy operation to execute
        :type statement: `!str`, `!bytes`, `sql.SQL`, or `sql.Composed`
        :param params: The parameters to pass to the statement, if any.
        :type params: Sequence or Mapping

        .. note::

            The method must be called with::

                with cursor.copy() as copy:
                    ...

        See :ref:`copy` for information about :sql:`COPY`.

        .. versionchanged:: 3.1
            Added parameters support.

    .. automethod:: stream

        This command is similar to execute + iter; however it supports endless
        data streams. The feature is not available in PostgreSQL, but some
        implementations exist: Materialize `TAIL`__ and CockroachDB
        `CHANGEFEED`__ for instance.

        The feature, and the API supporting it, are still experimental.
        Beware... 👀

        .. __: https://materialize.com/docs/sql/tail/#main
        .. __: https://www.cockroachlabs.com/docs/stable/changefeed-for.html

        The parameters are the same of `execute()`.

        .. warning::

            Failing to consume the iterator entirely will result in a
            connection left in `~psycopg.ConnectionInfo.transaction_status`
            `~pq.TransactionStatus.ACTIVE` state: this connection will refuse
            to receive further commands (with a message such as *another
            command is already in progress*).

            If there is a chance that the generator is not consumed entirely,
            in order to restore the connection to a working state you can call
            `~generator.close` on the generator object returned by `!stream()`. The
            `contextlib.closing` function might be particularly useful to make
            sure that `!close()` is called:

            .. code::

                with closing(cur.stream("select generate_series(1, 10000)")) as gen:
                    for rec in gen:
                        something(rec)  # might fail

            Without calling `!close()`, in case of error, the connection will
            be `!ACTIVE` and unusable. If `!close()` is called, the connection
            might be `!INTRANS` or `!INERROR`, depending on whether the server
            managed to send the entire resultset to the client. An autocommit
            connection will be `!IDLE` instead.


    .. attribute:: format

        The format of the data returned by the queries. It can be selected
        initially e.g. specifying `Connection.cursor`\ `!(binary=True)` and
        changed during the cursor's lifetime. It is also possible  to override
        the value for single queries, e.g. specifying `execute`\
        `!(binary=True)`.

        :type: `pq.Format`
        :default: `~pq.Format.TEXT`

        .. seealso:: :ref:`binary-data`


    .. rubric:: Methods to retrieve results

    Fetch methods are only available if the last operation produced results,
    e.g. a :sql:`SELECT` or a command with :sql:`RETURNING`. They will raise
    an exception if used with operations that don't return result, such as an
    :sql:`INSERT` with no :sql:`RETURNING` or an :sql:`ALTER TABLE`.

    .. note::

        Cursors are iterable objects, so just using the::

            for record in cursor:
                ...

        syntax will iterate on the records in the current recordset.

    .. autoattribute:: row_factory

        The property affects the objects returned by the `fetchone()`,
        `fetchmany()`, `fetchall()` methods. The default
        (`~psycopg.rows.tuple_row`) returns a tuple for each record fetched.

        See :ref:`row-factories` for details.

    .. automethod:: fetchone
    .. automethod:: fetchmany
    .. automethod:: fetchall
    .. automethod:: nextset
    .. automethod:: scroll

    .. attribute:: pgresult
        :type: Optional[psycopg.pq.PGresult]

        The result returned by the last query and currently exposed by the
        cursor, if available, else `!None`.

        It can be used to obtain low level info about the last query result
        and to access to features not currently wrapped by Psycopg.


    .. rubric:: Information about the data

    .. autoattribute:: description

    .. autoattribute:: statusmessage

        This is the status tag you typically see in :program:`psql` after
        a successful command, such as ``CREATE TABLE`` or ``UPDATE 42``.

    .. autoattribute:: rowcount
    .. autoattribute:: rownumber

    .. attribute:: _query

        An helper object used to convert queries and parameters before sending
        them to PostgreSQL.

        .. note::
            This attribute is exposed because it might be helpful to debug
            problems when the communication between Python and PostgreSQL
            doesn't work as expected. For this reason, the attribute is
            available when a query fails too.

            .. warning::
                You shouldn't consider it part of the public interface of the
                object: it might change without warnings.

                Except this warning, I guess.

            If you would like to build reliable features using this object,
            please get in touch so we can try and design an useful interface
            for it.

        Among the properties currently exposed by this object:

        - `!query` (`!bytes`): the query effectively sent to PostgreSQL. It
          will have Python placeholders (``%s``\-style) replaced with
          PostgreSQL ones (``$1``, ``$2``\-style).

        - `!params` (sequence of `!bytes`): the parameters passed to
          PostgreSQL, adapted to the database format.

        - `!types` (sequence of `!int`): the OID of the parameters passed to
          PostgreSQL.

        - `!formats` (sequence of `pq.Format`): whether the parameter format
          is text or binary.


The `!ClientCursor` class
-------------------------

.. seealso:: See :ref:`client-side-binding-cursors` for details.

.. autoclass:: ClientCursor

    This `Cursor` subclass has exactly the same interface of its parent class,
    but, instead of sending query and parameters separately to the server, it
    merges them on the client and sends them as a non-parametric query on the
    server. This allows, for instance, to execute parametrized data definition
    statements and other :ref:`problematic queries <server-side-binding>`.

    .. versionadded:: 3.1

    .. automethod:: mogrify

        :param query: The query to execute.
        :type query: `!str`, `!bytes`, `sql.SQL`, or `sql.Composed`
        :param params: The parameters to pass to the query, if any.
        :type params: Sequence or Mapping


The `!ServerCursor` class
--------------------------

.. seealso:: See :ref:`server-side-cursors` for details.

.. autoclass:: ServerCursor

    This class also implements a `DBAPI-compliant interface`__. It is created
    by `Connection.cursor()` specifying the `!name` parameter. Using this
    object results in the creation of an equivalent PostgreSQL cursor in the
    server. DBAPI-extension methods (such as `~Cursor.copy()` or
    `~Cursor.stream()`) are not implemented on this object: use a normal
    `Cursor` instead.

    .. __: dbapi-cursor_

    Most attribute and methods behave exactly like in `Cursor`, here are
    documented the differences:

    .. autoattribute:: name
    .. autoattribute:: scrollable

       .. seealso:: The PostgreSQL DECLARE_ statement documentation
          for the description of :sql:`[NO] SCROLL`.

    .. autoattribute:: withhold

       .. seealso:: The PostgreSQL DECLARE_ statement documentation
          for the description of :sql:`{WITH|WITHOUT} HOLD`.

    .. _DECLARE: https://www.postgresql.org/docs/current/sql-declare.html


    .. automethod:: close

        .. warning:: Closing a server-side cursor is more important than
            closing a client-side one because it also releases the resources
            on the server, which otherwise might remain allocated until the
            end of the session (memory, locks). Using the pattern::

                with conn.cursor():
                    ...

            is especially useful so that the cursor is closed at the end of
            the block.

    .. automethod:: execute

        :param query: The query to execute.
        :type query: `!str`, `!bytes`, `sql.SQL`, or `sql.Composed`
        :param params: The parameters to pass to the query, if any.
        :type params: Sequence or Mapping
        :param binary: Specify whether the server should return data in binary
            format (`!True`) or in text format (`!False`). By default
            (`!None`) return data as requested by the cursor's `~Cursor.format`.

        Create a server cursor with given `!name` and the `!query` in argument.

        If using :sql:`DECLARE` is not appropriate (for instance because the
        cursor is returned by calling a stored procedure) you can avoid to use
        `!execute()`, crete the cursor in other ways, and use directly the
        `!fetch*()` methods instead. See :ref:`cursor-steal` for an example.

        Using `!execute()` more than once will close the previous cursor and
        open a new one with the same name.

    .. automethod:: executemany
    .. automethod:: fetchone
    .. automethod:: fetchmany
    .. automethod:: fetchall

        These methods use the FETCH_ SQL statement to retrieve some of the
        records from the cursor's current position.

        .. _FETCH: https://www.postgresql.org/docs/current/sql-fetch.html

        .. note::

            You can also iterate on the cursor to read its result one at
            time with::

                for record in cur:
                    ...

            In this case, the records are not fetched one at time from the
            server but they are retrieved in batches of `itersize` to reduce
            the number of server roundtrips.

    .. autoattribute:: itersize

        Number of records to fetch at time when iterating on the cursor. The
        default is 100.

    .. automethod:: scroll

        This method uses the MOVE_ SQL statement to move the current position
        in the server-side cursor, which will affect following `!fetch*()`
        operations. If you need to scroll backwards you should probably
        call `~Connection.cursor()` using `scrollable=True`.

        Note that PostgreSQL doesn't provide a reliable way to report when a
        cursor moves out of bound, so the method might not raise `!IndexError`
        when it happens, but it might rather stop at the cursor boundary.

        .. _MOVE: https://www.postgresql.org/docs/current/sql-fetch.html


The `!AsyncCursor` class
------------------------

.. autoclass:: AsyncCursor

    This class implements a DBAPI-inspired interface, with all the blocking
    methods implemented as coroutines. Unless specified otherwise,
    non-blocking methods are shared with the `Cursor` class.

    The following methods have the same behaviour of the matching `!Cursor`
    methods, but should be called using the `await` keyword.

    .. attribute:: connection
        :type: AsyncConnection

    .. automethod:: close

        .. note::

            You can use::

                async with conn.cursor():
                    ...

            to close the cursor automatically when the block is exited.

    .. automethod:: execute
    .. automethod:: executemany
    .. automethod:: copy

        .. note::

            The method must be called with::

                async with cursor.copy() as copy:
                    ...

    .. automethod:: stream

        .. note::

            The method must be called with::

                async for record in cursor.stream(query):
                    ...

    .. automethod:: fetchone
    .. automethod:: fetchmany
    .. automethod:: fetchall
    .. automethod:: scroll

    .. note::

        You can also use::

            async for record in cursor:
                ...

        to iterate on the async cursor results.


The `!AsyncClientCursor` class
------------------------------

.. autoclass:: AsyncClientCursor

    This class is the `!async` equivalent of the `ClientCursor`. The
    difference are the same shown in `AsyncCursor`.

    .. versionadded:: 3.1



The `!AsyncServerCursor` class
------------------------------

.. autoclass:: AsyncServerCursor

    This class implements a DBAPI-inspired interface as the `AsyncCursor`
    does, but wraps a server-side cursor like the `ServerCursor` class. It is
    created by `AsyncConnection.cursor()` specifying the `!name` parameter.

    The following are the methods exposing a different (async) interface from
    the `ServerCursor` counterpart, but sharing the same semantics.

    .. automethod:: close

        .. note::
            You can close the cursor automatically using::

                async with conn.cursor("name") as cursor:
                    ...

    .. automethod:: execute
    .. automethod:: executemany
    .. automethod:: fetchone
    .. automethod:: fetchmany
    .. automethod:: fetchall

        .. note::

            You can also iterate on the cursor using::

                async for record in cur:
                    ...

    .. automethod:: scroll