Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
base.py5379 linesDownload Raw Back to postgresql
1# dialects/postgresql/base.py
2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7# mypy: ignore-errors
8
9r"""
10.. dialect:: postgresql
11    :name: PostgreSQL
12    :normal_support: 9.6+
13    :best_effort: 9+
14
15.. _postgresql_sequences:
16
17Sequences/SERIAL/IDENTITY
18-------------------------
19
20PostgreSQL supports sequences, and SQLAlchemy uses these as the default means
21of creating new primary key values for integer-based primary key columns. When
22creating tables, SQLAlchemy will issue the ``SERIAL`` datatype for
23integer-based primary key columns, which generates a sequence and server side
24default corresponding to the column.
25
26To specify a specific named sequence to be used for primary key generation,
27use the :func:`~sqlalchemy.schema.Sequence` construct::
28
29    Table(
30        "sometable",
31        metadata,
32        Column(
33            "id", Integer, Sequence("some_id_seq", start=1), primary_key=True
34        ),
35    )
36
37When SQLAlchemy issues a single INSERT statement, to fulfill the contract of
38having the "last insert identifier" available, a RETURNING clause is added to
39the INSERT statement which specifies the primary key columns should be
40returned after the statement completes. The RETURNING functionality only takes
41place if PostgreSQL 8.2 or later is in use. As a fallback approach, the
42sequence, whether specified explicitly or implicitly via ``SERIAL``, is
43executed independently beforehand, the returned value to be used in the
44subsequent insert. Note that when an
45:func:`~sqlalchemy.sql.expression.insert()` construct is executed using
46"executemany" semantics, the "last inserted identifier" functionality does not
47apply; no RETURNING clause is emitted nor is the sequence pre-executed in this
48case.
49
50
51PostgreSQL 10 and above IDENTITY columns
52^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
53
54PostgreSQL 10 and above have a new IDENTITY feature that supersedes the use
55of SERIAL. The :class:`_schema.Identity` construct in a
56:class:`_schema.Column` can be used to control its behavior::
57
58    from sqlalchemy import Table, Column, MetaData, Integer, Computed
59
60    metadata = MetaData()
61
62    data = Table(
63        "data",
64        metadata,
65        Column(
66            "id", Integer, Identity(start=42, cycle=True), primary_key=True
67        ),
68        Column("data", String),
69    )
70
71The CREATE TABLE for the above :class:`_schema.Table` object would be:
72
73.. sourcecode:: sql
74
75    CREATE TABLE data (
76        id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 42 CYCLE),
77        data VARCHAR,
78        PRIMARY KEY (id)
79    )
80
81.. versionchanged::  1.4   Added :class:`_schema.Identity` construct
82   in a :class:`_schema.Column` to specify the option of an autoincrementing
83   column.
84
85.. note::
86
87   Previous versions of SQLAlchemy did not have built-in support for rendering
88   of IDENTITY, and could use the following compilation hook to replace
89   occurrences of SERIAL with IDENTITY::
90
91       from sqlalchemy.schema import CreateColumn
92       from sqlalchemy.ext.compiler import compiles
93
94
95       @compiles(CreateColumn, "postgresql")
96       def use_identity(element, compiler, **kw):
97           text = compiler.visit_create_column(element, **kw)
98           text = text.replace("SERIAL", "INT GENERATED BY DEFAULT AS IDENTITY")
99           return text
100
101   Using the above, a table such as::
102
103       t = Table(
104           "t", m, Column("id", Integer, primary_key=True), Column("data", String)
105       )
106
107   Will generate on the backing database as:
108
109   .. sourcecode:: sql
110
111       CREATE TABLE t (
112           id INT GENERATED BY DEFAULT AS IDENTITY,
113           data VARCHAR,
114           PRIMARY KEY (id)
115       )
116
117.. _postgresql_ss_cursors:
118
119Server Side Cursors
120-------------------
121
122Server-side cursor support is available for the psycopg2, asyncpg
123dialects and may also be available in others.
124
125Server side cursors are enabled on a per-statement basis by using the
126:paramref:`.Connection.execution_options.stream_results` connection execution
127option::
128
129    with engine.connect() as conn:
130        result = conn.execution_options(stream_results=True).execute(
131            text("select * from table")
132        )
133
134Note that some kinds of SQL statements may not be supported with
135server side cursors; generally, only SQL statements that return rows should be
136used with this option.
137
138.. deprecated:: 1.4  The dialect-level server_side_cursors flag is deprecated
139   and will be removed in a future release.  Please use the
140   :paramref:`_engine.Connection.stream_results` execution option for
141   unbuffered cursor support.
142
143.. seealso::
144
145    :ref:`engine_stream_results`
146
147.. _postgresql_isolation_level:
148
149Transaction Isolation Level
150---------------------------
151
152Most SQLAlchemy dialects support setting of transaction isolation level
153using the :paramref:`_sa.create_engine.isolation_level` parameter
154at the :func:`_sa.create_engine` level, and at the :class:`_engine.Connection`
155level via the :paramref:`.Connection.execution_options.isolation_level`
156parameter.
157
158For PostgreSQL dialects, this feature works either by making use of the
159DBAPI-specific features, such as psycopg2's isolation level flags which will
160embed the isolation level setting inline with the ``"BEGIN"`` statement, or for
161DBAPIs with no direct support by emitting ``SET SESSION CHARACTERISTICS AS
162TRANSACTION ISOLATION LEVEL <level>`` ahead of the ``"BEGIN"`` statement
163emitted by the DBAPI.   For the special AUTOCOMMIT isolation level,
164DBAPI-specific techniques are used which is typically an ``.autocommit``
165flag on the DBAPI connection object.
166
167To set isolation level using :func:`_sa.create_engine`::
168
169    engine = create_engine(
170        "postgresql+pg8000://scott:tiger@localhost/test",
171        isolation_level="REPEATABLE READ",
172    )
173
174To set using per-connection execution options::
175
176    with engine.connect() as conn:
177        conn = conn.execution_options(isolation_level="REPEATABLE READ")
178        with conn.begin():
179            ...  # work with transaction
180
181There are also more options for isolation level configurations, such as
182"sub-engine" objects linked to a main :class:`_engine.Engine` which each apply
183different isolation level settings.  See the discussion at
184:ref:`dbapi_autocommit` for background.
185
186Valid values for ``isolation_level`` on most PostgreSQL dialects include:
187
188* ``READ COMMITTED``
189* ``READ UNCOMMITTED``
190* ``REPEATABLE READ``
191* ``SERIALIZABLE``
192* ``AUTOCOMMIT``
193
194.. seealso::
195
196    :ref:`dbapi_autocommit`
197
198    :ref:`postgresql_readonly_deferrable`
199
200    :ref:`psycopg2_isolation_level`
201
202    :ref:`pg8000_isolation_level`
203
204.. _postgresql_readonly_deferrable:
205
206Setting READ ONLY / DEFERRABLE
207------------------------------
208
209Most PostgreSQL dialects support setting the "READ ONLY" and "DEFERRABLE"
210characteristics of the transaction, which is in addition to the isolation level
211setting. These two attributes can be established either in conjunction with or
212independently of the isolation level by passing the ``postgresql_readonly`` and
213``postgresql_deferrable`` flags with
214:meth:`_engine.Connection.execution_options`.  The example below illustrates
215passing the ``"SERIALIZABLE"`` isolation level at the same time as setting
216"READ ONLY" and "DEFERRABLE"::
217
218    with engine.connect() as conn:
219        conn = conn.execution_options(
220            isolation_level="SERIALIZABLE",
221            postgresql_readonly=True,
222            postgresql_deferrable=True,
223        )
224        with conn.begin():
225            ...  # work with transaction
226
227Note that some DBAPIs such as asyncpg only support "readonly" with
228SERIALIZABLE isolation.
229
230.. versionadded:: 1.4 added support for the ``postgresql_readonly``
231   and ``postgresql_deferrable`` execution options.
232
233.. _postgresql_reset_on_return:
234
235Temporary Table / Resource Reset for Connection Pooling
236-------------------------------------------------------
237
238The :class:`.QueuePool` connection pool implementation used
239by the SQLAlchemy :class:`.Engine` object includes
240:ref:`reset on return <pool_reset_on_return>` behavior that will invoke
241the DBAPI ``.rollback()`` method when connections are returned to the pool.
242While this rollback will clear out the immediate state used by the previous
243transaction, it does not cover a wider range of session-level state, including
244temporary tables as well as other server state such as prepared statement
245handles and statement caches.   The PostgreSQL database includes a variety
246of commands which may be used to reset this state, including
247``DISCARD``, ``RESET``, ``DEALLOCATE``, and ``UNLISTEN``.
248
249
250To install
251one or more of these commands as the means of performing reset-on-return,
252the :meth:`.PoolEvents.reset` event hook may be used, as demonstrated
253in the example below. The implementation
254will end transactions in progress as well as discard temporary tables
255using the ``CLOSE``, ``RESET`` and ``DISCARD`` commands; see the PostgreSQL
256documentation for background on what each of these statements do.
257
258The :paramref:`_sa.create_engine.pool_reset_on_return` parameter
259is set to ``None`` so that the custom scheme can replace the default behavior
260completely.   The custom hook implementation calls ``.rollback()`` in any case,
261as it's usually important that the DBAPI's own tracking of commit/rollback
262will remain consistent with the state of the transaction::
263
264
265    from sqlalchemy import create_engine
266    from sqlalchemy import event
267
268    postgresql_engine = create_engine(
269        "postgresql+psycopg2://scott:tiger@hostname/dbname",
270        # disable default reset-on-return scheme
271        pool_reset_on_return=None,
272    )
273
274
275    @event.listens_for(postgresql_engine, "reset")
276    def _reset_postgresql(dbapi_connection, connection_record, reset_state):
277        if not reset_state.terminate_only:
278            dbapi_connection.execute("CLOSE ALL")
279            dbapi_connection.execute("RESET ALL")
280            dbapi_connection.execute("DISCARD TEMP")
281
282        # so that the DBAPI itself knows that the connection has been
283        # reset
284        dbapi_connection.rollback()
285
286.. versionchanged:: 2.0.0b3  Added additional state arguments to
287   the :meth:`.PoolEvents.reset` event and additionally ensured the event
288   is invoked for all "reset" occurrences, so that it's appropriate
289   as a place for custom "reset" handlers.   Previous schemes which
290   use the :meth:`.PoolEvents.checkin` handler remain usable as well.
291
292.. seealso::
293
294    :ref:`pool_reset_on_return` - in the :ref:`pooling_toplevel` documentation
295
296.. _postgresql_alternate_search_path:
297
298Setting Alternate Search Paths on Connect
299------------------------------------------
300
301The PostgreSQL ``search_path`` variable refers to the list of schema names
302that will be implicitly referenced when a particular table or other
303object is referenced in a SQL statement.  As detailed in the next section
304:ref:`postgresql_schema_reflection`, SQLAlchemy is generally organized around
305the concept of keeping this variable at its default value of ``public``,
306however, in order to have it set to any arbitrary name or names when connections
307are used automatically, the "SET SESSION search_path" command may be invoked
308for all connections in a pool using the following event handler, as discussed
309at :ref:`schema_set_default_connections`::
310
311    from sqlalchemy import event
312    from sqlalchemy import create_engine
313
314    engine = create_engine("postgresql+psycopg2://scott:tiger@host/dbname")
315
316
317    @event.listens_for(engine, "connect", insert=True)
318    def set_search_path(dbapi_connection, connection_record):
319        existing_autocommit = dbapi_connection.autocommit
320        dbapi_connection.autocommit = True
321        cursor = dbapi_connection.cursor()
322        cursor.execute("SET SESSION search_path='%s'" % schema_name)
323        cursor.close()
324        dbapi_connection.autocommit = existing_autocommit
325
326The reason the recipe is complicated by use of the ``.autocommit`` DBAPI
327attribute is so that when the ``SET SESSION search_path`` directive is invoked,
328it is invoked outside of the scope of any transaction and therefore will not
329be reverted when the DBAPI connection has a rollback.
330
331.. seealso::
332
333  :ref:`schema_set_default_connections` - in the :ref:`metadata_toplevel` documentation
334
335.. _postgresql_schema_reflection:
336
337Remote-Schema Table Introspection and PostgreSQL search_path
338------------------------------------------------------------
339
340.. admonition:: Section Best Practices Summarized
341
342    keep the ``search_path`` variable set to its default of ``public``, without
343    any other schema names. Ensure the username used to connect **does not**
344    match remote schemas, or ensure the ``"$user"`` token is **removed** from
345    ``search_path``.  For other schema names, name these explicitly
346    within :class:`_schema.Table` definitions. Alternatively, the
347    ``postgresql_ignore_search_path`` option will cause all reflected
348    :class:`_schema.Table` objects to have a :attr:`_schema.Table.schema`
349    attribute set up.
350
351The PostgreSQL dialect can reflect tables from any schema, as outlined in
352:ref:`metadata_reflection_schemas`.
353
354In all cases, the first thing SQLAlchemy does when reflecting tables is
355to **determine the default schema for the current database connection**.
356It does this using the PostgreSQL ``current_schema()``
357function, illustated below using a PostgreSQL client session (i.e. using
358the ``psql`` tool):
359
360.. sourcecode:: sql
361
362    test=> select current_schema();
363    current_schema
364    ----------------
365    public
366    (1 row)
367
368Above we see that on a plain install of PostgreSQL, the default schema name
369is the name ``public``.
370
371However, if your database username **matches the name of a schema**, PostgreSQL's
372default is to then **use that name as the default schema**.  Below, we log in
373using the username ``scott``.  When we create a schema named ``scott``, **it
374implicitly changes the default schema**:
375
376.. sourcecode:: sql
377
378    test=> select current_schema();
379    current_schema
380    ----------------
381    public
382    (1 row)
383
384    test=> create schema scott;
385    CREATE SCHEMA
386    test=> select current_schema();
387    current_schema
388    ----------------
389    scott
390    (1 row)
391
392The behavior of ``current_schema()`` is derived from the
393`PostgreSQL search path
394<https://www.postgresql.org/docs/current/static/ddl-schemas.html#DDL-SCHEMAS-PATH>`_
395variable ``search_path``, which in modern PostgreSQL versions defaults to this:
396
397.. sourcecode:: sql
398
399    test=> show search_path;
400    search_path
401    -----------------
402    "$user", public
403    (1 row)
404
405Where above, the ``"$user"`` variable will inject the current username as the
406default schema, if one exists.   Otherwise, ``public`` is used.
407
408When a :class:`_schema.Table` object is reflected, if it is present in the
409schema indicated by the ``current_schema()`` function, **the schema name assigned
410to the ".schema" attribute of the Table is the Python "None" value**.  Otherwise, the
411".schema" attribute will be assigned the string name of that schema.
412
413With regards to tables which these :class:`_schema.Table`
414objects refer to via foreign key constraint, a decision must be made as to how
415the ``.schema`` is represented in those remote tables, in the case where that
416remote schema name is also a member of the current ``search_path``.
417
418By default, the PostgreSQL dialect mimics the behavior encouraged by
419PostgreSQL's own ``pg_get_constraintdef()`` builtin procedure.  This function
420returns a sample definition for a particular foreign key constraint,
421omitting the referenced schema name from that definition when the name is
422also in the PostgreSQL schema search path.  The interaction below
423illustrates this behavior:
424
425.. sourcecode:: sql
426
427    test=> CREATE TABLE test_schema.referred(id INTEGER PRIMARY KEY);
428    CREATE TABLE
429    test=> CREATE TABLE referring(
430    test(>         id INTEGER PRIMARY KEY,
431    test(>         referred_id INTEGER REFERENCES test_schema.referred(id));
432    CREATE TABLE
433    test=> SET search_path TO public, test_schema;
434    test=> SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM
435    test-> pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n
436    test-> ON n.oid = c.relnamespace
437    test-> JOIN pg_catalog.pg_constraint r  ON c.oid = r.conrelid
438    test-> WHERE c.relname='referring' AND r.contype = 'f'
439    test-> ;
440                   pg_get_constraintdef
441    ---------------------------------------------------
442     FOREIGN KEY (referred_id) REFERENCES referred(id)
443    (1 row)
444
445Above, we created a table ``referred`` as a member of the remote schema
446``test_schema``, however when we added ``test_schema`` to the
447PG ``search_path`` and then asked ``pg_get_constraintdef()`` for the
448``FOREIGN KEY`` syntax, ``test_schema`` was not included in the output of
449the function.
450
451On the other hand, if we set the search path back to the typical default
452of ``public``:
453
454.. sourcecode:: sql
455
456    test=> SET search_path TO public;
457    SET
458
459The same query against ``pg_get_constraintdef()`` now returns the fully
460schema-qualified name for us:
461
462.. sourcecode:: sql
463
464    test=> SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM
465    test-> pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n
466    test-> ON n.oid = c.relnamespace
467    test-> JOIN pg_catalog.pg_constraint r  ON c.oid = r.conrelid
468    test-> WHERE c.relname='referring' AND r.contype = 'f';
469                         pg_get_constraintdef
470    ---------------------------------------------------------------
471     FOREIGN KEY (referred_id) REFERENCES test_schema.referred(id)
472    (1 row)
473
474SQLAlchemy will by default use the return value of ``pg_get_constraintdef()``
475in order to determine the remote schema name.  That is, if our ``search_path``
476were set to include ``test_schema``, and we invoked a table
477reflection process as follows::
478
479    >>> from sqlalchemy import Table, MetaData, create_engine, text
480    >>> engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test")
481    >>> with engine.connect() as conn:
482    ...     conn.execute(text("SET search_path TO test_schema, public"))
483    ...     metadata_obj = MetaData()
484    ...     referring = Table("referring", metadata_obj, autoload_with=conn)
485    <sqlalchemy.engine.result.CursorResult object at 0x101612ed0>
486
487The above process would deliver to the :attr:`_schema.MetaData.tables`
488collection
489``referred`` table named **without** the schema::
490
491    >>> metadata_obj.tables["referred"].schema is None
492    True
493
494To alter the behavior of reflection such that the referred schema is
495maintained regardless of the ``search_path`` setting, use the
496``postgresql_ignore_search_path`` option, which can be specified as a
497dialect-specific argument to both :class:`_schema.Table` as well as
498:meth:`_schema.MetaData.reflect`::
499
500    >>> with engine.connect() as conn:
501    ...     conn.execute(text("SET search_path TO test_schema, public"))
502    ...     metadata_obj = MetaData()
503    ...     referring = Table(
504    ...         "referring",
505    ...         metadata_obj,
506    ...         autoload_with=conn,
507    ...         postgresql_ignore_search_path=True,
508    ...     )
509    <sqlalchemy.engine.result.CursorResult object at 0x1016126d0>
510
511We will now have ``test_schema.referred`` stored as schema-qualified::
512
513    >>> metadata_obj.tables["test_schema.referred"].schema
514    'test_schema'
515
516.. sidebar:: Best Practices for PostgreSQL Schema reflection
517
518    The description of PostgreSQL schema reflection behavior is complex, and
519    is the product of many years of dealing with widely varied use cases and
520    user preferences. But in fact, there's no need to understand any of it if
521    you just stick to the simplest use pattern: leave the ``search_path`` set
522    to its default of ``public`` only, never refer to the name ``public`` as
523    an explicit schema name otherwise, and refer to all other schema names
524    explicitly when building up a :class:`_schema.Table` object.  The options
525    described here are only for those users who can't, or prefer not to, stay
526    within these guidelines.
527
528.. seealso::
529
530    :ref:`reflection_schema_qualified_interaction` - discussion of the issue
531    from a backend-agnostic perspective
532
533    `The Schema Search Path
534    <https://www.postgresql.org/docs/current/static/ddl-schemas.html#DDL-SCHEMAS-PATH>`_
535    - on the PostgreSQL website.
536
537INSERT/UPDATE...RETURNING
538-------------------------
539
540The dialect supports PG 8.2's ``INSERT..RETURNING``, ``UPDATE..RETURNING`` and
541``DELETE..RETURNING`` syntaxes.   ``INSERT..RETURNING`` is used by default
542for single-row INSERT statements in order to fetch newly generated
543primary key identifiers.   To specify an explicit ``RETURNING`` clause,
544use the :meth:`._UpdateBase.returning` method on a per-statement basis::
545
546    # INSERT..RETURNING
547    result = (
548        table.insert().returning(table.c.col1, table.c.col2).values(name="foo")
549    )
550    print(result.fetchall())
551
552    # UPDATE..RETURNING
553    result = (
554        table.update()
555        .returning(table.c.col1, table.c.col2)
556        .where(table.c.name == "foo")
557        .values(name="bar")
558    )
559    print(result.fetchall())
560
561    # DELETE..RETURNING
562    result = (
563        table.delete()
564        .returning(table.c.col1, table.c.col2)
565        .where(table.c.name == "foo")
566    )
567    print(result.fetchall())
568
569.. _postgresql_insert_on_conflict:
570
571INSERT...ON CONFLICT (Upsert)
572------------------------------
573
574Starting with version 9.5, PostgreSQL allows "upserts" (update or insert) of
575rows into a table via the ``ON CONFLICT`` clause of the ``INSERT`` statement. A
576candidate row will only be inserted if that row does not violate any unique
577constraints.  In the case of a unique constraint violation, a secondary action
578can occur which can be either "DO UPDATE", indicating that the data in the
579target row should be updated, or "DO NOTHING", which indicates to silently skip
580this row.
581
582Conflicts are determined using existing unique constraints and indexes.  These
583constraints may be identified either using their name as stated in DDL,
584or they may be inferred by stating the columns and conditions that comprise
585the indexes.
586
587SQLAlchemy provides ``ON CONFLICT`` support via the PostgreSQL-specific
588:func:`_postgresql.insert()` function, which provides
589the generative methods :meth:`_postgresql.Insert.on_conflict_do_update`
590and :meth:`~.postgresql.Insert.on_conflict_do_nothing`:
591
592.. sourcecode:: pycon+sql
593
594    >>> from sqlalchemy.dialects.postgresql import insert
595    >>> insert_stmt = insert(my_table).values(
596    ...     id="some_existing_id", data="inserted value"
597    ... )
598    >>> do_nothing_stmt = insert_stmt.on_conflict_do_nothing(index_elements=["id"])
599    >>> print(do_nothing_stmt)
600    {printsql}INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s)
601    ON CONFLICT (id) DO NOTHING
602    {stop}
603
604    >>> do_update_stmt = insert_stmt.on_conflict_do_update(
605    ...     constraint="pk_my_table", set_=dict(data="updated value")
606    ... )
607    >>> print(do_update_stmt)
608    {printsql}INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s)
609    ON CONFLICT ON CONSTRAINT pk_my_table DO UPDATE SET data = %(param_1)s
610
611.. seealso::
612
613    `INSERT .. ON CONFLICT
614    <https://www.postgresql.org/docs/current/static/sql-insert.html#SQL-ON-CONFLICT>`_
615    - in the PostgreSQL documentation.
616
617Specifying the Target
618^^^^^^^^^^^^^^^^^^^^^
619
620Both methods supply the "target" of the conflict using either the
621named constraint or by column inference:
622
623* The :paramref:`_postgresql.Insert.on_conflict_do_update.index_elements` argument
624  specifies a sequence containing string column names, :class:`_schema.Column`
625  objects, and/or SQL expression elements, which would identify a unique
626  index:
627
628  .. sourcecode:: pycon+sql
629
630    >>> do_update_stmt = insert_stmt.on_conflict_do_update(
631    ...     index_elements=["id"], set_=dict(data="updated value")
632    ... )
633    >>> print(do_update_stmt)
634    {printsql}INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s)
635    ON CONFLICT (id) DO UPDATE SET data = %(param_1)s
636    {stop}
637
638    >>> do_update_stmt = insert_stmt.on_conflict_do_update(
639    ...     index_elements=[my_table.c.id], set_=dict(data="updated value")
640    ... )
641    >>> print(do_update_stmt)
642    {printsql}INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s)
643    ON CONFLICT (id) DO UPDATE SET data = %(param_1)s
644
645* When using :paramref:`_postgresql.Insert.on_conflict_do_update.index_elements` to
646  infer an index, a partial index can be inferred by also specifying the
647  use the :paramref:`_postgresql.Insert.on_conflict_do_update.index_where` parameter:
648
649  .. sourcecode:: pycon+sql
650
651    >>> stmt = insert(my_table).values(user_email="a@b.com", data="inserted data")
652    >>> stmt = stmt.on_conflict_do_update(
653    ...     index_elements=[my_table.c.user_email],
654    ...     index_where=my_table.c.user_email.like("%@gmail.com"),
655    ...     set_=dict(data=stmt.excluded.data),
656    ... )
657    >>> print(stmt)
658    {printsql}INSERT INTO my_table (data, user_email)
659    VALUES (%(data)s, %(user_email)s) ON CONFLICT (user_email)
660    WHERE user_email LIKE %(user_email_1)s DO UPDATE SET data = excluded.data
661
662* The :paramref:`_postgresql.Insert.on_conflict_do_update.constraint` argument is
663  used to specify an index directly rather than inferring it.  This can be
664  the name of a UNIQUE constraint, a PRIMARY KEY constraint, or an INDEX:
665
666  .. sourcecode:: pycon+sql
667
668    >>> do_update_stmt = insert_stmt.on_conflict_do_update(
669    ...     constraint="my_table_idx_1", set_=dict(data="updated value")
670    ... )
671    >>> print(do_update_stmt)
672    {printsql}INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s)
673    ON CONFLICT ON CONSTRAINT my_table_idx_1 DO UPDATE SET data = %(param_1)s
674    {stop}
675
676    >>> do_update_stmt = insert_stmt.on_conflict_do_update(
677    ...     constraint="my_table_pk", set_=dict(data="updated value")
678    ... )
679    >>> print(do_update_stmt)
680    {printsql}INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s)
681    ON CONFLICT ON CONSTRAINT my_table_pk DO UPDATE SET data = %(param_1)s
682    {stop}
683
684* The :paramref:`_postgresql.Insert.on_conflict_do_update.constraint` argument may
685  also refer to a SQLAlchemy construct representing a constraint,
686  e.g. :class:`.UniqueConstraint`, :class:`.PrimaryKeyConstraint`,
687  :class:`.Index`, or :class:`.ExcludeConstraint`.   In this use,
688  if the constraint has a name, it is used directly.  Otherwise, if the
689  constraint is unnamed, then inference will be used, where the expressions
690  and optional WHERE clause of the constraint will be spelled out in the
691  construct.  This use is especially convenient
692  to refer to the named or unnamed primary key of a :class:`_schema.Table`
693  using the
694  :attr:`_schema.Table.primary_key` attribute:
695
696  .. sourcecode:: pycon+sql
697
698    >>> do_update_stmt = insert_stmt.on_conflict_do_update(
699    ...     constraint=my_table.primary_key, set_=dict(data="updated value")
700    ... )
701    >>> print(do_update_stmt)
702    {printsql}INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s)
703    ON CONFLICT (id) DO UPDATE SET data = %(param_1)s
704
705The SET Clause
706^^^^^^^^^^^^^^^
707
708``ON CONFLICT...DO UPDATE`` is used to perform an update of the already
709existing row, using any combination of new values as well as values
710from the proposed insertion.   These values are specified using the
711:paramref:`_postgresql.Insert.on_conflict_do_update.set_` parameter.  This
712parameter accepts a dictionary which consists of direct values
713for UPDATE:
714
715.. sourcecode:: pycon+sql
716
717    >>> stmt = insert(my_table).values(id="some_id", data="inserted value")
718    >>> do_update_stmt = stmt.on_conflict_do_update(
719    ...     index_elements=["id"], set_=dict(data="updated value")
720    ... )
721    >>> print(do_update_stmt)
722    {printsql}INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s)
723    ON CONFLICT (id) DO UPDATE SET data = %(param_1)s
724
725.. warning::
726
727    The :meth:`_expression.Insert.on_conflict_do_update`
728    method does **not** take into
729    account Python-side default UPDATE values or generation functions, e.g.
730    those specified using :paramref:`_schema.Column.onupdate`.
731    These values will not be exercised for an ON CONFLICT style of UPDATE,
732    unless they are manually specified in the
733    :paramref:`_postgresql.Insert.on_conflict_do_update.set_` dictionary.
734
735Updating using the Excluded INSERT Values
736^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
737
738In order to refer to the proposed insertion row, the special alias
739:attr:`~.postgresql.Insert.excluded` is available as an attribute on
740the :class:`_postgresql.Insert` object; this object is a
741:class:`_expression.ColumnCollection`
742which alias contains all columns of the target
743table:
744
745.. sourcecode:: pycon+sql
746
747    >>> stmt = insert(my_table).values(
748    ...     id="some_id", data="inserted value", author="jlh"
749    ... )
750    >>> do_update_stmt = stmt.on_conflict_do_update(
751    ...     index_elements=["id"],
752    ...     set_=dict(data="updated value", author=stmt.excluded.author),
753    ... )
754    >>> print(do_update_stmt)
755    {printsql}INSERT INTO my_table (id, data, author)
756    VALUES (%(id)s, %(data)s, %(author)s)
757    ON CONFLICT (id) DO UPDATE SET data = %(param_1)s, author = excluded.author
758
759Additional WHERE Criteria
760^^^^^^^^^^^^^^^^^^^^^^^^^
761
762The :meth:`_expression.Insert.on_conflict_do_update` method also accepts
763a WHERE clause using the :paramref:`_postgresql.Insert.on_conflict_do_update.where`
764parameter, which will limit those rows which receive an UPDATE:
765
766.. sourcecode:: pycon+sql
767
768    >>> stmt = insert(my_table).values(
769    ...     id="some_id", data="inserted value", author="jlh"
770    ... )
771    >>> on_update_stmt = stmt.on_conflict_do_update(
772    ...     index_elements=["id"],
773    ...     set_=dict(data="updated value", author=stmt.excluded.author),
774    ...     where=(my_table.c.status == 2),
775    ... )
776    >>> print(on_update_stmt)
777    {printsql}INSERT INTO my_table (id, data, author)
778    VALUES (%(id)s, %(data)s, %(author)s)
779    ON CONFLICT (id) DO UPDATE SET data = %(param_1)s, author = excluded.author
780    WHERE my_table.status = %(status_1)s
781
782Skipping Rows with DO NOTHING
783^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
784
785``ON CONFLICT`` may be used to skip inserting a row entirely
786if any conflict with a unique or exclusion constraint occurs; below
787this is illustrated using the
788:meth:`~.postgresql.Insert.on_conflict_do_nothing` method:
789
790.. sourcecode:: pycon+sql
791
792    >>> stmt = insert(my_table).values(id="some_id", data="inserted value")
793    >>> stmt = stmt.on_conflict_do_nothing(index_elements=["id"])
794    >>> print(stmt)
795    {printsql}INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s)
796    ON CONFLICT (id) DO NOTHING
797
798If ``DO NOTHING`` is used without specifying any columns or constraint,
799it has the effect of skipping the INSERT for any unique or exclusion
800constraint violation which occurs:
801
802.. sourcecode:: pycon+sql
803
804    >>> stmt = insert(my_table).values(id="some_id", data="inserted value")
805    >>> stmt = stmt.on_conflict_do_nothing()
806    >>> print(stmt)
807    {printsql}INSERT INTO my_table (id, data) VALUES (%(id)s, %(data)s)
808    ON CONFLICT DO NOTHING
809
810.. _postgresql_match:
811
812Full Text Search
813----------------
814
815PostgreSQL's full text search system is available through the use of the
816:data:`.func` namespace, combined with the use of custom operators
817via the :meth:`.Operators.bool_op` method.    For simple cases with some
818degree of cross-backend compatibility, the :meth:`.Operators.match` operator
819may also be used.
820
821.. _postgresql_simple_match:
822
823Simple plain text matching with ``match()``
824^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
825
826The :meth:`.Operators.match` operator provides for cross-compatible simple
827text matching.   For the PostgreSQL backend, it's hardcoded to generate
828an expression using the ``@@`` operator in conjunction with the
829``plainto_tsquery()`` PostgreSQL function.
830
831On the PostgreSQL dialect, an expression like the following::
832
833    select(sometable.c.text.match("search string"))
834
835would emit to the database:
836
837.. sourcecode:: sql
838
839    SELECT text @@ plainto_tsquery('search string') FROM table
840
841Above, passing a plain string to :meth:`.Operators.match` will automatically
842make use of ``plainto_tsquery()`` to specify the type of tsquery.  This
843establishes basic database cross-compatibility for :meth:`.Operators.match`
844with other backends.
845
846.. versionchanged:: 2.0 The default tsquery generation function used by the
847   PostgreSQL dialect with :meth:`.Operators.match` is ``plainto_tsquery()``.
848
849   To render exactly what was rendered in 1.4, use the following form::
850
851        from sqlalchemy import func
852
853        select(sometable.c.text.bool_op("@@")(func.to_tsquery("search string")))
854
855   Which would emit:
856
857   .. sourcecode:: sql
858
859        SELECT text @@ to_tsquery('search string') FROM table
860
861Using PostgreSQL full text functions and operators directly
862^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
863
864Text search operations beyond the simple use of :meth:`.Operators.match`
865may make use of the :data:`.func` namespace to generate PostgreSQL full-text
866functions, in combination with :meth:`.Operators.bool_op` to generate
867any boolean operator.
868
869For example, the query::
870
871    select(func.to_tsquery("cat").bool_op("@>")(func.to_tsquery("cat & rat")))
872
873would generate:
874
875.. sourcecode:: sql
876
877    SELECT to_tsquery('cat') @> to_tsquery('cat & rat')
878
879
880The :class:`_postgresql.TSVECTOR` type can provide for explicit CAST::
881
882    from sqlalchemy.dialects.postgresql import TSVECTOR
883    from sqlalchemy import select, cast
884
885    select(cast("some text", TSVECTOR))
886
887produces a statement equivalent to:
888
889.. sourcecode:: sql
890
891    SELECT CAST('some text' AS TSVECTOR) AS anon_1
892
893The ``func`` namespace is augmented by the PostgreSQL dialect to set up
894correct argument and return types for most full text search functions.
895These functions are used automatically by the :attr:`_sql.func` namespace
896assuming the ``sqlalchemy.dialects.postgresql`` package has been imported,
897or :func:`_sa.create_engine` has been invoked using a ``postgresql``
898dialect.  These functions are documented at:
899
900* :class:`_postgresql.to_tsvector`
901* :class:`_postgresql.to_tsquery`
902* :class:`_postgresql.plainto_tsquery`
903* :class:`_postgresql.phraseto_tsquery`
904* :class:`_postgresql.websearch_to_tsquery`
905* :class:`_postgresql.ts_headline`
906
907Specifying the "regconfig" with ``match()`` or custom operators
908^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
909
910PostgreSQL's ``plainto_tsquery()`` function accepts an optional
911"regconfig" argument that is used to instruct PostgreSQL to use a
912particular pre-computed GIN or GiST index in order to perform the search.
913When using :meth:`.Operators.match`, this additional parameter may be
914specified using the ``postgresql_regconfig`` parameter, such as::
915
916    select(mytable.c.id).where(
917        mytable.c.title.match("somestring", postgresql_regconfig="english")
918    )
919
920Which would emit:
921
922.. sourcecode:: sql
923
924    SELECT mytable.id FROM mytable
925    WHERE mytable.title @@ plainto_tsquery('english', 'somestring')
926
927When using other PostgreSQL search functions with :data:`.func`, the
928"regconfig" parameter may be passed directly as the initial argument::
929
930    select(mytable.c.id).where(
931        func.to_tsvector("english", mytable.c.title).bool_op("@@")(
932            func.to_tsquery("english", "somestring")
933        )
934    )
935
936produces a statement equivalent to:
937
938.. sourcecode:: sql
939
940    SELECT mytable.id FROM mytable
941    WHERE to_tsvector('english', mytable.title) @@
942        to_tsquery('english', 'somestring')
943
944It is recommended that you use the ``EXPLAIN ANALYZE...`` tool from
945PostgreSQL to ensure that you are generating queries with SQLAlchemy that
946take full advantage of any indexes you may have created for full text search.
947
948.. seealso::
949
950    `Full Text Search <https://www.postgresql.org/docs/current/textsearch-controls.html>`_ - in the PostgreSQL documentation
951
952
953FROM ONLY ...
954-------------
955
956The dialect supports PostgreSQL's ONLY keyword for targeting only a particular
957table in an inheritance hierarchy. This can be used to produce the
958``SELECT ... FROM ONLY``, ``UPDATE ONLY ...``, and ``DELETE FROM ONLY ...``
959syntaxes. It uses SQLAlchemy's hints mechanism::
960
961    # SELECT ... FROM ONLY ...
962    result = table.select().with_hint(table, "ONLY", "postgresql")
963    print(result.fetchall())
964
965    # UPDATE ONLY ...
966    table.update(values=dict(foo="bar")).with_hint(
967        "ONLY", dialect_name="postgresql"
968    )
969
970    # DELETE FROM ONLY ...
971    table.delete().with_hint("ONLY", dialect_name="postgresql")
972
973.. _postgresql_indexes:
974
975PostgreSQL-Specific Index Options
976---------------------------------
977
978Several extensions to the :class:`.Index` construct are available, specific
979to the PostgreSQL dialect.
980
981.. _postgresql_covering_indexes:
982
983Covering Indexes
984^^^^^^^^^^^^^^^^
985
986A covering index includes additional columns that are not part of the index key
987but are stored in the index, allowing PostgreSQL to satisfy queries using only
988the index without accessing the table (an "index-only scan").   This is
989indicated on the index using the ``INCLUDE`` clause.  The
990``postgresql_include`` option for :class:`.Index` (as well as
991:class:`.UniqueConstraint`) renders ``INCLUDE(colname)`` for the given string
992names::
993
994    Index("my_index", table.c.x, postgresql_include=["y"])
995
996would render the index as ``CREATE INDEX my_index ON table (x) INCLUDE (y)``
997
998Note that this feature requires PostgreSQL 11 or later.
999
1000.. seealso::
1001
1002  :ref:`postgresql_constraint_options_include` - the same feature implemented
1003  for :class:`.UniqueConstraint`
1004
1005.. versionadded:: 1.4 - support for covering indexes with :class:`.Index`.
1006   support for :class:`.UniqueConstraint` was in 2.0.41
1007
1008.. _postgresql_partial_indexes:
1009
1010Partial Indexes
1011^^^^^^^^^^^^^^^
1012
1013Partial indexes add criterion to the index definition so that the index is
1014applied to a subset of rows.   These can be specified on :class:`.Index`
1015using the ``postgresql_where`` keyword argument::
1016
1017  Index("my_index", my_table.c.id, postgresql_where=my_table.c.value > 10)
1018
1019.. _postgresql_operator_classes:
1020
1021Operator Classes
1022^^^^^^^^^^^^^^^^
1023
1024PostgreSQL allows the specification of an *operator class* for each column of
1025an index (see
1026https://www.postgresql.org/docs/current/interactive/indexes-opclass.html).
1027The :class:`.Index` construct allows these to be specified via the
1028``postgresql_ops`` keyword argument::
1029
1030    Index(
1031        "my_index",
1032        my_table.c.id,
1033        my_table.c.data,
1034        postgresql_ops={"data": "text_pattern_ops", "id": "int4_ops"},
1035    )
1036
1037Note that the keys in the ``postgresql_ops`` dictionaries are the
1038"key" name of the :class:`_schema.Column`, i.e. the name used to access it from
1039the ``.c`` collection of :class:`_schema.Table`, which can be configured to be
1040different than the actual name of the column as expressed in the database.
1041
1042If ``postgresql_ops`` is to be used against a complex SQL expression such
1043as a function call, then to apply to the column it must be given a label
1044that is identified in the dictionary by name, e.g.::
1045
1046    Index(
1047        "my_index",
1048        my_table.c.id,
1049        func.lower(my_table.c.data).label("data_lower"),
1050        postgresql_ops={"data_lower": "text_pattern_ops", "id": "int4_ops"},
1051    )
1052
1053Operator classes are also supported by the
1054:class:`_postgresql.ExcludeConstraint` construct using the
1055:paramref:`_postgresql.ExcludeConstraint.ops` parameter. See that parameter for
1056details.
1057
1058.. versionadded:: 1.3.21 added support for operator classes with
1059   :class:`_postgresql.ExcludeConstraint`.
1060
1061
1062Index Types
1063^^^^^^^^^^^
1064
1065PostgreSQL provides several index types: B-Tree, Hash, GiST, and GIN, as well
1066as the ability for users to create their own (see
1067https://www.postgresql.org/docs/current/static/indexes-types.html). These can be
1068specified on :class:`.Index` using the ``postgresql_using`` keyword argument::
1069
1070    Index("my_index", my_table.c.data, postgresql_using="gin")
1071
1072The value passed to the keyword argument will be simply passed through to the
1073underlying CREATE INDEX command, so it *must* be a valid index type for your
1074version of PostgreSQL.
1075
1076.. _postgresql_index_storage:
1077
1078Index Storage Parameters
1079^^^^^^^^^^^^^^^^^^^^^^^^
1080
1081PostgreSQL allows storage parameters to be set on indexes. The storage
1082parameters available depend on the index method used by the index. Storage
1083parameters can be specified on :class:`.Index` using the ``postgresql_with``
1084keyword argument::
1085
1086    Index("my_index", my_table.c.data, postgresql_with={"fillfactor": 50})
1087
1088PostgreSQL allows to define the tablespace in which to create the index.
1089The tablespace can be specified on :class:`.Index` using the
1090``postgresql_tablespace`` keyword argument::
1091
1092    Index("my_index", my_table.c.data, postgresql_tablespace="my_tablespace")
1093
1094Note that the same option is available on :class:`_schema.Table` as well.
1095
1096.. _postgresql_index_concurrently:
1097
1098Indexes with CONCURRENTLY
1099^^^^^^^^^^^^^^^^^^^^^^^^^
1100
1101The PostgreSQL index option CONCURRENTLY is supported by passing the
1102flag ``postgresql_concurrently`` to the :class:`.Index` construct::
1103
1104    tbl = Table("testtbl", m, Column("data", Integer))
1105
1106    idx1 = Index("test_idx1", tbl.c.data, postgresql_concurrently=True)
1107
1108The above index construct will render DDL for CREATE INDEX, assuming
1109PostgreSQL 8.2 or higher is detected or for a connection-less dialect, as:
1110
1111.. sourcecode:: sql
1112
1113    CREATE INDEX CONCURRENTLY test_idx1 ON testtbl (data)
1114
1115For DROP INDEX, assuming PostgreSQL 9.2 or higher is detected or for
1116a connection-less dialect, it will emit:
1117
1118.. sourcecode:: sql
1119
1120    DROP INDEX CONCURRENTLY test_idx1
1121
1122When using CONCURRENTLY, the PostgreSQL database requires that the statement
1123be invoked outside of a transaction block.   The Python DBAPI enforces that
1124even for a single statement, a transaction is present, so to use this
1125construct, the DBAPI's "autocommit" mode must be used::
1126
1127    metadata = MetaData()
1128    table = Table("foo", metadata, Column("id", String))
1129    index = Index("foo_idx", table.c.id, postgresql_concurrently=True)
1130
1131    with engine.connect() as conn:
1132        with conn.execution_options(isolation_level="AUTOCOMMIT"):
1133            table.create(conn)
1134
1135.. seealso::
1136
1137    :ref:`postgresql_isolation_level`
1138
1139.. _postgresql_index_reflection:
1140
1141PostgreSQL Index Reflection
1142---------------------------
1143
1144The PostgreSQL database creates a UNIQUE INDEX implicitly whenever the
1145UNIQUE CONSTRAINT construct is used.   When inspecting a table using
1146:class:`_reflection.Inspector`, the :meth:`_reflection.Inspector.get_indexes`
1147and the :meth:`_reflection.Inspector.get_unique_constraints`
1148will report on these
1149two constructs distinctly; in the case of the index, the key
1150``duplicates_constraint`` will be present in the index entry if it is
1151detected as mirroring a constraint.   When performing reflection using
1152``Table(..., autoload_with=engine)``, the UNIQUE INDEX is **not** returned
1153in :attr:`_schema.Table.indexes` when it is detected as mirroring a
1154:class:`.UniqueConstraint` in the :attr:`_schema.Table.constraints` collection
1155.
1156
1157Special Reflection Options
1158--------------------------
1159
1160The :class:`_reflection.Inspector`
1161used for the PostgreSQL backend is an instance
1162of :class:`.PGInspector`, which offers additional methods::
1163
1164    from sqlalchemy import create_engine, inspect
1165
1166    engine = create_engine("postgresql+psycopg2://localhost/test")
1167    insp = inspect(engine)  # will be a PGInspector
1168
1169    print(insp.get_enums())
1170
1171.. autoclass:: PGInspector
1172    :members:
1173
1174.. _postgresql_table_options:
1175
1176PostgreSQL Table Options
1177------------------------
1178
1179Several options for CREATE TABLE are supported directly by the PostgreSQL
1180dialect in conjunction with the :class:`_schema.Table` construct, listed in
1181the following sections.
1182
1183.. seealso::
1184
1185    `PostgreSQL CREATE TABLE options
1186    <https://www.postgresql.org/docs/current/static/sql-createtable.html>`_ -
1187    in the PostgreSQL documentation.
1188
1189``INHERITS``
1190^^^^^^^^^^^^
1191
1192Specifies one or more parent tables from which this table inherits columns and
1193constraints, enabling table inheritance hierarchies in PostgreSQL.
1194
1195::
1196
1197    Table("some_table", metadata, ..., postgresql_inherits="some_supertable")
1198
1199    Table("some_table", metadata, ..., postgresql_inherits=("t1", "t2", ...))
1200

Showing the first 1,200 of 5379 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai