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,198 @@
1
+ # testing/schema.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
+
9
+ from __future__ import annotations
10
+
11
+ import sys
12
+
13
+ from . import config
14
+ from . import exclusions
15
+ from .. import event
16
+ from .. import schema
17
+ from .. import types as sqltypes
18
+ from ..orm import mapped_column as _orm_mapped_column
19
+ from ..util import OrderedDict
20
+
21
+ __all__ = ["Table", "Column"]
22
+
23
+ table_options = {}
24
+
25
+
26
+ def Table(*args, **kw) -> schema.Table:
27
+ """A schema.Table wrapper/hook for dialect-specific tweaks."""
28
+
29
+ # pop out local options; these are not used at the moment
30
+ _ = {k: kw.pop(k) for k in list(kw) if k.startswith("test_")}
31
+
32
+ kw.update(table_options)
33
+
34
+ return schema.Table(*args, **kw)
35
+
36
+
37
+ def mapped_column(*args, **kw):
38
+ """An orm.mapped_column wrapper/hook for dialect-specific tweaks."""
39
+
40
+ return _schema_column(_orm_mapped_column, args, kw)
41
+
42
+
43
+ def Column(*args, **kw):
44
+ """A schema.Column wrapper/hook for dialect-specific tweaks."""
45
+
46
+ return _schema_column(schema.Column, args, kw)
47
+
48
+
49
+ def _schema_column(factory, args, kw):
50
+ test_opts = {k: kw.pop(k) for k in list(kw) if k.startswith("test_")}
51
+
52
+ if not config.requirements.foreign_key_ddl.enabled_for_config(config):
53
+ args = [arg for arg in args if not isinstance(arg, schema.ForeignKey)]
54
+
55
+ construct = factory(*args, **kw)
56
+
57
+ if factory is schema.Column:
58
+ col = construct
59
+ else:
60
+ col = construct.column
61
+
62
+ if test_opts.get("test_needs_autoincrement", False) and kw.get(
63
+ "primary_key", False
64
+ ):
65
+ if col.default is None and col.server_default is None:
66
+ col.autoincrement = True
67
+
68
+ # allow any test suite to pick up on this
69
+ col.info["test_needs_autoincrement"] = True
70
+
71
+ # hardcoded rule for oracle; this should
72
+ # be moved out
73
+ if exclusions.against(config._current, "oracle"):
74
+
75
+ def add_seq(c, tbl):
76
+ c._init_items(
77
+ schema.Sequence(
78
+ _truncate_name(
79
+ config.db.dialect, tbl.name + "_" + c.name + "_seq"
80
+ ),
81
+ optional=True,
82
+ )
83
+ )
84
+
85
+ event.listen(col, "after_parent_attach", add_seq, propagate=True)
86
+ return construct
87
+
88
+
89
+ class eq_type_affinity:
90
+ """Helper to compare types inside of datastructures based on affinity.
91
+
92
+ E.g.::
93
+
94
+ eq_(
95
+ inspect(connection).get_columns("foo"),
96
+ [
97
+ {
98
+ "name": "id",
99
+ "type": testing.eq_type_affinity(sqltypes.INTEGER),
100
+ "nullable": False,
101
+ "default": None,
102
+ "autoincrement": False,
103
+ },
104
+ {
105
+ "name": "data",
106
+ "type": testing.eq_type_affinity(sqltypes.NullType),
107
+ "nullable": True,
108
+ "default": None,
109
+ "autoincrement": False,
110
+ },
111
+ ],
112
+ )
113
+
114
+ """
115
+
116
+ def __init__(self, target):
117
+ self.target = sqltypes.to_instance(target)
118
+
119
+ def __eq__(self, other):
120
+ return self.target._type_affinity is other._type_affinity
121
+
122
+ def __ne__(self, other):
123
+ return self.target._type_affinity is not other._type_affinity
124
+
125
+
126
+ class eq_compile_type:
127
+ """similar to eq_type_affinity but uses compile"""
128
+
129
+ def __init__(self, target):
130
+ self.target = target
131
+
132
+ def __eq__(self, other):
133
+ return self.target == other.compile()
134
+
135
+ def __ne__(self, other):
136
+ return self.target != other.compile()
137
+
138
+
139
+ class eq_clause_element:
140
+ """Helper to compare SQL structures based on compare()"""
141
+
142
+ def __init__(self, target):
143
+ self.target = target
144
+
145
+ def __eq__(self, other):
146
+ return self.target.compare(other)
147
+
148
+ def __ne__(self, other):
149
+ return not self.target.compare(other)
150
+
151
+
152
+ def _truncate_name(dialect, name):
153
+ if len(name) > dialect.max_identifier_length:
154
+ return (
155
+ name[0 : max(dialect.max_identifier_length - 6, 0)]
156
+ + "_"
157
+ + hex(hash(name) % 64)[2:]
158
+ )
159
+ else:
160
+ return name
161
+
162
+
163
+ def pep435_enum(name):
164
+ # Implements PEP 435 in the minimal fashion needed by SQLAlchemy
165
+ __members__ = OrderedDict()
166
+
167
+ def __init__(self, name, value, alias=None):
168
+ self.name = name
169
+ self.value = value
170
+ self.__members__[name] = self
171
+ value_to_member[value] = self
172
+ setattr(self.__class__, name, self)
173
+ if alias:
174
+ self.__members__[alias] = self
175
+ setattr(self.__class__, alias, self)
176
+
177
+ value_to_member = {}
178
+
179
+ @classmethod
180
+ def get(cls, value):
181
+ return value_to_member[value]
182
+
183
+ someenum = type(
184
+ name,
185
+ (object,),
186
+ {"__members__": __members__, "__init__": __init__, "get": get},
187
+ )
188
+
189
+ # getframe() trick for pickling I don't understand courtesy
190
+ # Python namedtuple()
191
+ try:
192
+ module = sys._getframe(1).f_globals.get("__name__", "__main__")
193
+ except (AttributeError, ValueError):
194
+ pass
195
+ if module is not None:
196
+ someenum.__module__ = module
197
+
198
+ return someenum
@@ -0,0 +1,19 @@
1
+ # testing/suite/__init__.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 .test_cte import * # noqa
8
+ from .test_ddl import * # noqa
9
+ from .test_dialect import * # noqa
10
+ from .test_insert import * # noqa
11
+ from .test_reflection import * # noqa
12
+ from .test_results import * # noqa
13
+ from .test_rowcount import * # noqa
14
+ from .test_select import * # noqa
15
+ from .test_sequence import * # noqa
16
+ from .test_table_via_select import * # noqa
17
+ from .test_types import * # noqa
18
+ from .test_unicode_ddl import * # noqa
19
+ from .test_update_delete import * # noqa
@@ -0,0 +1,237 @@
1
+ # testing/suite/test_cte.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
+
9
+ from .. import fixtures
10
+ from ..assertions import eq_
11
+ from ..schema import Column
12
+ from ..schema import Table
13
+ from ... import column
14
+ from ... import ForeignKey
15
+ from ... import Integer
16
+ from ... import select
17
+ from ... import String
18
+ from ... import testing
19
+ from ... import values
20
+
21
+
22
+ class CTETest(fixtures.TablesTest):
23
+ __sparse_driver_backend__ = True
24
+ __requires__ = ("ctes",)
25
+
26
+ run_inserts = "each"
27
+ run_deletes = "each"
28
+
29
+ @classmethod
30
+ def define_tables(cls, metadata):
31
+ Table(
32
+ "some_table",
33
+ metadata,
34
+ Column("id", Integer, primary_key=True),
35
+ Column("data", String(50)),
36
+ Column("parent_id", ForeignKey("some_table.id")),
37
+ )
38
+
39
+ Table(
40
+ "some_other_table",
41
+ metadata,
42
+ Column("id", Integer, primary_key=True),
43
+ Column("data", String(50)),
44
+ Column("parent_id", Integer),
45
+ )
46
+
47
+ @classmethod
48
+ def insert_data(cls, connection):
49
+ connection.execute(
50
+ cls.tables.some_table.insert(),
51
+ [
52
+ {"id": 1, "data": "d1", "parent_id": None},
53
+ {"id": 2, "data": "d2", "parent_id": 1},
54
+ {"id": 3, "data": "d3", "parent_id": 1},
55
+ {"id": 4, "data": "d4", "parent_id": 3},
56
+ {"id": 5, "data": "d5", "parent_id": 3},
57
+ ],
58
+ )
59
+
60
+ def test_select_nonrecursive_round_trip(self, connection):
61
+ some_table = self.tables.some_table
62
+
63
+ cte = (
64
+ select(some_table)
65
+ .where(some_table.c.data.in_(["d2", "d3", "d4"]))
66
+ .cte("some_cte")
67
+ )
68
+ result = connection.execute(
69
+ select(cte.c.data).where(cte.c.data.in_(["d4", "d5"]))
70
+ )
71
+ eq_(result.fetchall(), [("d4",)])
72
+
73
+ def test_select_recursive_round_trip(self, connection):
74
+ some_table = self.tables.some_table
75
+
76
+ cte = (
77
+ select(some_table)
78
+ .where(some_table.c.data.in_(["d2", "d3", "d4"]))
79
+ .cte("some_cte", recursive=True)
80
+ )
81
+
82
+ cte_alias = cte.alias("c1")
83
+ st1 = some_table.alias()
84
+ # note that SQL Server requires this to be UNION ALL,
85
+ # can't be UNION
86
+ cte = cte.union_all(
87
+ select(st1).where(st1.c.id == cte_alias.c.parent_id)
88
+ )
89
+ result = connection.execute(
90
+ select(cte.c.data)
91
+ .where(cte.c.data != "d2")
92
+ .order_by(cte.c.data.desc())
93
+ )
94
+ eq_(
95
+ result.fetchall(),
96
+ [("d4",), ("d3",), ("d3",), ("d1",), ("d1",), ("d1",)],
97
+ )
98
+
99
+ def test_insert_from_select_round_trip(self, connection):
100
+ some_table = self.tables.some_table
101
+ some_other_table = self.tables.some_other_table
102
+
103
+ cte = (
104
+ select(some_table)
105
+ .where(some_table.c.data.in_(["d2", "d3", "d4"]))
106
+ .cte("some_cte")
107
+ )
108
+ connection.execute(
109
+ some_other_table.insert().from_select(
110
+ ["id", "data", "parent_id"], select(cte)
111
+ )
112
+ )
113
+ eq_(
114
+ connection.execute(
115
+ select(some_other_table).order_by(some_other_table.c.id)
116
+ ).fetchall(),
117
+ [(2, "d2", 1), (3, "d3", 1), (4, "d4", 3)],
118
+ )
119
+
120
+ @testing.requires.ctes_with_update_delete
121
+ @testing.requires.update_from
122
+ def test_update_from_round_trip(self, connection):
123
+ some_table = self.tables.some_table
124
+ some_other_table = self.tables.some_other_table
125
+
126
+ connection.execute(
127
+ some_other_table.insert().from_select(
128
+ ["id", "data", "parent_id"], select(some_table)
129
+ )
130
+ )
131
+
132
+ cte = (
133
+ select(some_table)
134
+ .where(some_table.c.data.in_(["d2", "d3", "d4"]))
135
+ .cte("some_cte")
136
+ )
137
+ connection.execute(
138
+ some_other_table.update()
139
+ .values(parent_id=5)
140
+ .where(some_other_table.c.data == cte.c.data)
141
+ )
142
+ eq_(
143
+ connection.execute(
144
+ select(some_other_table).order_by(some_other_table.c.id)
145
+ ).fetchall(),
146
+ [
147
+ (1, "d1", None),
148
+ (2, "d2", 5),
149
+ (3, "d3", 5),
150
+ (4, "d4", 5),
151
+ (5, "d5", 3),
152
+ ],
153
+ )
154
+
155
+ @testing.requires.ctes_with_update_delete
156
+ @testing.requires.delete_from
157
+ def test_delete_from_round_trip(self, connection):
158
+ some_table = self.tables.some_table
159
+ some_other_table = self.tables.some_other_table
160
+
161
+ connection.execute(
162
+ some_other_table.insert().from_select(
163
+ ["id", "data", "parent_id"], select(some_table)
164
+ )
165
+ )
166
+
167
+ cte = (
168
+ select(some_table)
169
+ .where(some_table.c.data.in_(["d2", "d3", "d4"]))
170
+ .cte("some_cte")
171
+ )
172
+ connection.execute(
173
+ some_other_table.delete().where(
174
+ some_other_table.c.data == cte.c.data
175
+ )
176
+ )
177
+ eq_(
178
+ connection.execute(
179
+ select(some_other_table).order_by(some_other_table.c.id)
180
+ ).fetchall(),
181
+ [(1, "d1", None), (5, "d5", 3)],
182
+ )
183
+
184
+ @testing.requires.ctes_with_update_delete
185
+ def test_delete_scalar_subq_round_trip(self, connection):
186
+ some_table = self.tables.some_table
187
+ some_other_table = self.tables.some_other_table
188
+
189
+ connection.execute(
190
+ some_other_table.insert().from_select(
191
+ ["id", "data", "parent_id"], select(some_table)
192
+ )
193
+ )
194
+
195
+ cte = (
196
+ select(some_table)
197
+ .where(some_table.c.data.in_(["d2", "d3", "d4"]))
198
+ .cte("some_cte")
199
+ )
200
+ connection.execute(
201
+ some_other_table.delete().where(
202
+ some_other_table.c.data
203
+ == select(cte.c.data)
204
+ .where(cte.c.id == some_other_table.c.id)
205
+ .scalar_subquery()
206
+ )
207
+ )
208
+ eq_(
209
+ connection.execute(
210
+ select(some_other_table).order_by(some_other_table.c.id)
211
+ ).fetchall(),
212
+ [(1, "d1", None), (5, "d5", 3)],
213
+ )
214
+
215
+ @testing.variation("values_named", [True, False])
216
+ @testing.variation("cte_named", [True, False])
217
+ @testing.variation("literal_binds", [True, False])
218
+ @testing.requires.ctes_with_values
219
+ def test_values_named_via_cte(
220
+ self, connection, values_named, cte_named, literal_binds
221
+ ):
222
+
223
+ cte1 = (
224
+ values(
225
+ column("col1", String),
226
+ column("col2", Integer),
227
+ literal_binds=bool(literal_binds),
228
+ name="some name" if values_named else None,
229
+ )
230
+ .data([("a", 2), ("b", 3)])
231
+ .cte("cte1" if cte_named else None)
232
+ )
233
+
234
+ stmt = select(cte1)
235
+
236
+ rows = connection.execute(stmt).all()
237
+ eq_(rows, [("a", 2), ("b", 3)])