SQLAlchemy 2.1.0b2__cp313-cp313t-win_arm64.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 (270) hide show
  1. sqlalchemy/__init__.py +298 -0
  2. sqlalchemy/connectors/__init__.py +18 -0
  3. sqlalchemy/connectors/aioodbc.py +171 -0
  4. sqlalchemy/connectors/asyncio.py +476 -0
  5. sqlalchemy/connectors/pyodbc.py +250 -0
  6. sqlalchemy/dialects/__init__.py +62 -0
  7. sqlalchemy/dialects/_typing.py +30 -0
  8. sqlalchemy/dialects/mssql/__init__.py +89 -0
  9. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  10. sqlalchemy/dialects/mssql/base.py +4166 -0
  11. sqlalchemy/dialects/mssql/information_schema.py +285 -0
  12. sqlalchemy/dialects/mssql/json.py +140 -0
  13. sqlalchemy/dialects/mssql/mssqlpython.py +220 -0
  14. sqlalchemy/dialects/mssql/provision.py +196 -0
  15. sqlalchemy/dialects/mssql/pymssql.py +126 -0
  16. sqlalchemy/dialects/mssql/pyodbc.py +698 -0
  17. sqlalchemy/dialects/mysql/__init__.py +106 -0
  18. sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
  19. sqlalchemy/dialects/mysql/aiomysql.py +226 -0
  20. sqlalchemy/dialects/mysql/asyncmy.py +214 -0
  21. sqlalchemy/dialects/mysql/base.py +3877 -0
  22. sqlalchemy/dialects/mysql/cymysql.py +106 -0
  23. sqlalchemy/dialects/mysql/dml.py +279 -0
  24. sqlalchemy/dialects/mysql/enumerated.py +277 -0
  25. sqlalchemy/dialects/mysql/expression.py +146 -0
  26. sqlalchemy/dialects/mysql/json.py +92 -0
  27. sqlalchemy/dialects/mysql/mariadb.py +67 -0
  28. sqlalchemy/dialects/mysql/mariadbconnector.py +330 -0
  29. sqlalchemy/dialects/mysql/mysqlconnector.py +296 -0
  30. sqlalchemy/dialects/mysql/mysqldb.py +312 -0
  31. sqlalchemy/dialects/mysql/provision.py +153 -0
  32. sqlalchemy/dialects/mysql/pymysql.py +157 -0
  33. sqlalchemy/dialects/mysql/pyodbc.py +156 -0
  34. sqlalchemy/dialects/mysql/reflection.py +724 -0
  35. sqlalchemy/dialects/mysql/reserved_words.py +570 -0
  36. sqlalchemy/dialects/mysql/types.py +845 -0
  37. sqlalchemy/dialects/oracle/__init__.py +85 -0
  38. sqlalchemy/dialects/oracle/base.py +3977 -0
  39. sqlalchemy/dialects/oracle/cx_oracle.py +1601 -0
  40. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  41. sqlalchemy/dialects/oracle/json.py +158 -0
  42. sqlalchemy/dialects/oracle/oracledb.py +909 -0
  43. sqlalchemy/dialects/oracle/provision.py +288 -0
  44. sqlalchemy/dialects/oracle/types.py +367 -0
  45. sqlalchemy/dialects/oracle/vector.py +368 -0
  46. sqlalchemy/dialects/postgresql/__init__.py +171 -0
  47. sqlalchemy/dialects/postgresql/_psycopg_common.py +229 -0
  48. sqlalchemy/dialects/postgresql/array.py +534 -0
  49. sqlalchemy/dialects/postgresql/asyncpg.py +1323 -0
  50. sqlalchemy/dialects/postgresql/base.py +5789 -0
  51. sqlalchemy/dialects/postgresql/bitstring.py +327 -0
  52. sqlalchemy/dialects/postgresql/dml.py +360 -0
  53. sqlalchemy/dialects/postgresql/ext.py +593 -0
  54. sqlalchemy/dialects/postgresql/hstore.py +423 -0
  55. sqlalchemy/dialects/postgresql/json.py +408 -0
  56. sqlalchemy/dialects/postgresql/named_types.py +521 -0
  57. sqlalchemy/dialects/postgresql/operators.py +130 -0
  58. sqlalchemy/dialects/postgresql/pg8000.py +670 -0
  59. sqlalchemy/dialects/postgresql/pg_catalog.py +344 -0
  60. sqlalchemy/dialects/postgresql/provision.py +184 -0
  61. sqlalchemy/dialects/postgresql/psycopg.py +799 -0
  62. sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
  63. sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
  64. sqlalchemy/dialects/postgresql/ranges.py +1002 -0
  65. sqlalchemy/dialects/postgresql/types.py +388 -0
  66. sqlalchemy/dialects/sqlite/__init__.py +57 -0
  67. sqlalchemy/dialects/sqlite/aiosqlite.py +321 -0
  68. sqlalchemy/dialects/sqlite/base.py +3063 -0
  69. sqlalchemy/dialects/sqlite/dml.py +279 -0
  70. sqlalchemy/dialects/sqlite/json.py +100 -0
  71. sqlalchemy/dialects/sqlite/provision.py +229 -0
  72. sqlalchemy/dialects/sqlite/pysqlcipher.py +161 -0
  73. sqlalchemy/dialects/sqlite/pysqlite.py +754 -0
  74. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  75. sqlalchemy/engine/__init__.py +62 -0
  76. sqlalchemy/engine/_processors_cy.cp313t-win_arm64.pyd +0 -0
  77. sqlalchemy/engine/_processors_cy.py +92 -0
  78. sqlalchemy/engine/_result_cy.cp313t-win_arm64.pyd +0 -0
  79. sqlalchemy/engine/_result_cy.py +633 -0
  80. sqlalchemy/engine/_row_cy.cp313t-win_arm64.pyd +0 -0
  81. sqlalchemy/engine/_row_cy.py +232 -0
  82. sqlalchemy/engine/_util_cy.cp313t-win_arm64.pyd +0 -0
  83. sqlalchemy/engine/_util_cy.py +136 -0
  84. sqlalchemy/engine/base.py +3354 -0
  85. sqlalchemy/engine/characteristics.py +155 -0
  86. sqlalchemy/engine/create.py +877 -0
  87. sqlalchemy/engine/cursor.py +2421 -0
  88. sqlalchemy/engine/default.py +2402 -0
  89. sqlalchemy/engine/events.py +965 -0
  90. sqlalchemy/engine/interfaces.py +3495 -0
  91. sqlalchemy/engine/mock.py +134 -0
  92. sqlalchemy/engine/processors.py +82 -0
  93. sqlalchemy/engine/reflection.py +2100 -0
  94. sqlalchemy/engine/result.py +1966 -0
  95. sqlalchemy/engine/row.py +397 -0
  96. sqlalchemy/engine/strategies.py +16 -0
  97. sqlalchemy/engine/url.py +922 -0
  98. sqlalchemy/engine/util.py +156 -0
  99. sqlalchemy/event/__init__.py +26 -0
  100. sqlalchemy/event/api.py +220 -0
  101. sqlalchemy/event/attr.py +674 -0
  102. sqlalchemy/event/base.py +472 -0
  103. sqlalchemy/event/legacy.py +258 -0
  104. sqlalchemy/event/registry.py +390 -0
  105. sqlalchemy/events.py +17 -0
  106. sqlalchemy/exc.py +922 -0
  107. sqlalchemy/ext/__init__.py +11 -0
  108. sqlalchemy/ext/associationproxy.py +2072 -0
  109. sqlalchemy/ext/asyncio/__init__.py +29 -0
  110. sqlalchemy/ext/asyncio/base.py +281 -0
  111. sqlalchemy/ext/asyncio/engine.py +1487 -0
  112. sqlalchemy/ext/asyncio/exc.py +21 -0
  113. sqlalchemy/ext/asyncio/result.py +994 -0
  114. sqlalchemy/ext/asyncio/scoping.py +1679 -0
  115. sqlalchemy/ext/asyncio/session.py +2007 -0
  116. sqlalchemy/ext/automap.py +1701 -0
  117. sqlalchemy/ext/baked.py +559 -0
  118. sqlalchemy/ext/compiler.py +600 -0
  119. sqlalchemy/ext/declarative/__init__.py +65 -0
  120. sqlalchemy/ext/declarative/extensions.py +560 -0
  121. sqlalchemy/ext/horizontal_shard.py +481 -0
  122. sqlalchemy/ext/hybrid.py +1877 -0
  123. sqlalchemy/ext/indexable.py +364 -0
  124. sqlalchemy/ext/instrumentation.py +450 -0
  125. sqlalchemy/ext/mutable.py +1081 -0
  126. sqlalchemy/ext/orderinglist.py +439 -0
  127. sqlalchemy/ext/serializer.py +185 -0
  128. sqlalchemy/future/__init__.py +16 -0
  129. sqlalchemy/future/engine.py +15 -0
  130. sqlalchemy/inspection.py +174 -0
  131. sqlalchemy/log.py +283 -0
  132. sqlalchemy/orm/__init__.py +176 -0
  133. sqlalchemy/orm/_orm_constructors.py +2694 -0
  134. sqlalchemy/orm/_typing.py +179 -0
  135. sqlalchemy/orm/attributes.py +2868 -0
  136. sqlalchemy/orm/base.py +976 -0
  137. sqlalchemy/orm/bulk_persistence.py +2152 -0
  138. sqlalchemy/orm/clsregistry.py +582 -0
  139. sqlalchemy/orm/collections.py +1568 -0
  140. sqlalchemy/orm/context.py +3471 -0
  141. sqlalchemy/orm/decl_api.py +2280 -0
  142. sqlalchemy/orm/decl_base.py +2309 -0
  143. sqlalchemy/orm/dependency.py +1306 -0
  144. sqlalchemy/orm/descriptor_props.py +1183 -0
  145. sqlalchemy/orm/dynamic.py +307 -0
  146. sqlalchemy/orm/evaluator.py +379 -0
  147. sqlalchemy/orm/events.py +3386 -0
  148. sqlalchemy/orm/exc.py +237 -0
  149. sqlalchemy/orm/identity.py +302 -0
  150. sqlalchemy/orm/instrumentation.py +746 -0
  151. sqlalchemy/orm/interfaces.py +1589 -0
  152. sqlalchemy/orm/loading.py +1684 -0
  153. sqlalchemy/orm/mapped_collection.py +557 -0
  154. sqlalchemy/orm/mapper.py +4411 -0
  155. sqlalchemy/orm/path_registry.py +829 -0
  156. sqlalchemy/orm/persistence.py +1789 -0
  157. sqlalchemy/orm/properties.py +973 -0
  158. sqlalchemy/orm/query.py +3528 -0
  159. sqlalchemy/orm/relationships.py +3570 -0
  160. sqlalchemy/orm/scoping.py +2232 -0
  161. sqlalchemy/orm/session.py +5403 -0
  162. sqlalchemy/orm/state.py +1175 -0
  163. sqlalchemy/orm/state_changes.py +196 -0
  164. sqlalchemy/orm/strategies.py +3492 -0
  165. sqlalchemy/orm/strategy_options.py +2562 -0
  166. sqlalchemy/orm/sync.py +164 -0
  167. sqlalchemy/orm/unitofwork.py +798 -0
  168. sqlalchemy/orm/util.py +2438 -0
  169. sqlalchemy/orm/writeonly.py +694 -0
  170. sqlalchemy/pool/__init__.py +41 -0
  171. sqlalchemy/pool/base.py +1522 -0
  172. sqlalchemy/pool/events.py +375 -0
  173. sqlalchemy/pool/impl.py +582 -0
  174. sqlalchemy/py.typed +0 -0
  175. sqlalchemy/schema.py +74 -0
  176. sqlalchemy/sql/__init__.py +156 -0
  177. sqlalchemy/sql/_annotated_cols.py +397 -0
  178. sqlalchemy/sql/_dml_constructors.py +132 -0
  179. sqlalchemy/sql/_elements_constructors.py +2164 -0
  180. sqlalchemy/sql/_orm_types.py +20 -0
  181. sqlalchemy/sql/_selectable_constructors.py +840 -0
  182. sqlalchemy/sql/_typing.py +487 -0
  183. sqlalchemy/sql/_util_cy.cp313t-win_arm64.pyd +0 -0
  184. sqlalchemy/sql/_util_cy.py +127 -0
  185. sqlalchemy/sql/annotation.py +590 -0
  186. sqlalchemy/sql/base.py +2699 -0
  187. sqlalchemy/sql/cache_key.py +1066 -0
  188. sqlalchemy/sql/coercions.py +1373 -0
  189. sqlalchemy/sql/compiler.py +8327 -0
  190. sqlalchemy/sql/crud.py +1815 -0
  191. sqlalchemy/sql/ddl.py +1928 -0
  192. sqlalchemy/sql/default_comparator.py +654 -0
  193. sqlalchemy/sql/dml.py +1977 -0
  194. sqlalchemy/sql/elements.py +6033 -0
  195. sqlalchemy/sql/events.py +458 -0
  196. sqlalchemy/sql/expression.py +172 -0
  197. sqlalchemy/sql/functions.py +2305 -0
  198. sqlalchemy/sql/lambdas.py +1443 -0
  199. sqlalchemy/sql/naming.py +209 -0
  200. sqlalchemy/sql/operators.py +2897 -0
  201. sqlalchemy/sql/roles.py +332 -0
  202. sqlalchemy/sql/schema.py +6703 -0
  203. sqlalchemy/sql/selectable.py +7553 -0
  204. sqlalchemy/sql/sqltypes.py +4093 -0
  205. sqlalchemy/sql/traversals.py +1042 -0
  206. sqlalchemy/sql/type_api.py +2446 -0
  207. sqlalchemy/sql/util.py +1495 -0
  208. sqlalchemy/sql/visitors.py +1157 -0
  209. sqlalchemy/testing/__init__.py +96 -0
  210. sqlalchemy/testing/assertions.py +1007 -0
  211. sqlalchemy/testing/assertsql.py +519 -0
  212. sqlalchemy/testing/asyncio.py +128 -0
  213. sqlalchemy/testing/config.py +440 -0
  214. sqlalchemy/testing/engines.py +483 -0
  215. sqlalchemy/testing/entities.py +117 -0
  216. sqlalchemy/testing/exclusions.py +476 -0
  217. sqlalchemy/testing/fixtures/__init__.py +30 -0
  218. sqlalchemy/testing/fixtures/base.py +384 -0
  219. sqlalchemy/testing/fixtures/mypy.py +247 -0
  220. sqlalchemy/testing/fixtures/orm.py +227 -0
  221. sqlalchemy/testing/fixtures/sql.py +538 -0
  222. sqlalchemy/testing/pickleable.py +155 -0
  223. sqlalchemy/testing/plugin/__init__.py +6 -0
  224. sqlalchemy/testing/plugin/bootstrap.py +51 -0
  225. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  226. sqlalchemy/testing/plugin/pytestplugin.py +892 -0
  227. sqlalchemy/testing/profiling.py +329 -0
  228. sqlalchemy/testing/provision.py +613 -0
  229. sqlalchemy/testing/requirements.py +1978 -0
  230. sqlalchemy/testing/schema.py +198 -0
  231. sqlalchemy/testing/suite/__init__.py +19 -0
  232. sqlalchemy/testing/suite/test_cte.py +237 -0
  233. sqlalchemy/testing/suite/test_ddl.py +420 -0
  234. sqlalchemy/testing/suite/test_dialect.py +776 -0
  235. sqlalchemy/testing/suite/test_insert.py +630 -0
  236. sqlalchemy/testing/suite/test_reflection.py +3557 -0
  237. sqlalchemy/testing/suite/test_results.py +660 -0
  238. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  239. sqlalchemy/testing/suite/test_select.py +2112 -0
  240. sqlalchemy/testing/suite/test_sequence.py +317 -0
  241. sqlalchemy/testing/suite/test_table_via_select.py +686 -0
  242. sqlalchemy/testing/suite/test_types.py +2271 -0
  243. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  244. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  245. sqlalchemy/testing/util.py +535 -0
  246. sqlalchemy/testing/warnings.py +52 -0
  247. sqlalchemy/types.py +76 -0
  248. sqlalchemy/util/__init__.py +158 -0
  249. sqlalchemy/util/_collections.py +688 -0
  250. sqlalchemy/util/_collections_cy.cp313t-win_arm64.pyd +0 -0
  251. sqlalchemy/util/_collections_cy.pxd +8 -0
  252. sqlalchemy/util/_collections_cy.py +516 -0
  253. sqlalchemy/util/_has_cython.py +46 -0
  254. sqlalchemy/util/_immutabledict_cy.cp313t-win_arm64.pyd +0 -0
  255. sqlalchemy/util/_immutabledict_cy.py +240 -0
  256. sqlalchemy/util/compat.py +299 -0
  257. sqlalchemy/util/concurrency.py +322 -0
  258. sqlalchemy/util/cython.py +79 -0
  259. sqlalchemy/util/deprecations.py +401 -0
  260. sqlalchemy/util/langhelpers.py +2320 -0
  261. sqlalchemy/util/preloaded.py +152 -0
  262. sqlalchemy/util/queue.py +304 -0
  263. sqlalchemy/util/tool_support.py +201 -0
  264. sqlalchemy/util/topological.py +120 -0
  265. sqlalchemy/util/typing.py +711 -0
  266. sqlalchemy-2.1.0b2.dist-info/METADATA +269 -0
  267. sqlalchemy-2.1.0b2.dist-info/RECORD +270 -0
  268. sqlalchemy-2.1.0b2.dist-info/WHEEL +5 -0
  269. sqlalchemy-2.1.0b2.dist-info/licenses/LICENSE +19 -0
  270. sqlalchemy-2.1.0b2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,654 @@
1
+ # sql/default_comparator.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
+
8
+ """Default implementation of SQL comparison operations."""
9
+
10
+ from __future__ import annotations
11
+
12
+ import typing
13
+ from typing import Any
14
+ from typing import Callable
15
+ from typing import NoReturn
16
+ from typing import Optional
17
+ from typing import Tuple
18
+ from typing import Type
19
+ from typing import Union
20
+
21
+ from . import coercions
22
+ from . import functions
23
+ from . import operators
24
+ from . import roles
25
+ from . import type_api
26
+ from .elements import and_
27
+ from .elements import BinaryExpression
28
+ from .elements import ClauseElement
29
+ from .elements import CollationClause
30
+ from .elements import CollectionAggregate
31
+ from .elements import ExpressionClauseList
32
+ from .elements import False_
33
+ from .elements import Null
34
+ from .elements import OperatorExpression
35
+ from .elements import or_
36
+ from .elements import True_
37
+ from .elements import UnaryExpression
38
+ from .operators import OperatorType
39
+ from .. import exc
40
+ from .. import util
41
+
42
+ _T = typing.TypeVar("_T", bound=Any)
43
+
44
+ if typing.TYPE_CHECKING:
45
+ from .elements import ColumnElement
46
+ from .operators import custom_op
47
+ from .type_api import TypeEngine
48
+
49
+
50
+ def _boolean_compare(
51
+ expr: ColumnElement[Any],
52
+ op: OperatorType,
53
+ obj: Any,
54
+ *,
55
+ negate_op: Optional[OperatorType] = None,
56
+ reverse: bool = False,
57
+ _python_is_types: Tuple[Type[Any], ...] = (type(None), bool),
58
+ result_type: Optional[TypeEngine[bool]] = None,
59
+ **kwargs: Any,
60
+ ) -> OperatorExpression[bool]:
61
+ if result_type is None:
62
+ result_type = type_api.BOOLEANTYPE
63
+
64
+ if isinstance(obj, _python_is_types + (Null, True_, False_)):
65
+ # allow x ==/!= True/False to be treated as a literal.
66
+ # this comes out to "== / != true/false" or "1/0" if those
67
+ # constants aren't supported and works on all platforms
68
+ if op in (operators.eq, operators.ne) and isinstance(
69
+ obj, (bool, True_, False_)
70
+ ):
71
+ return OperatorExpression._construct_for_op(
72
+ expr,
73
+ coercions.expect(roles.ConstExprRole, obj),
74
+ op,
75
+ type_=result_type,
76
+ negate=negate_op,
77
+ modifiers=kwargs,
78
+ )
79
+ elif op in (
80
+ operators.is_distinct_from,
81
+ operators.is_not_distinct_from,
82
+ ):
83
+ return OperatorExpression._construct_for_op(
84
+ expr,
85
+ coercions.expect(roles.ConstExprRole, obj),
86
+ op,
87
+ type_=result_type,
88
+ negate=negate_op,
89
+ modifiers=kwargs,
90
+ )
91
+ elif expr._is_collection_aggregate:
92
+ obj = coercions.expect(
93
+ roles.ConstExprRole, element=obj, operator=op, expr=expr
94
+ )
95
+ else:
96
+ # all other None uses IS, IS NOT
97
+ if op in (operators.eq, operators.is_):
98
+ return OperatorExpression._construct_for_op(
99
+ expr,
100
+ coercions.expect(roles.ConstExprRole, obj),
101
+ operators.is_,
102
+ negate=operators.is_not,
103
+ type_=result_type,
104
+ )
105
+ elif op in (operators.ne, operators.is_not):
106
+ return OperatorExpression._construct_for_op(
107
+ expr,
108
+ coercions.expect(roles.ConstExprRole, obj),
109
+ operators.is_not,
110
+ negate=operators.is_,
111
+ type_=result_type,
112
+ )
113
+ else:
114
+ raise exc.ArgumentError(
115
+ "Only '=', '!=', 'is_()', 'is_not()', "
116
+ "'is_distinct_from()', 'is_not_distinct_from()' "
117
+ "operators can be used with None/True/False"
118
+ )
119
+ else:
120
+ obj = coercions.expect(
121
+ roles.BinaryElementRole, element=obj, operator=op, expr=expr
122
+ )
123
+
124
+ if reverse:
125
+ return OperatorExpression._construct_for_op(
126
+ obj,
127
+ expr,
128
+ op,
129
+ type_=result_type,
130
+ negate=negate_op,
131
+ modifiers=kwargs,
132
+ )
133
+ else:
134
+ return OperatorExpression._construct_for_op(
135
+ expr,
136
+ obj,
137
+ op,
138
+ type_=result_type,
139
+ negate=negate_op,
140
+ modifiers=kwargs,
141
+ )
142
+
143
+
144
+ def _custom_op_operate(
145
+ expr: ColumnElement[Any],
146
+ op: custom_op[Any],
147
+ obj: Any,
148
+ reverse: bool = False,
149
+ result_type: Optional[TypeEngine[Any]] = None,
150
+ **kw: Any,
151
+ ) -> ColumnElement[Any]:
152
+ if result_type is None:
153
+ if op.return_type:
154
+ result_type = op.return_type
155
+ elif op.is_comparison:
156
+ result_type = type_api.BOOLEANTYPE
157
+
158
+ return _binary_operate(
159
+ expr, op, obj, reverse=reverse, result_type=result_type, **kw
160
+ )
161
+
162
+
163
+ def _binary_operate(
164
+ expr: ColumnElement[Any],
165
+ op: OperatorType,
166
+ obj: roles.BinaryElementRole[Any],
167
+ *,
168
+ reverse: bool = False,
169
+ result_type: Optional[TypeEngine[_T]] = None,
170
+ **kw: Any,
171
+ ) -> OperatorExpression[_T]:
172
+ coerced_obj = coercions.expect(
173
+ roles.BinaryElementRole, obj, expr=expr, operator=op
174
+ )
175
+
176
+ if reverse:
177
+ left, right = coerced_obj, expr
178
+ else:
179
+ left, right = expr, coerced_obj
180
+
181
+ if result_type is None:
182
+ op, result_type = left.comparator._adapt_expression(
183
+ op, right.comparator
184
+ )
185
+
186
+ return OperatorExpression._construct_for_op(
187
+ left, right, op, type_=result_type, modifiers=kw
188
+ )
189
+
190
+
191
+ def _conjunction_operate(
192
+ expr: ColumnElement[Any], op: OperatorType, other: Any, **kw: Any
193
+ ) -> ColumnElement[Any]:
194
+ if op is operators.and_:
195
+ return and_(expr, other)
196
+ elif op is operators.or_:
197
+ return or_(expr, other)
198
+ else:
199
+ raise NotImplementedError()
200
+
201
+
202
+ def _scalar(
203
+ expr: ColumnElement[Any],
204
+ op: OperatorType,
205
+ fn: Callable[[ColumnElement[Any]], ColumnElement[Any]],
206
+ **kw: Any,
207
+ ) -> ColumnElement[Any]:
208
+ return fn(expr)
209
+
210
+
211
+ def _in_impl(
212
+ expr: ColumnElement[Any],
213
+ op: OperatorType,
214
+ seq_or_selectable: ClauseElement,
215
+ negate_op: OperatorType,
216
+ **kw: Any,
217
+ ) -> ColumnElement[Any]:
218
+ seq_or_selectable = coercions.expect(
219
+ roles.InElementRole, seq_or_selectable, expr=expr, operator=op
220
+ )
221
+ if "in_ops" in seq_or_selectable._annotations:
222
+ op, negate_op = seq_or_selectable._annotations["in_ops"]
223
+
224
+ return _boolean_compare(
225
+ expr, op, seq_or_selectable, negate_op=negate_op, **kw
226
+ )
227
+
228
+
229
+ def _getitem_impl(
230
+ expr: ColumnElement[Any], op: OperatorType, other: Any, **kw: Any
231
+ ) -> ColumnElement[Any]:
232
+ if (
233
+ isinstance(expr.type, type_api.INDEXABLE)
234
+ or isinstance(expr.type, type_api.TypeDecorator)
235
+ and isinstance(expr.type.impl_instance, type_api.INDEXABLE)
236
+ ):
237
+ other = coercions.expect(
238
+ roles.BinaryElementRole, other, expr=expr, operator=op
239
+ )
240
+ return _binary_operate(expr, op, other, **kw)
241
+ else:
242
+ _unsupported_impl(expr, op, other, **kw)
243
+
244
+
245
+ def _unsupported_impl(
246
+ expr: ColumnElement[Any], op: OperatorType, *arg: Any, **kw: Any
247
+ ) -> NoReturn:
248
+ raise NotImplementedError(
249
+ "Operator '%s' is not supported on this expression" % op.__name__
250
+ )
251
+
252
+
253
+ def _inv_impl(
254
+ expr: ColumnElement[Any], op: OperatorType, **kw: Any
255
+ ) -> ColumnElement[Any]:
256
+ """See :meth:`.ColumnOperators.__inv__`."""
257
+
258
+ # undocumented element currently used by the ORM for
259
+ # relationship.contains()
260
+ if hasattr(expr, "negation_clause"):
261
+ return expr.negation_clause
262
+ else:
263
+ return expr._negate()
264
+
265
+
266
+ def _neg_impl(
267
+ expr: ColumnElement[Any], op: OperatorType, **kw: Any
268
+ ) -> ColumnElement[Any]:
269
+ """See :meth:`.ColumnOperators.__neg__`."""
270
+ return UnaryExpression(expr, operator=operators.neg, type_=expr.type)
271
+
272
+
273
+ def _bitwise_not_impl(
274
+ expr: ColumnElement[Any], op: OperatorType, **kw: Any
275
+ ) -> ColumnElement[Any]:
276
+ """See :meth:`.ColumnOperators.bitwise_not`."""
277
+
278
+ return UnaryExpression(
279
+ expr, operator=operators.bitwise_not_op, type_=expr.type
280
+ )
281
+
282
+
283
+ def _match_impl(
284
+ expr: ColumnElement[Any], op: OperatorType, other: Any, **kw: Any
285
+ ) -> ColumnElement[Any]:
286
+ """See :meth:`.ColumnOperators.match`."""
287
+
288
+ return _boolean_compare(
289
+ expr,
290
+ operators.match_op,
291
+ coercions.expect(
292
+ roles.BinaryElementRole,
293
+ other,
294
+ expr=expr,
295
+ operator=operators.match_op,
296
+ ),
297
+ result_type=type_api.MATCHTYPE,
298
+ negate_op=(
299
+ operators.not_match_op
300
+ if op is operators.match_op
301
+ else operators.match_op
302
+ ),
303
+ **kw,
304
+ )
305
+
306
+
307
+ def _distinct_impl(
308
+ expr: ColumnElement[Any], op: OperatorType, **kw: Any
309
+ ) -> ColumnElement[Any]:
310
+ """See :meth:`.ColumnOperators.distinct`."""
311
+ return UnaryExpression(
312
+ expr, operator=operators.distinct_op, type_=expr.type
313
+ )
314
+
315
+
316
+ def _between_impl(
317
+ expr: ColumnElement[Any],
318
+ op: OperatorType,
319
+ cleft: Any,
320
+ cright: Any,
321
+ **kw: Any,
322
+ ) -> ColumnElement[Any]:
323
+ """See :meth:`.ColumnOperators.between`."""
324
+ return BinaryExpression(
325
+ expr,
326
+ ExpressionClauseList._construct_for_list(
327
+ operators.and_,
328
+ type_api.NULLTYPE,
329
+ coercions.expect(
330
+ roles.BinaryElementRole,
331
+ cleft,
332
+ expr=expr,
333
+ operator=operators.and_,
334
+ ),
335
+ coercions.expect(
336
+ roles.BinaryElementRole,
337
+ cright,
338
+ expr=expr,
339
+ operator=operators.and_,
340
+ ),
341
+ group=False,
342
+ ),
343
+ op,
344
+ negate=(
345
+ operators.not_between_op
346
+ if op is operators.between_op
347
+ else operators.between_op
348
+ ),
349
+ modifiers=kw,
350
+ )
351
+
352
+
353
+ def _pow_impl(
354
+ expr: ColumnElement[Any],
355
+ op: OperatorType,
356
+ other: Any,
357
+ reverse: bool = False,
358
+ **kw: Any,
359
+ ) -> ColumnElement[Any]:
360
+ if reverse:
361
+ return functions.pow(other, expr)
362
+ else:
363
+ return functions.pow(expr, other)
364
+
365
+
366
+ def _collate_impl(
367
+ expr: ColumnElement[str], op: OperatorType, collation: str, **kw: Any
368
+ ) -> ColumnElement[str]:
369
+ return CollationClause._create_collation_expression(expr, collation)
370
+
371
+
372
+ def _regexp_match_impl(
373
+ expr: ColumnElement[str],
374
+ op: OperatorType,
375
+ pattern: Any,
376
+ flags: Optional[str],
377
+ **kw: Any,
378
+ ) -> ColumnElement[Any]:
379
+ return BinaryExpression(
380
+ expr,
381
+ coercions.expect(
382
+ roles.BinaryElementRole,
383
+ pattern,
384
+ expr=expr,
385
+ operator=operators.comma_op,
386
+ ),
387
+ op,
388
+ negate=operators.not_regexp_match_op,
389
+ modifiers={"flags": flags},
390
+ )
391
+
392
+
393
+ def _regexp_replace_impl(
394
+ expr: ColumnElement[Any],
395
+ op: OperatorType,
396
+ pattern: Any,
397
+ replacement: Any,
398
+ flags: Optional[str],
399
+ **kw: Any,
400
+ ) -> ColumnElement[Any]:
401
+ return BinaryExpression(
402
+ expr,
403
+ ExpressionClauseList._construct_for_list(
404
+ operators.comma_op,
405
+ type_api.NULLTYPE,
406
+ coercions.expect(
407
+ roles.BinaryElementRole,
408
+ pattern,
409
+ expr=expr,
410
+ operator=operators.comma_op,
411
+ ),
412
+ coercions.expect(
413
+ roles.BinaryElementRole,
414
+ replacement,
415
+ expr=expr,
416
+ operator=operators.comma_op,
417
+ ),
418
+ group=False,
419
+ ),
420
+ op,
421
+ modifiers={"flags": flags},
422
+ )
423
+
424
+
425
+ operator_lookup: util.immutabledict[
426
+ str,
427
+ Tuple[
428
+ Callable[..., "ColumnElement[Any]"],
429
+ util.immutabledict[
430
+ str, Union["OperatorType", Callable[..., "ColumnElement[Any]"]]
431
+ ],
432
+ ],
433
+ ] = util.immutabledict(
434
+ {
435
+ "any_op": (
436
+ _scalar,
437
+ util.immutabledict({"fn": CollectionAggregate._create_any}),
438
+ ),
439
+ "all_op": (
440
+ _scalar,
441
+ util.immutabledict({"fn": CollectionAggregate._create_all}),
442
+ ),
443
+ "lt": (
444
+ _boolean_compare,
445
+ util.immutabledict({"negate_op": operators.ge}),
446
+ ),
447
+ "le": (
448
+ _boolean_compare,
449
+ util.immutabledict({"negate_op": operators.gt}),
450
+ ),
451
+ "ne": (
452
+ _boolean_compare,
453
+ util.immutabledict({"negate_op": operators.eq}),
454
+ ),
455
+ "gt": (
456
+ _boolean_compare,
457
+ util.immutabledict({"negate_op": operators.le}),
458
+ ),
459
+ "ge": (
460
+ _boolean_compare,
461
+ util.immutabledict({"negate_op": operators.lt}),
462
+ ),
463
+ "eq": (
464
+ _boolean_compare,
465
+ util.immutabledict({"negate_op": operators.ne}),
466
+ ),
467
+ "is_distinct_from": (
468
+ _boolean_compare,
469
+ util.immutabledict({"negate_op": operators.is_not_distinct_from}),
470
+ ),
471
+ "is_not_distinct_from": (
472
+ _boolean_compare,
473
+ util.immutabledict({"negate_op": operators.is_distinct_from}),
474
+ ),
475
+ "in_op": (
476
+ _in_impl,
477
+ util.immutabledict({"negate_op": operators.not_in_op}),
478
+ ),
479
+ "not_in_op": (
480
+ _in_impl,
481
+ util.immutabledict({"negate_op": operators.in_op}),
482
+ ),
483
+ "is_": (
484
+ _boolean_compare,
485
+ util.immutabledict({"negate_op": operators.is_}),
486
+ ),
487
+ "is_not": (
488
+ _boolean_compare,
489
+ util.immutabledict({"negate_op": operators.is_not}),
490
+ ),
491
+ "between_op": (
492
+ _between_impl,
493
+ util.EMPTY_DICT,
494
+ ),
495
+ "not_between_op": (
496
+ _between_impl,
497
+ util.EMPTY_DICT,
498
+ ),
499
+ "desc_op": (
500
+ _scalar,
501
+ util.immutabledict({"fn": UnaryExpression._create_desc}),
502
+ ),
503
+ "asc_op": (
504
+ _scalar,
505
+ util.immutabledict({"fn": UnaryExpression._create_asc}),
506
+ ),
507
+ "nulls_first_op": (
508
+ _scalar,
509
+ util.immutabledict({"fn": UnaryExpression._create_nulls_first}),
510
+ ),
511
+ "nulls_last_op": (
512
+ _scalar,
513
+ util.immutabledict({"fn": UnaryExpression._create_nulls_last}),
514
+ ),
515
+ "distinct_op": (
516
+ _distinct_impl,
517
+ util.EMPTY_DICT,
518
+ ),
519
+ "null_op": (_binary_operate, util.EMPTY_DICT),
520
+ "custom_op": (_custom_op_operate, util.EMPTY_DICT),
521
+ "and_": (
522
+ _conjunction_operate,
523
+ util.EMPTY_DICT,
524
+ ),
525
+ "or_": (
526
+ _conjunction_operate,
527
+ util.EMPTY_DICT,
528
+ ),
529
+ "inv": (
530
+ _inv_impl,
531
+ util.EMPTY_DICT,
532
+ ),
533
+ "add": (
534
+ _binary_operate,
535
+ util.EMPTY_DICT,
536
+ ),
537
+ "concat_op": (
538
+ _binary_operate,
539
+ util.EMPTY_DICT,
540
+ ),
541
+ "getitem": (_getitem_impl, util.EMPTY_DICT),
542
+ "contains_op": (
543
+ _boolean_compare,
544
+ util.immutabledict({"negate_op": operators.not_contains_op}),
545
+ ),
546
+ "icontains_op": (
547
+ _boolean_compare,
548
+ util.immutabledict({"negate_op": operators.not_icontains_op}),
549
+ ),
550
+ "contains": (
551
+ _unsupported_impl,
552
+ util.EMPTY_DICT,
553
+ ),
554
+ "like_op": (
555
+ _boolean_compare,
556
+ util.immutabledict({"negate_op": operators.not_like_op}),
557
+ ),
558
+ "ilike_op": (
559
+ _boolean_compare,
560
+ util.immutabledict({"negate_op": operators.not_ilike_op}),
561
+ ),
562
+ "not_like_op": (
563
+ _boolean_compare,
564
+ util.immutabledict({"negate_op": operators.like_op}),
565
+ ),
566
+ "not_ilike_op": (
567
+ _boolean_compare,
568
+ util.immutabledict({"negate_op": operators.ilike_op}),
569
+ ),
570
+ "startswith_op": (
571
+ _boolean_compare,
572
+ util.immutabledict({"negate_op": operators.not_startswith_op}),
573
+ ),
574
+ "istartswith_op": (
575
+ _boolean_compare,
576
+ util.immutabledict({"negate_op": operators.not_istartswith_op}),
577
+ ),
578
+ "endswith_op": (
579
+ _boolean_compare,
580
+ util.immutabledict({"negate_op": operators.not_endswith_op}),
581
+ ),
582
+ "iendswith_op": (
583
+ _boolean_compare,
584
+ util.immutabledict({"negate_op": operators.not_iendswith_op}),
585
+ ),
586
+ "collate": (
587
+ _collate_impl,
588
+ util.EMPTY_DICT,
589
+ ),
590
+ "match_op": (_match_impl, util.EMPTY_DICT),
591
+ "not_match_op": (
592
+ _match_impl,
593
+ util.EMPTY_DICT,
594
+ ),
595
+ "regexp_match_op": (
596
+ _regexp_match_impl,
597
+ util.EMPTY_DICT,
598
+ ),
599
+ "not_regexp_match_op": (
600
+ _regexp_match_impl,
601
+ util.EMPTY_DICT,
602
+ ),
603
+ "regexp_replace_op": (
604
+ _regexp_replace_impl,
605
+ util.EMPTY_DICT,
606
+ ),
607
+ "lshift": (_unsupported_impl, util.EMPTY_DICT),
608
+ "rshift": (_unsupported_impl, util.EMPTY_DICT),
609
+ "bitwise_xor_op": (
610
+ _binary_operate,
611
+ util.EMPTY_DICT,
612
+ ),
613
+ "bitwise_or_op": (
614
+ _binary_operate,
615
+ util.EMPTY_DICT,
616
+ ),
617
+ "bitwise_and_op": (
618
+ _binary_operate,
619
+ util.EMPTY_DICT,
620
+ ),
621
+ "bitwise_not_op": (
622
+ _bitwise_not_impl,
623
+ util.EMPTY_DICT,
624
+ ),
625
+ "bitwise_lshift_op": (
626
+ _binary_operate,
627
+ util.EMPTY_DICT,
628
+ ),
629
+ "bitwise_rshift_op": (
630
+ _binary_operate,
631
+ util.EMPTY_DICT,
632
+ ),
633
+ "matmul": (_unsupported_impl, util.EMPTY_DICT),
634
+ "pow": (_pow_impl, util.EMPTY_DICT),
635
+ "neg": (_neg_impl, util.EMPTY_DICT),
636
+ "mul": (_binary_operate, util.EMPTY_DICT),
637
+ "sub": (
638
+ _binary_operate,
639
+ util.EMPTY_DICT,
640
+ ),
641
+ "div": (_binary_operate, util.EMPTY_DICT),
642
+ "mod": (_binary_operate, util.EMPTY_DICT),
643
+ "truediv": (_binary_operate, util.EMPTY_DICT),
644
+ "floordiv": (_binary_operate, util.EMPTY_DICT),
645
+ "json_path_getitem_op": (
646
+ _binary_operate,
647
+ util.EMPTY_DICT,
648
+ ),
649
+ "json_getitem_op": (
650
+ _binary_operate,
651
+ util.EMPTY_DICT,
652
+ ),
653
+ }
654
+ )