SQLAlchemy 2.0.47__cp313-cp313t-win_amd64.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-win_amd64.pyd +0 -0
  8. sqlalchemy/cyextension/collections.pyx +409 -0
  9. sqlalchemy/cyextension/immutabledict.cp313t-win_amd64.pyd +0 -0
  10. sqlalchemy/cyextension/immutabledict.pxd +8 -0
  11. sqlalchemy/cyextension/immutabledict.pyx +133 -0
  12. sqlalchemy/cyextension/processors.cp313t-win_amd64.pyd +0 -0
  13. sqlalchemy/cyextension/processors.pyx +68 -0
  14. sqlalchemy/cyextension/resultproxy.cp313t-win_amd64.pyd +0 -0
  15. sqlalchemy/cyextension/resultproxy.pyx +102 -0
  16. sqlalchemy/cyextension/util.cp313t-win_amd64.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,540 @@
1
+ # dialects/postgresql/ext.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
+ from __future__ import annotations
9
+
10
+ from typing import Any
11
+ from typing import Iterable
12
+ from typing import List
13
+ from typing import Optional
14
+ from typing import overload
15
+ from typing import Tuple
16
+ from typing import TYPE_CHECKING
17
+ from typing import TypeVar
18
+
19
+ from . import types
20
+ from .array import ARRAY
21
+ from ...sql import coercions
22
+ from ...sql import elements
23
+ from ...sql import expression
24
+ from ...sql import functions
25
+ from ...sql import roles
26
+ from ...sql import schema
27
+ from ...sql.schema import ColumnCollectionConstraint
28
+ from ...sql.sqltypes import TEXT
29
+ from ...sql.visitors import InternalTraversal
30
+
31
+ if TYPE_CHECKING:
32
+ from ...sql._typing import _ColumnExpressionArgument
33
+ from ...sql._typing import _DDLColumnArgument
34
+ from ...sql.elements import ClauseElement
35
+ from ...sql.elements import ColumnElement
36
+ from ...sql.operators import OperatorType
37
+ from ...sql.selectable import FromClause
38
+ from ...sql.visitors import _CloneCallableType
39
+ from ...sql.visitors import _TraverseInternalsType
40
+
41
+ _T = TypeVar("_T", bound=Any)
42
+
43
+
44
+ class aggregate_order_by(expression.ColumnElement[_T]):
45
+ """Represent a PostgreSQL aggregate order by expression.
46
+
47
+ E.g.::
48
+
49
+ from sqlalchemy.dialects.postgresql import aggregate_order_by
50
+
51
+ expr = func.array_agg(aggregate_order_by(table.c.a, table.c.b.desc()))
52
+ stmt = select(expr)
53
+
54
+ would represent the expression:
55
+
56
+ .. sourcecode:: sql
57
+
58
+ SELECT array_agg(a ORDER BY b DESC) FROM table;
59
+
60
+ Similarly::
61
+
62
+ expr = func.string_agg(
63
+ table.c.a, aggregate_order_by(literal_column("','"), table.c.a)
64
+ )
65
+ stmt = select(expr)
66
+
67
+ Would represent:
68
+
69
+ .. sourcecode:: sql
70
+
71
+ SELECT string_agg(a, ',' ORDER BY a) FROM table;
72
+
73
+ .. versionchanged:: 1.2.13 - the ORDER BY argument may be multiple terms
74
+
75
+ .. seealso::
76
+
77
+ :class:`_functions.array_agg`
78
+
79
+ """
80
+
81
+ __visit_name__ = "aggregate_order_by"
82
+
83
+ stringify_dialect = "postgresql"
84
+ _traverse_internals: _TraverseInternalsType = [
85
+ ("target", InternalTraversal.dp_clauseelement),
86
+ ("type", InternalTraversal.dp_type),
87
+ ("order_by", InternalTraversal.dp_clauseelement),
88
+ ]
89
+
90
+ @overload
91
+ def __init__(
92
+ self,
93
+ target: ColumnElement[_T],
94
+ *order_by: _ColumnExpressionArgument[Any],
95
+ ): ...
96
+
97
+ @overload
98
+ def __init__(
99
+ self,
100
+ target: _ColumnExpressionArgument[_T],
101
+ *order_by: _ColumnExpressionArgument[Any],
102
+ ): ...
103
+
104
+ def __init__(
105
+ self,
106
+ target: _ColumnExpressionArgument[_T],
107
+ *order_by: _ColumnExpressionArgument[Any],
108
+ ):
109
+ self.target: ClauseElement = coercions.expect(
110
+ roles.ExpressionElementRole, target
111
+ )
112
+ self.type = self.target.type
113
+
114
+ _lob = len(order_by)
115
+ self.order_by: ClauseElement
116
+ if _lob == 0:
117
+ raise TypeError("at least one ORDER BY element is required")
118
+ elif _lob == 1:
119
+ self.order_by = coercions.expect(
120
+ roles.ExpressionElementRole, order_by[0]
121
+ )
122
+ else:
123
+ self.order_by = elements.ClauseList(
124
+ *order_by, _literal_as_text_role=roles.ExpressionElementRole
125
+ )
126
+
127
+ def self_group(
128
+ self, against: Optional[OperatorType] = None
129
+ ) -> ClauseElement:
130
+ return self
131
+
132
+ def get_children(self, **kwargs: Any) -> Iterable[ClauseElement]:
133
+ return self.target, self.order_by
134
+
135
+ def _copy_internals(
136
+ self, clone: _CloneCallableType = elements._clone, **kw: Any
137
+ ) -> None:
138
+ self.target = clone(self.target, **kw)
139
+ self.order_by = clone(self.order_by, **kw)
140
+
141
+ @property
142
+ def _from_objects(self) -> List[FromClause]:
143
+ return self.target._from_objects + self.order_by._from_objects
144
+
145
+
146
+ class ExcludeConstraint(ColumnCollectionConstraint):
147
+ """A table-level EXCLUDE constraint.
148
+
149
+ Defines an EXCLUDE constraint as described in the `PostgreSQL
150
+ documentation`__.
151
+
152
+ __ https://www.postgresql.org/docs/current/static/sql-createtable.html#SQL-CREATETABLE-EXCLUDE
153
+
154
+ """ # noqa
155
+
156
+ __visit_name__ = "exclude_constraint"
157
+
158
+ where = None
159
+ inherit_cache = False
160
+
161
+ create_drop_stringify_dialect = "postgresql"
162
+
163
+ @elements._document_text_coercion(
164
+ "where",
165
+ ":class:`.ExcludeConstraint`",
166
+ ":paramref:`.ExcludeConstraint.where`",
167
+ )
168
+ def __init__(
169
+ self, *elements: Tuple[_DDLColumnArgument, str], **kw: Any
170
+ ) -> None:
171
+ r"""
172
+ Create an :class:`.ExcludeConstraint` object.
173
+
174
+ E.g.::
175
+
176
+ const = ExcludeConstraint(
177
+ (Column("period"), "&&"),
178
+ (Column("group"), "="),
179
+ where=(Column("group") != "some group"),
180
+ ops={"group": "my_operator_class"},
181
+ )
182
+
183
+ The constraint is normally embedded into the :class:`_schema.Table`
184
+ construct
185
+ directly, or added later using :meth:`.append_constraint`::
186
+
187
+ some_table = Table(
188
+ "some_table",
189
+ metadata,
190
+ Column("id", Integer, primary_key=True),
191
+ Column("period", TSRANGE()),
192
+ Column("group", String),
193
+ )
194
+
195
+ some_table.append_constraint(
196
+ ExcludeConstraint(
197
+ (some_table.c.period, "&&"),
198
+ (some_table.c.group, "="),
199
+ where=some_table.c.group != "some group",
200
+ name="some_table_excl_const",
201
+ ops={"group": "my_operator_class"},
202
+ )
203
+ )
204
+
205
+ The exclude constraint defined in this example requires the
206
+ ``btree_gist`` extension, that can be created using the
207
+ command ``CREATE EXTENSION btree_gist;``.
208
+
209
+ :param \*elements:
210
+
211
+ A sequence of two tuples of the form ``(column, operator)`` where
212
+ "column" is either a :class:`_schema.Column` object, or a SQL
213
+ expression element (e.g. ``func.int8range(table.from, table.to)``)
214
+ or the name of a column as string, and "operator" is a string
215
+ containing the operator to use (e.g. `"&&"` or `"="`).
216
+
217
+ In order to specify a column name when a :class:`_schema.Column`
218
+ object is not available, while ensuring
219
+ that any necessary quoting rules take effect, an ad-hoc
220
+ :class:`_schema.Column` or :func:`_expression.column`
221
+ object should be used.
222
+ The ``column`` may also be a string SQL expression when
223
+ passed as :func:`_expression.literal_column` or
224
+ :func:`_expression.text`
225
+
226
+ :param name:
227
+ Optional, the in-database name of this constraint.
228
+
229
+ :param deferrable:
230
+ Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when
231
+ issuing DDL for this constraint.
232
+
233
+ :param initially:
234
+ Optional string. If set, emit INITIALLY <value> when issuing DDL
235
+ for this constraint.
236
+
237
+ :param using:
238
+ Optional string. If set, emit USING <index_method> when issuing DDL
239
+ for this constraint. Defaults to 'gist'.
240
+
241
+ :param where:
242
+ Optional SQL expression construct or literal SQL string.
243
+ If set, emit WHERE <predicate> when issuing DDL
244
+ for this constraint.
245
+
246
+ :param ops:
247
+ Optional dictionary. Used to define operator classes for the
248
+ elements; works the same way as that of the
249
+ :ref:`postgresql_ops <postgresql_operator_classes>`
250
+ parameter specified to the :class:`_schema.Index` construct.
251
+
252
+ .. versionadded:: 1.3.21
253
+
254
+ .. seealso::
255
+
256
+ :ref:`postgresql_operator_classes` - general description of how
257
+ PostgreSQL operator classes are specified.
258
+
259
+ """
260
+ columns = []
261
+ render_exprs = []
262
+ self.operators = {}
263
+
264
+ expressions, operators = zip(*elements)
265
+
266
+ for (expr, column, strname, add_element), operator in zip(
267
+ coercions.expect_col_expression_collection(
268
+ roles.DDLConstraintColumnRole, expressions
269
+ ),
270
+ operators,
271
+ ):
272
+ if add_element is not None:
273
+ columns.append(add_element)
274
+
275
+ name = column.name if column is not None else strname
276
+
277
+ if name is not None:
278
+ # backwards compat
279
+ self.operators[name] = operator
280
+
281
+ render_exprs.append((expr, name, operator))
282
+
283
+ self._render_exprs = render_exprs
284
+
285
+ ColumnCollectionConstraint.__init__(
286
+ self,
287
+ *columns,
288
+ name=kw.get("name"),
289
+ deferrable=kw.get("deferrable"),
290
+ initially=kw.get("initially"),
291
+ )
292
+ self.using = kw.get("using", "gist")
293
+ where = kw.get("where")
294
+ if where is not None:
295
+ self.where = coercions.expect(roles.StatementOptionRole, where)
296
+
297
+ self.ops = kw.get("ops", {})
298
+
299
+ def _set_parent(self, table, **kw):
300
+ super()._set_parent(table)
301
+
302
+ self._render_exprs = [
303
+ (
304
+ expr if not isinstance(expr, str) else table.c[expr],
305
+ name,
306
+ operator,
307
+ )
308
+ for expr, name, operator in (self._render_exprs)
309
+ ]
310
+
311
+ def _copy(self, target_table=None, **kw):
312
+ elements = [
313
+ (
314
+ schema._copy_expression(expr, self.parent, target_table),
315
+ operator,
316
+ )
317
+ for expr, _, operator in self._render_exprs
318
+ ]
319
+ c = self.__class__(
320
+ *elements,
321
+ name=self.name,
322
+ deferrable=self.deferrable,
323
+ initially=self.initially,
324
+ where=self.where,
325
+ using=self.using,
326
+ )
327
+ c.dispatch._update(self.dispatch)
328
+ return c
329
+
330
+
331
+ def array_agg(*arg, **kw):
332
+ """PostgreSQL-specific form of :class:`_functions.array_agg`, ensures
333
+ return type is :class:`_postgresql.ARRAY` and not
334
+ the plain :class:`_types.ARRAY`, unless an explicit ``type_``
335
+ is passed.
336
+
337
+ """
338
+ kw["_default_array_type"] = ARRAY
339
+ return functions.func.array_agg(*arg, **kw)
340
+
341
+
342
+ class _regconfig_fn(functions.GenericFunction[_T]):
343
+ inherit_cache = True
344
+
345
+ def __init__(self, *args, **kwargs):
346
+ args = list(args)
347
+ if len(args) > 1:
348
+ initial_arg = coercions.expect(
349
+ roles.ExpressionElementRole,
350
+ args.pop(0),
351
+ name=getattr(self, "name", None),
352
+ apply_propagate_attrs=self,
353
+ type_=types.REGCONFIG,
354
+ )
355
+ initial_arg = [initial_arg]
356
+ else:
357
+ initial_arg = []
358
+
359
+ addtl_args = [
360
+ coercions.expect(
361
+ roles.ExpressionElementRole,
362
+ c,
363
+ name=getattr(self, "name", None),
364
+ apply_propagate_attrs=self,
365
+ )
366
+ for c in args
367
+ ]
368
+ super().__init__(*(initial_arg + addtl_args), **kwargs)
369
+
370
+
371
+ class to_tsvector(_regconfig_fn):
372
+ """The PostgreSQL ``to_tsvector`` SQL function.
373
+
374
+ This function applies automatic casting of the REGCONFIG argument
375
+ to use the :class:`_postgresql.REGCONFIG` datatype automatically,
376
+ and applies a return type of :class:`_postgresql.TSVECTOR`.
377
+
378
+ Assuming the PostgreSQL dialect has been imported, either by invoking
379
+ ``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
380
+ engine using ``create_engine("postgresql...")``,
381
+ :class:`_postgresql.to_tsvector` will be used automatically when invoking
382
+ ``sqlalchemy.func.to_tsvector()``, ensuring the correct argument and return
383
+ type handlers are used at compile and execution time.
384
+
385
+ .. versionadded:: 2.0.0rc1
386
+
387
+ """
388
+
389
+ inherit_cache = True
390
+ type = types.TSVECTOR
391
+
392
+
393
+ class to_tsquery(_regconfig_fn):
394
+ """The PostgreSQL ``to_tsquery`` SQL function.
395
+
396
+ This function applies automatic casting of the REGCONFIG argument
397
+ to use the :class:`_postgresql.REGCONFIG` datatype automatically,
398
+ and applies a return type of :class:`_postgresql.TSQUERY`.
399
+
400
+ Assuming the PostgreSQL dialect has been imported, either by invoking
401
+ ``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
402
+ engine using ``create_engine("postgresql...")``,
403
+ :class:`_postgresql.to_tsquery` will be used automatically when invoking
404
+ ``sqlalchemy.func.to_tsquery()``, ensuring the correct argument and return
405
+ type handlers are used at compile and execution time.
406
+
407
+ .. versionadded:: 2.0.0rc1
408
+
409
+ """
410
+
411
+ inherit_cache = True
412
+ type = types.TSQUERY
413
+
414
+
415
+ class plainto_tsquery(_regconfig_fn):
416
+ """The PostgreSQL ``plainto_tsquery`` SQL function.
417
+
418
+ This function applies automatic casting of the REGCONFIG argument
419
+ to use the :class:`_postgresql.REGCONFIG` datatype automatically,
420
+ and applies a return type of :class:`_postgresql.TSQUERY`.
421
+
422
+ Assuming the PostgreSQL dialect has been imported, either by invoking
423
+ ``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
424
+ engine using ``create_engine("postgresql...")``,
425
+ :class:`_postgresql.plainto_tsquery` will be used automatically when
426
+ invoking ``sqlalchemy.func.plainto_tsquery()``, ensuring the correct
427
+ argument and return type handlers are used at compile and execution time.
428
+
429
+ .. versionadded:: 2.0.0rc1
430
+
431
+ """
432
+
433
+ inherit_cache = True
434
+ type = types.TSQUERY
435
+
436
+
437
+ class phraseto_tsquery(_regconfig_fn):
438
+ """The PostgreSQL ``phraseto_tsquery`` SQL function.
439
+
440
+ This function applies automatic casting of the REGCONFIG argument
441
+ to use the :class:`_postgresql.REGCONFIG` datatype automatically,
442
+ and applies a return type of :class:`_postgresql.TSQUERY`.
443
+
444
+ Assuming the PostgreSQL dialect has been imported, either by invoking
445
+ ``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
446
+ engine using ``create_engine("postgresql...")``,
447
+ :class:`_postgresql.phraseto_tsquery` will be used automatically when
448
+ invoking ``sqlalchemy.func.phraseto_tsquery()``, ensuring the correct
449
+ argument and return type handlers are used at compile and execution time.
450
+
451
+ .. versionadded:: 2.0.0rc1
452
+
453
+ """
454
+
455
+ inherit_cache = True
456
+ type = types.TSQUERY
457
+
458
+
459
+ class websearch_to_tsquery(_regconfig_fn):
460
+ """The PostgreSQL ``websearch_to_tsquery`` SQL function.
461
+
462
+ This function applies automatic casting of the REGCONFIG argument
463
+ to use the :class:`_postgresql.REGCONFIG` datatype automatically,
464
+ and applies a return type of :class:`_postgresql.TSQUERY`.
465
+
466
+ Assuming the PostgreSQL dialect has been imported, either by invoking
467
+ ``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
468
+ engine using ``create_engine("postgresql...")``,
469
+ :class:`_postgresql.websearch_to_tsquery` will be used automatically when
470
+ invoking ``sqlalchemy.func.websearch_to_tsquery()``, ensuring the correct
471
+ argument and return type handlers are used at compile and execution time.
472
+
473
+ .. versionadded:: 2.0.0rc1
474
+
475
+ """
476
+
477
+ inherit_cache = True
478
+ type = types.TSQUERY
479
+
480
+
481
+ class ts_headline(_regconfig_fn):
482
+ """The PostgreSQL ``ts_headline`` SQL function.
483
+
484
+ This function applies automatic casting of the REGCONFIG argument
485
+ to use the :class:`_postgresql.REGCONFIG` datatype automatically,
486
+ and applies a return type of :class:`_types.TEXT`.
487
+
488
+ Assuming the PostgreSQL dialect has been imported, either by invoking
489
+ ``from sqlalchemy.dialects import postgresql``, or by creating a PostgreSQL
490
+ engine using ``create_engine("postgresql...")``,
491
+ :class:`_postgresql.ts_headline` will be used automatically when invoking
492
+ ``sqlalchemy.func.ts_headline()``, ensuring the correct argument and return
493
+ type handlers are used at compile and execution time.
494
+
495
+ .. versionadded:: 2.0.0rc1
496
+
497
+ """
498
+
499
+ inherit_cache = True
500
+ type = TEXT
501
+
502
+ def __init__(self, *args, **kwargs):
503
+ args = list(args)
504
+
505
+ # parse types according to
506
+ # https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-HEADLINE
507
+ if len(args) < 2:
508
+ # invalid args; don't do anything
509
+ has_regconfig = False
510
+ elif (
511
+ isinstance(args[1], elements.ColumnElement)
512
+ and args[1].type._type_affinity is types.TSQUERY
513
+ ):
514
+ # tsquery is second argument, no regconfig argument
515
+ has_regconfig = False
516
+ else:
517
+ has_regconfig = True
518
+
519
+ if has_regconfig:
520
+ initial_arg = coercions.expect(
521
+ roles.ExpressionElementRole,
522
+ args.pop(0),
523
+ apply_propagate_attrs=self,
524
+ name=getattr(self, "name", None),
525
+ type_=types.REGCONFIG,
526
+ )
527
+ initial_arg = [initial_arg]
528
+ else:
529
+ initial_arg = []
530
+
531
+ addtl_args = [
532
+ coercions.expect(
533
+ roles.ExpressionElementRole,
534
+ c,
535
+ name=getattr(self, "name", None),
536
+ apply_propagate_attrs=self,
537
+ )
538
+ for c in args
539
+ ]
540
+ super().__init__(*(initial_arg + addtl_args), **kwargs)