SQLAlchemy 2.0.47__cp313-cp313t-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. sqlalchemy/__init__.py +283 -0
  2. sqlalchemy/connectors/__init__.py +18 -0
  3. sqlalchemy/connectors/aioodbc.py +184 -0
  4. sqlalchemy/connectors/asyncio.py +429 -0
  5. sqlalchemy/connectors/pyodbc.py +250 -0
  6. sqlalchemy/cyextension/__init__.py +6 -0
  7. sqlalchemy/cyextension/collections.cp313t-win32.pyd +0 -0
  8. sqlalchemy/cyextension/collections.pyx +409 -0
  9. sqlalchemy/cyextension/immutabledict.cp313t-win32.pyd +0 -0
  10. sqlalchemy/cyextension/immutabledict.pxd +8 -0
  11. sqlalchemy/cyextension/immutabledict.pyx +133 -0
  12. sqlalchemy/cyextension/processors.cp313t-win32.pyd +0 -0
  13. sqlalchemy/cyextension/processors.pyx +68 -0
  14. sqlalchemy/cyextension/resultproxy.cp313t-win32.pyd +0 -0
  15. sqlalchemy/cyextension/resultproxy.pyx +102 -0
  16. sqlalchemy/cyextension/util.cp313t-win32.pyd +0 -0
  17. sqlalchemy/cyextension/util.pyx +90 -0
  18. sqlalchemy/dialects/__init__.py +62 -0
  19. sqlalchemy/dialects/_typing.py +30 -0
  20. sqlalchemy/dialects/mssql/__init__.py +88 -0
  21. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  22. sqlalchemy/dialects/mssql/base.py +4093 -0
  23. sqlalchemy/dialects/mssql/information_schema.py +285 -0
  24. sqlalchemy/dialects/mssql/json.py +129 -0
  25. sqlalchemy/dialects/mssql/provision.py +185 -0
  26. sqlalchemy/dialects/mssql/pymssql.py +126 -0
  27. sqlalchemy/dialects/mssql/pyodbc.py +760 -0
  28. sqlalchemy/dialects/mysql/__init__.py +104 -0
  29. sqlalchemy/dialects/mysql/aiomysql.py +250 -0
  30. sqlalchemy/dialects/mysql/asyncmy.py +231 -0
  31. sqlalchemy/dialects/mysql/base.py +3949 -0
  32. sqlalchemy/dialects/mysql/cymysql.py +106 -0
  33. sqlalchemy/dialects/mysql/dml.py +225 -0
  34. sqlalchemy/dialects/mysql/enumerated.py +282 -0
  35. sqlalchemy/dialects/mysql/expression.py +146 -0
  36. sqlalchemy/dialects/mysql/json.py +91 -0
  37. sqlalchemy/dialects/mysql/mariadb.py +72 -0
  38. sqlalchemy/dialects/mysql/mariadbconnector.py +322 -0
  39. sqlalchemy/dialects/mysql/mysqlconnector.py +302 -0
  40. sqlalchemy/dialects/mysql/mysqldb.py +314 -0
  41. sqlalchemy/dialects/mysql/provision.py +153 -0
  42. sqlalchemy/dialects/mysql/pymysql.py +158 -0
  43. sqlalchemy/dialects/mysql/pyodbc.py +157 -0
  44. sqlalchemy/dialects/mysql/reflection.py +727 -0
  45. sqlalchemy/dialects/mysql/reserved_words.py +570 -0
  46. sqlalchemy/dialects/mysql/types.py +835 -0
  47. sqlalchemy/dialects/oracle/__init__.py +81 -0
  48. sqlalchemy/dialects/oracle/base.py +3802 -0
  49. sqlalchemy/dialects/oracle/cx_oracle.py +1555 -0
  50. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  51. sqlalchemy/dialects/oracle/oracledb.py +941 -0
  52. sqlalchemy/dialects/oracle/provision.py +297 -0
  53. sqlalchemy/dialects/oracle/types.py +316 -0
  54. sqlalchemy/dialects/oracle/vector.py +365 -0
  55. sqlalchemy/dialects/postgresql/__init__.py +167 -0
  56. sqlalchemy/dialects/postgresql/_psycopg_common.py +189 -0
  57. sqlalchemy/dialects/postgresql/array.py +519 -0
  58. sqlalchemy/dialects/postgresql/asyncpg.py +1284 -0
  59. sqlalchemy/dialects/postgresql/base.py +5378 -0
  60. sqlalchemy/dialects/postgresql/dml.py +339 -0
  61. sqlalchemy/dialects/postgresql/ext.py +540 -0
  62. sqlalchemy/dialects/postgresql/hstore.py +406 -0
  63. sqlalchemy/dialects/postgresql/json.py +404 -0
  64. sqlalchemy/dialects/postgresql/named_types.py +524 -0
  65. sqlalchemy/dialects/postgresql/operators.py +129 -0
  66. sqlalchemy/dialects/postgresql/pg8000.py +669 -0
  67. sqlalchemy/dialects/postgresql/pg_catalog.py +326 -0
  68. sqlalchemy/dialects/postgresql/provision.py +183 -0
  69. sqlalchemy/dialects/postgresql/psycopg.py +862 -0
  70. sqlalchemy/dialects/postgresql/psycopg2.py +892 -0
  71. sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
  72. sqlalchemy/dialects/postgresql/ranges.py +1031 -0
  73. sqlalchemy/dialects/postgresql/types.py +313 -0
  74. sqlalchemy/dialects/sqlite/__init__.py +57 -0
  75. sqlalchemy/dialects/sqlite/aiosqlite.py +482 -0
  76. sqlalchemy/dialects/sqlite/base.py +3056 -0
  77. sqlalchemy/dialects/sqlite/dml.py +263 -0
  78. sqlalchemy/dialects/sqlite/json.py +92 -0
  79. sqlalchemy/dialects/sqlite/provision.py +229 -0
  80. sqlalchemy/dialects/sqlite/pysqlcipher.py +157 -0
  81. sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
  82. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  83. sqlalchemy/engine/__init__.py +62 -0
  84. sqlalchemy/engine/_py_processors.py +136 -0
  85. sqlalchemy/engine/_py_row.py +128 -0
  86. sqlalchemy/engine/_py_util.py +74 -0
  87. sqlalchemy/engine/base.py +3390 -0
  88. sqlalchemy/engine/characteristics.py +155 -0
  89. sqlalchemy/engine/create.py +893 -0
  90. sqlalchemy/engine/cursor.py +2298 -0
  91. sqlalchemy/engine/default.py +2394 -0
  92. sqlalchemy/engine/events.py +965 -0
  93. sqlalchemy/engine/interfaces.py +3471 -0
  94. sqlalchemy/engine/mock.py +134 -0
  95. sqlalchemy/engine/processors.py +61 -0
  96. sqlalchemy/engine/reflection.py +2102 -0
  97. sqlalchemy/engine/result.py +2399 -0
  98. sqlalchemy/engine/row.py +400 -0
  99. sqlalchemy/engine/strategies.py +16 -0
  100. sqlalchemy/engine/url.py +924 -0
  101. sqlalchemy/engine/util.py +167 -0
  102. sqlalchemy/event/__init__.py +26 -0
  103. sqlalchemy/event/api.py +220 -0
  104. sqlalchemy/event/attr.py +676 -0
  105. sqlalchemy/event/base.py +472 -0
  106. sqlalchemy/event/legacy.py +258 -0
  107. sqlalchemy/event/registry.py +390 -0
  108. sqlalchemy/events.py +17 -0
  109. sqlalchemy/exc.py +832 -0
  110. sqlalchemy/ext/__init__.py +11 -0
  111. sqlalchemy/ext/associationproxy.py +2027 -0
  112. sqlalchemy/ext/asyncio/__init__.py +25 -0
  113. sqlalchemy/ext/asyncio/base.py +281 -0
  114. sqlalchemy/ext/asyncio/engine.py +1471 -0
  115. sqlalchemy/ext/asyncio/exc.py +21 -0
  116. sqlalchemy/ext/asyncio/result.py +965 -0
  117. sqlalchemy/ext/asyncio/scoping.py +1599 -0
  118. sqlalchemy/ext/asyncio/session.py +1947 -0
  119. sqlalchemy/ext/automap.py +1701 -0
  120. sqlalchemy/ext/baked.py +570 -0
  121. sqlalchemy/ext/compiler.py +600 -0
  122. sqlalchemy/ext/declarative/__init__.py +65 -0
  123. sqlalchemy/ext/declarative/extensions.py +564 -0
  124. sqlalchemy/ext/horizontal_shard.py +478 -0
  125. sqlalchemy/ext/hybrid.py +1535 -0
  126. sqlalchemy/ext/indexable.py +364 -0
  127. sqlalchemy/ext/instrumentation.py +450 -0
  128. sqlalchemy/ext/mutable.py +1085 -0
  129. sqlalchemy/ext/mypy/__init__.py +6 -0
  130. sqlalchemy/ext/mypy/apply.py +324 -0
  131. sqlalchemy/ext/mypy/decl_class.py +515 -0
  132. sqlalchemy/ext/mypy/infer.py +590 -0
  133. sqlalchemy/ext/mypy/names.py +335 -0
  134. sqlalchemy/ext/mypy/plugin.py +303 -0
  135. sqlalchemy/ext/mypy/util.py +357 -0
  136. sqlalchemy/ext/orderinglist.py +439 -0
  137. sqlalchemy/ext/serializer.py +185 -0
  138. sqlalchemy/future/__init__.py +16 -0
  139. sqlalchemy/future/engine.py +15 -0
  140. sqlalchemy/inspection.py +174 -0
  141. sqlalchemy/log.py +288 -0
  142. sqlalchemy/orm/__init__.py +171 -0
  143. sqlalchemy/orm/_orm_constructors.py +2661 -0
  144. sqlalchemy/orm/_typing.py +179 -0
  145. sqlalchemy/orm/attributes.py +2845 -0
  146. sqlalchemy/orm/base.py +971 -0
  147. sqlalchemy/orm/bulk_persistence.py +2135 -0
  148. sqlalchemy/orm/clsregistry.py +571 -0
  149. sqlalchemy/orm/collections.py +1627 -0
  150. sqlalchemy/orm/context.py +3334 -0
  151. sqlalchemy/orm/decl_api.py +2004 -0
  152. sqlalchemy/orm/decl_base.py +2192 -0
  153. sqlalchemy/orm/dependency.py +1302 -0
  154. sqlalchemy/orm/descriptor_props.py +1092 -0
  155. sqlalchemy/orm/dynamic.py +300 -0
  156. sqlalchemy/orm/evaluator.py +379 -0
  157. sqlalchemy/orm/events.py +3252 -0
  158. sqlalchemy/orm/exc.py +237 -0
  159. sqlalchemy/orm/identity.py +302 -0
  160. sqlalchemy/orm/instrumentation.py +754 -0
  161. sqlalchemy/orm/interfaces.py +1496 -0
  162. sqlalchemy/orm/loading.py +1686 -0
  163. sqlalchemy/orm/mapped_collection.py +557 -0
  164. sqlalchemy/orm/mapper.py +4444 -0
  165. sqlalchemy/orm/path_registry.py +809 -0
  166. sqlalchemy/orm/persistence.py +1788 -0
  167. sqlalchemy/orm/properties.py +935 -0
  168. sqlalchemy/orm/query.py +3459 -0
  169. sqlalchemy/orm/relationships.py +3508 -0
  170. sqlalchemy/orm/scoping.py +2148 -0
  171. sqlalchemy/orm/session.py +5280 -0
  172. sqlalchemy/orm/state.py +1168 -0
  173. sqlalchemy/orm/state_changes.py +196 -0
  174. sqlalchemy/orm/strategies.py +3470 -0
  175. sqlalchemy/orm/strategy_options.py +2568 -0
  176. sqlalchemy/orm/sync.py +164 -0
  177. sqlalchemy/orm/unitofwork.py +796 -0
  178. sqlalchemy/orm/util.py +2403 -0
  179. sqlalchemy/orm/writeonly.py +674 -0
  180. sqlalchemy/pool/__init__.py +44 -0
  181. sqlalchemy/pool/base.py +1524 -0
  182. sqlalchemy/pool/events.py +375 -0
  183. sqlalchemy/pool/impl.py +588 -0
  184. sqlalchemy/py.typed +0 -0
  185. sqlalchemy/schema.py +69 -0
  186. sqlalchemy/sql/__init__.py +145 -0
  187. sqlalchemy/sql/_dml_constructors.py +132 -0
  188. sqlalchemy/sql/_elements_constructors.py +1872 -0
  189. sqlalchemy/sql/_orm_types.py +20 -0
  190. sqlalchemy/sql/_py_util.py +75 -0
  191. sqlalchemy/sql/_selectable_constructors.py +763 -0
  192. sqlalchemy/sql/_typing.py +482 -0
  193. sqlalchemy/sql/annotation.py +587 -0
  194. sqlalchemy/sql/base.py +2293 -0
  195. sqlalchemy/sql/cache_key.py +1057 -0
  196. sqlalchemy/sql/coercions.py +1404 -0
  197. sqlalchemy/sql/compiler.py +8081 -0
  198. sqlalchemy/sql/crud.py +1752 -0
  199. sqlalchemy/sql/ddl.py +1444 -0
  200. sqlalchemy/sql/default_comparator.py +551 -0
  201. sqlalchemy/sql/dml.py +1850 -0
  202. sqlalchemy/sql/elements.py +5589 -0
  203. sqlalchemy/sql/events.py +458 -0
  204. sqlalchemy/sql/expression.py +159 -0
  205. sqlalchemy/sql/functions.py +2158 -0
  206. sqlalchemy/sql/lambdas.py +1442 -0
  207. sqlalchemy/sql/naming.py +209 -0
  208. sqlalchemy/sql/operators.py +2623 -0
  209. sqlalchemy/sql/roles.py +323 -0
  210. sqlalchemy/sql/schema.py +6222 -0
  211. sqlalchemy/sql/selectable.py +7265 -0
  212. sqlalchemy/sql/sqltypes.py +3930 -0
  213. sqlalchemy/sql/traversals.py +1024 -0
  214. sqlalchemy/sql/type_api.py +2368 -0
  215. sqlalchemy/sql/util.py +1485 -0
  216. sqlalchemy/sql/visitors.py +1164 -0
  217. sqlalchemy/testing/__init__.py +96 -0
  218. sqlalchemy/testing/assertions.py +994 -0
  219. sqlalchemy/testing/assertsql.py +520 -0
  220. sqlalchemy/testing/asyncio.py +135 -0
  221. sqlalchemy/testing/config.py +434 -0
  222. sqlalchemy/testing/engines.py +483 -0
  223. sqlalchemy/testing/entities.py +117 -0
  224. sqlalchemy/testing/exclusions.py +476 -0
  225. sqlalchemy/testing/fixtures/__init__.py +28 -0
  226. sqlalchemy/testing/fixtures/base.py +384 -0
  227. sqlalchemy/testing/fixtures/mypy.py +332 -0
  228. sqlalchemy/testing/fixtures/orm.py +227 -0
  229. sqlalchemy/testing/fixtures/sql.py +482 -0
  230. sqlalchemy/testing/pickleable.py +155 -0
  231. sqlalchemy/testing/plugin/__init__.py +6 -0
  232. sqlalchemy/testing/plugin/bootstrap.py +51 -0
  233. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  234. sqlalchemy/testing/plugin/pytestplugin.py +892 -0
  235. sqlalchemy/testing/profiling.py +329 -0
  236. sqlalchemy/testing/provision.py +603 -0
  237. sqlalchemy/testing/requirements.py +1945 -0
  238. sqlalchemy/testing/schema.py +198 -0
  239. sqlalchemy/testing/suite/__init__.py +19 -0
  240. sqlalchemy/testing/suite/test_cte.py +237 -0
  241. sqlalchemy/testing/suite/test_ddl.py +389 -0
  242. sqlalchemy/testing/suite/test_deprecations.py +153 -0
  243. sqlalchemy/testing/suite/test_dialect.py +776 -0
  244. sqlalchemy/testing/suite/test_insert.py +630 -0
  245. sqlalchemy/testing/suite/test_reflection.py +3557 -0
  246. sqlalchemy/testing/suite/test_results.py +504 -0
  247. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  248. sqlalchemy/testing/suite/test_select.py +2010 -0
  249. sqlalchemy/testing/suite/test_sequence.py +317 -0
  250. sqlalchemy/testing/suite/test_types.py +2147 -0
  251. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  252. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  253. sqlalchemy/testing/util.py +535 -0
  254. sqlalchemy/testing/warnings.py +52 -0
  255. sqlalchemy/types.py +74 -0
  256. sqlalchemy/util/__init__.py +162 -0
  257. sqlalchemy/util/_collections.py +712 -0
  258. sqlalchemy/util/_concurrency_py3k.py +288 -0
  259. sqlalchemy/util/_has_cy.py +40 -0
  260. sqlalchemy/util/_py_collections.py +541 -0
  261. sqlalchemy/util/compat.py +421 -0
  262. sqlalchemy/util/concurrency.py +110 -0
  263. sqlalchemy/util/deprecations.py +401 -0
  264. sqlalchemy/util/langhelpers.py +2203 -0
  265. sqlalchemy/util/preloaded.py +150 -0
  266. sqlalchemy/util/queue.py +322 -0
  267. sqlalchemy/util/tool_support.py +201 -0
  268. sqlalchemy/util/topological.py +120 -0
  269. sqlalchemy/util/typing.py +734 -0
  270. sqlalchemy-2.0.47.dist-info/METADATA +243 -0
  271. sqlalchemy-2.0.47.dist-info/RECORD +274 -0
  272. sqlalchemy-2.0.47.dist-info/WHEEL +5 -0
  273. sqlalchemy-2.0.47.dist-info/licenses/LICENSE +19 -0
  274. sqlalchemy-2.0.47.dist-info/top_level.txt +1 -0
@@ -0,0 +1,339 @@
1
+ # dialects/postgresql/dml.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
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+ from typing import List
11
+ from typing import Optional
12
+ from typing import Tuple
13
+ from typing import Union
14
+
15
+ from . import ext
16
+ from .._typing import _OnConflictConstraintT
17
+ from .._typing import _OnConflictIndexElementsT
18
+ from .._typing import _OnConflictIndexWhereT
19
+ from .._typing import _OnConflictSetT
20
+ from .._typing import _OnConflictWhereT
21
+ from ... import util
22
+ from ...sql import coercions
23
+ from ...sql import roles
24
+ from ...sql import schema
25
+ from ...sql._typing import _DMLTableArgument
26
+ from ...sql.base import _exclusive_against
27
+ from ...sql.base import _generative
28
+ from ...sql.base import ColumnCollection
29
+ from ...sql.base import ReadOnlyColumnCollection
30
+ from ...sql.dml import Insert as StandardInsert
31
+ from ...sql.elements import ClauseElement
32
+ from ...sql.elements import ColumnElement
33
+ from ...sql.elements import KeyedColumnElement
34
+ from ...sql.elements import TextClause
35
+ from ...sql.expression import alias
36
+ from ...util.typing import Self
37
+
38
+
39
+ __all__ = ("Insert", "insert")
40
+
41
+
42
+ def insert(table: _DMLTableArgument) -> Insert:
43
+ """Construct a PostgreSQL-specific variant :class:`_postgresql.Insert`
44
+ construct.
45
+
46
+ .. container:: inherited_member
47
+
48
+ The :func:`sqlalchemy.dialects.postgresql.insert` function creates
49
+ a :class:`sqlalchemy.dialects.postgresql.Insert`. This class is based
50
+ on the dialect-agnostic :class:`_sql.Insert` construct which may
51
+ be constructed using the :func:`_sql.insert` function in
52
+ SQLAlchemy Core.
53
+
54
+ The :class:`_postgresql.Insert` construct includes additional methods
55
+ :meth:`_postgresql.Insert.on_conflict_do_update`,
56
+ :meth:`_postgresql.Insert.on_conflict_do_nothing`.
57
+
58
+ """
59
+ return Insert(table)
60
+
61
+
62
+ class Insert(StandardInsert):
63
+ """PostgreSQL-specific implementation of INSERT.
64
+
65
+ Adds methods for PG-specific syntaxes such as ON CONFLICT.
66
+
67
+ The :class:`_postgresql.Insert` object is created using the
68
+ :func:`sqlalchemy.dialects.postgresql.insert` function.
69
+
70
+ """
71
+
72
+ stringify_dialect = "postgresql"
73
+ inherit_cache = False
74
+
75
+ @util.memoized_property
76
+ def excluded(
77
+ self,
78
+ ) -> ReadOnlyColumnCollection[str, KeyedColumnElement[Any]]:
79
+ """Provide the ``excluded`` namespace for an ON CONFLICT statement
80
+
81
+ PG's ON CONFLICT clause allows reference to the row that would
82
+ be inserted, known as ``excluded``. This attribute provides
83
+ all columns in this row to be referenceable.
84
+
85
+ .. tip:: The :attr:`_postgresql.Insert.excluded` attribute is an
86
+ instance of :class:`_expression.ColumnCollection`, which provides
87
+ an interface the same as that of the :attr:`_schema.Table.c`
88
+ collection described at :ref:`metadata_tables_and_columns`.
89
+ With this collection, ordinary names are accessible like attributes
90
+ (e.g. ``stmt.excluded.some_column``), but special names and
91
+ dictionary method names should be accessed using indexed access,
92
+ such as ``stmt.excluded["column name"]`` or
93
+ ``stmt.excluded["values"]``. See the docstring for
94
+ :class:`_expression.ColumnCollection` for further examples.
95
+
96
+ .. seealso::
97
+
98
+ :ref:`postgresql_insert_on_conflict` - example of how
99
+ to use :attr:`_expression.Insert.excluded`
100
+
101
+ """
102
+ return alias(self.table, name="excluded").columns
103
+
104
+ _on_conflict_exclusive = _exclusive_against(
105
+ "_post_values_clause",
106
+ msgs={
107
+ "_post_values_clause": "This Insert construct already has "
108
+ "an ON CONFLICT clause established"
109
+ },
110
+ )
111
+
112
+ @_generative
113
+ @_on_conflict_exclusive
114
+ def on_conflict_do_update(
115
+ self,
116
+ constraint: _OnConflictConstraintT = None,
117
+ index_elements: _OnConflictIndexElementsT = None,
118
+ index_where: _OnConflictIndexWhereT = None,
119
+ set_: _OnConflictSetT = None,
120
+ where: _OnConflictWhereT = None,
121
+ ) -> Self:
122
+ r"""
123
+ Specifies a DO UPDATE SET action for ON CONFLICT clause.
124
+
125
+ Either the ``constraint`` or ``index_elements`` argument is
126
+ required, but only one of these can be specified.
127
+
128
+ :param constraint:
129
+ The name of a unique or exclusion constraint on the table,
130
+ or the constraint object itself if it has a .name attribute.
131
+
132
+ :param index_elements:
133
+ A sequence consisting of string column names, :class:`_schema.Column`
134
+ objects, or other column expression objects that will be used
135
+ to infer a target index.
136
+
137
+ :param index_where:
138
+ Additional WHERE criterion that can be used to infer a
139
+ conditional target index.
140
+
141
+ :param set\_:
142
+ A dictionary or other mapping object
143
+ where the keys are either names of columns in the target table,
144
+ or :class:`_schema.Column` objects or other ORM-mapped columns
145
+ matching that of the target table, and expressions or literals
146
+ as values, specifying the ``SET`` actions to take.
147
+
148
+ .. versionadded:: 1.4 The
149
+ :paramref:`_postgresql.Insert.on_conflict_do_update.set_`
150
+ parameter supports :class:`_schema.Column` objects from the target
151
+ :class:`_schema.Table` as keys.
152
+
153
+ .. warning:: This dictionary does **not** take into account
154
+ Python-specified default UPDATE values or generation functions,
155
+ e.g. those specified using :paramref:`_schema.Column.onupdate`.
156
+ These values will not be exercised for an ON CONFLICT style of
157
+ UPDATE, unless they are manually specified in the
158
+ :paramref:`.Insert.on_conflict_do_update.set_` dictionary.
159
+
160
+ :param where:
161
+ Optional argument. An expression object representing a ``WHERE``
162
+ clause that restricts the rows affected by ``DO UPDATE SET``. Rows not
163
+ meeting the ``WHERE`` condition will not be updated (effectively a
164
+ ``DO NOTHING`` for those rows).
165
+
166
+
167
+ .. seealso::
168
+
169
+ :ref:`postgresql_insert_on_conflict`
170
+
171
+ """
172
+ self._post_values_clause = OnConflictDoUpdate(
173
+ constraint, index_elements, index_where, set_, where
174
+ )
175
+ return self
176
+
177
+ @_generative
178
+ @_on_conflict_exclusive
179
+ def on_conflict_do_nothing(
180
+ self,
181
+ constraint: _OnConflictConstraintT = None,
182
+ index_elements: _OnConflictIndexElementsT = None,
183
+ index_where: _OnConflictIndexWhereT = None,
184
+ ) -> Self:
185
+ """
186
+ Specifies a DO NOTHING action for ON CONFLICT clause.
187
+
188
+ The ``constraint`` and ``index_elements`` arguments
189
+ are optional, but only one of these can be specified.
190
+
191
+ :param constraint:
192
+ The name of a unique or exclusion constraint on the table,
193
+ or the constraint object itself if it has a .name attribute.
194
+
195
+ :param index_elements:
196
+ A sequence consisting of string column names, :class:`_schema.Column`
197
+ objects, or other column expression objects that will be used
198
+ to infer a target index.
199
+
200
+ :param index_where:
201
+ Additional WHERE criterion that can be used to infer a
202
+ conditional target index.
203
+
204
+ .. seealso::
205
+
206
+ :ref:`postgresql_insert_on_conflict`
207
+
208
+ """
209
+ self._post_values_clause = OnConflictDoNothing(
210
+ constraint, index_elements, index_where
211
+ )
212
+ return self
213
+
214
+
215
+ class OnConflictClause(ClauseElement):
216
+ stringify_dialect = "postgresql"
217
+
218
+ constraint_target: Optional[str]
219
+ inferred_target_elements: Optional[List[Union[str, schema.Column[Any]]]]
220
+ inferred_target_whereclause: Optional[
221
+ Union[ColumnElement[Any], TextClause]
222
+ ]
223
+
224
+ def __init__(
225
+ self,
226
+ constraint: _OnConflictConstraintT = None,
227
+ index_elements: _OnConflictIndexElementsT = None,
228
+ index_where: _OnConflictIndexWhereT = None,
229
+ ):
230
+ if constraint is not None:
231
+ if not isinstance(constraint, str) and isinstance(
232
+ constraint,
233
+ (schema.Constraint, ext.ExcludeConstraint),
234
+ ):
235
+ constraint = getattr(constraint, "name") or constraint
236
+
237
+ if constraint is not None:
238
+ if index_elements is not None:
239
+ raise ValueError(
240
+ "'constraint' and 'index_elements' are mutually exclusive"
241
+ )
242
+
243
+ if isinstance(constraint, str):
244
+ self.constraint_target = constraint
245
+ self.inferred_target_elements = None
246
+ self.inferred_target_whereclause = None
247
+ elif isinstance(constraint, schema.Index):
248
+ index_elements = constraint.expressions
249
+ index_where = constraint.dialect_options["postgresql"].get(
250
+ "where"
251
+ )
252
+ elif isinstance(constraint, ext.ExcludeConstraint):
253
+ index_elements = constraint.columns
254
+ index_where = constraint.where
255
+ else:
256
+ index_elements = constraint.columns
257
+ index_where = constraint.dialect_options["postgresql"].get(
258
+ "where"
259
+ )
260
+
261
+ if index_elements is not None:
262
+ self.constraint_target = None
263
+ self.inferred_target_elements = [
264
+ coercions.expect(roles.DDLConstraintColumnRole, column)
265
+ for column in index_elements
266
+ ]
267
+
268
+ self.inferred_target_whereclause = (
269
+ coercions.expect(
270
+ (
271
+ roles.StatementOptionRole
272
+ if isinstance(constraint, ext.ExcludeConstraint)
273
+ else roles.WhereHavingRole
274
+ ),
275
+ index_where,
276
+ )
277
+ if index_where is not None
278
+ else None
279
+ )
280
+
281
+ elif constraint is None:
282
+ self.constraint_target = self.inferred_target_elements = (
283
+ self.inferred_target_whereclause
284
+ ) = None
285
+
286
+
287
+ class OnConflictDoNothing(OnConflictClause):
288
+ __visit_name__ = "on_conflict_do_nothing"
289
+
290
+
291
+ class OnConflictDoUpdate(OnConflictClause):
292
+ __visit_name__ = "on_conflict_do_update"
293
+
294
+ update_values_to_set: List[Tuple[Union[schema.Column[Any], str], Any]]
295
+ update_whereclause: Optional[ColumnElement[Any]]
296
+
297
+ def __init__(
298
+ self,
299
+ constraint: _OnConflictConstraintT = None,
300
+ index_elements: _OnConflictIndexElementsT = None,
301
+ index_where: _OnConflictIndexWhereT = None,
302
+ set_: _OnConflictSetT = None,
303
+ where: _OnConflictWhereT = None,
304
+ ):
305
+ super().__init__(
306
+ constraint=constraint,
307
+ index_elements=index_elements,
308
+ index_where=index_where,
309
+ )
310
+
311
+ if (
312
+ self.inferred_target_elements is None
313
+ and self.constraint_target is None
314
+ ):
315
+ raise ValueError(
316
+ "Either constraint or index_elements, "
317
+ "but not both, must be specified unless DO NOTHING"
318
+ )
319
+
320
+ if isinstance(set_, dict):
321
+ if not set_:
322
+ raise ValueError("set parameter dictionary must not be empty")
323
+ elif isinstance(set_, ColumnCollection):
324
+ set_ = dict(set_)
325
+ else:
326
+ raise ValueError(
327
+ "set parameter must be a non-empty dictionary "
328
+ "or a ColumnCollection such as the `.c.` collection "
329
+ "of a Table object"
330
+ )
331
+ self.update_values_to_set = [
332
+ (coercions.expect(roles.DMLColumnRole, key), value)
333
+ for key, value in set_.items()
334
+ ]
335
+ self.update_whereclause = (
336
+ coercions.expect(roles.WhereHavingRole, where)
337
+ if where is not None
338
+ else None
339
+ )