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,389 @@
1
+ # testing/suite/test_ddl.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
+ import random
10
+
11
+ from . import testing
12
+ from .. import config
13
+ from .. import fixtures
14
+ from .. import util
15
+ from ..assertions import eq_
16
+ from ..assertions import is_false
17
+ from ..assertions import is_true
18
+ from ..config import requirements
19
+ from ..schema import Table
20
+ from ... import CheckConstraint
21
+ from ... import Column
22
+ from ... import ForeignKeyConstraint
23
+ from ... import Index
24
+ from ... import inspect
25
+ from ... import Integer
26
+ from ... import schema
27
+ from ... import String
28
+ from ... import UniqueConstraint
29
+
30
+
31
+ class TableDDLTest(fixtures.TestBase):
32
+ __sparse_driver_backend__ = True
33
+
34
+ def _simple_fixture(self, schema=None):
35
+ return Table(
36
+ "test_table",
37
+ self.metadata,
38
+ Column("id", Integer, primary_key=True, autoincrement=False),
39
+ Column("data", String(50)),
40
+ schema=schema,
41
+ )
42
+
43
+ def _underscore_fixture(self):
44
+ return Table(
45
+ "_test_table",
46
+ self.metadata,
47
+ Column("id", Integer, primary_key=True, autoincrement=False),
48
+ Column("_data", String(50)),
49
+ )
50
+
51
+ def _table_index_fixture(self, schema=None):
52
+ table = self._simple_fixture(schema=schema)
53
+ idx = Index("test_index", table.c.data)
54
+ return table, idx
55
+
56
+ def _simple_roundtrip(self, table):
57
+ with config.db.begin() as conn:
58
+ conn.execute(table.insert().values((1, "some data")))
59
+ result = conn.execute(table.select())
60
+ eq_(result.first(), (1, "some data"))
61
+
62
+ @requirements.create_table
63
+ @util.provide_metadata
64
+ def test_create_table(self):
65
+ table = self._simple_fixture()
66
+ table.create(config.db, checkfirst=False)
67
+ self._simple_roundtrip(table)
68
+
69
+ @requirements.create_table
70
+ @requirements.schemas
71
+ @util.provide_metadata
72
+ def test_create_table_schema(self):
73
+ table = self._simple_fixture(schema=config.test_schema)
74
+ table.create(config.db, checkfirst=False)
75
+ self._simple_roundtrip(table)
76
+
77
+ @requirements.drop_table
78
+ @util.provide_metadata
79
+ def test_drop_table(self):
80
+ table = self._simple_fixture()
81
+ table.create(config.db, checkfirst=False)
82
+ table.drop(config.db, checkfirst=False)
83
+
84
+ @requirements.create_table
85
+ @util.provide_metadata
86
+ def test_underscore_names(self):
87
+ table = self._underscore_fixture()
88
+ table.create(config.db, checkfirst=False)
89
+ self._simple_roundtrip(table)
90
+
91
+ @requirements.comment_reflection
92
+ @util.provide_metadata
93
+ def test_add_table_comment(self, connection):
94
+ table = self._simple_fixture()
95
+ table.create(connection, checkfirst=False)
96
+ table.comment = "a comment"
97
+ connection.execute(schema.SetTableComment(table))
98
+ eq_(
99
+ inspect(connection).get_table_comment("test_table"),
100
+ {"text": "a comment"},
101
+ )
102
+
103
+ @requirements.comment_reflection
104
+ @util.provide_metadata
105
+ def test_drop_table_comment(self, connection):
106
+ table = self._simple_fixture()
107
+ table.create(connection, checkfirst=False)
108
+ table.comment = "a comment"
109
+ connection.execute(schema.SetTableComment(table))
110
+ connection.execute(schema.DropTableComment(table))
111
+ eq_(
112
+ inspect(connection).get_table_comment("test_table"), {"text": None}
113
+ )
114
+
115
+ @requirements.table_ddl_if_exists
116
+ @util.provide_metadata
117
+ def test_create_table_if_not_exists(self, connection):
118
+ table = self._simple_fixture()
119
+
120
+ connection.execute(schema.CreateTable(table, if_not_exists=True))
121
+
122
+ is_true(inspect(connection).has_table("test_table"))
123
+ connection.execute(schema.CreateTable(table, if_not_exists=True))
124
+
125
+ @requirements.index_ddl_if_exists
126
+ @util.provide_metadata
127
+ def test_create_index_if_not_exists(self, connection):
128
+ table, idx = self._table_index_fixture()
129
+
130
+ connection.execute(schema.CreateTable(table, if_not_exists=True))
131
+ is_true(inspect(connection).has_table("test_table"))
132
+ is_false(
133
+ "test_index"
134
+ in [
135
+ ix["name"]
136
+ for ix in inspect(connection).get_indexes("test_table")
137
+ ]
138
+ )
139
+
140
+ connection.execute(schema.CreateIndex(idx, if_not_exists=True))
141
+
142
+ is_true(
143
+ "test_index"
144
+ in [
145
+ ix["name"]
146
+ for ix in inspect(connection).get_indexes("test_table")
147
+ ]
148
+ )
149
+
150
+ connection.execute(schema.CreateIndex(idx, if_not_exists=True))
151
+
152
+ @requirements.table_ddl_if_exists
153
+ @util.provide_metadata
154
+ def test_drop_table_if_exists(self, connection):
155
+ table = self._simple_fixture()
156
+
157
+ table.create(connection)
158
+
159
+ is_true(inspect(connection).has_table("test_table"))
160
+
161
+ connection.execute(schema.DropTable(table, if_exists=True))
162
+
163
+ is_false(inspect(connection).has_table("test_table"))
164
+
165
+ connection.execute(schema.DropTable(table, if_exists=True))
166
+
167
+ @requirements.index_ddl_if_exists
168
+ @util.provide_metadata
169
+ def test_drop_index_if_exists(self, connection):
170
+ table, idx = self._table_index_fixture()
171
+
172
+ table.create(connection)
173
+
174
+ is_true(
175
+ "test_index"
176
+ in [
177
+ ix["name"]
178
+ for ix in inspect(connection).get_indexes("test_table")
179
+ ]
180
+ )
181
+
182
+ connection.execute(schema.DropIndex(idx, if_exists=True))
183
+
184
+ is_false(
185
+ "test_index"
186
+ in [
187
+ ix["name"]
188
+ for ix in inspect(connection).get_indexes("test_table")
189
+ ]
190
+ )
191
+
192
+ connection.execute(schema.DropIndex(idx, if_exists=True))
193
+
194
+
195
+ class FutureTableDDLTest(fixtures.FutureEngineMixin, TableDDLTest):
196
+ pass
197
+
198
+
199
+ class LongNameBlowoutTest(fixtures.TestBase):
200
+ """test the creation of a variety of DDL structures and ensure
201
+ label length limits pass on backends
202
+
203
+ """
204
+
205
+ __sparse_driver_backend__ = True
206
+
207
+ def fk(self, metadata, connection):
208
+ convention = {
209
+ "fk": "foreign_key_%(table_name)s_"
210
+ "%(column_0_N_name)s_"
211
+ "%(referred_table_name)s_"
212
+ + (
213
+ "_".join(
214
+ "".join(random.choice("abcdef") for j in range(20))
215
+ for i in range(10)
216
+ )
217
+ ),
218
+ }
219
+ metadata.naming_convention = convention
220
+
221
+ Table(
222
+ "a_things_with_stuff",
223
+ metadata,
224
+ Column("id_long_column_name", Integer, primary_key=True),
225
+ test_needs_fk=True,
226
+ )
227
+
228
+ cons = ForeignKeyConstraint(
229
+ ["aid"], ["a_things_with_stuff.id_long_column_name"]
230
+ )
231
+ Table(
232
+ "b_related_things_of_value",
233
+ metadata,
234
+ Column(
235
+ "aid",
236
+ ),
237
+ cons,
238
+ test_needs_fk=True,
239
+ )
240
+ actual_name = cons.name
241
+
242
+ metadata.create_all(connection)
243
+
244
+ if testing.requires.foreign_key_constraint_name_reflection.enabled:
245
+ insp = inspect(connection)
246
+ fks = insp.get_foreign_keys("b_related_things_of_value")
247
+ reflected_name = fks[0]["name"]
248
+
249
+ return actual_name, reflected_name
250
+ else:
251
+ return actual_name, None
252
+
253
+ def pk(self, metadata, connection):
254
+ convention = {
255
+ "pk": "primary_key_%(table_name)s_"
256
+ "%(column_0_N_name)s"
257
+ + (
258
+ "_".join(
259
+ "".join(random.choice("abcdef") for j in range(30))
260
+ for i in range(10)
261
+ )
262
+ ),
263
+ }
264
+ metadata.naming_convention = convention
265
+
266
+ a = Table(
267
+ "a_things_with_stuff",
268
+ metadata,
269
+ Column("id_long_column_name", Integer, primary_key=True),
270
+ Column("id_another_long_name", Integer, primary_key=True),
271
+ )
272
+ cons = a.primary_key
273
+ actual_name = cons.name
274
+
275
+ metadata.create_all(connection)
276
+ insp = inspect(connection)
277
+ pk = insp.get_pk_constraint("a_things_with_stuff")
278
+ reflected_name = pk["name"]
279
+ return actual_name, reflected_name
280
+
281
+ def ix(self, metadata, connection):
282
+ convention = {
283
+ "ix": "index_%(table_name)s_"
284
+ "%(column_0_N_name)s"
285
+ + (
286
+ "_".join(
287
+ "".join(random.choice("abcdef") for j in range(30))
288
+ for i in range(10)
289
+ )
290
+ ),
291
+ }
292
+ metadata.naming_convention = convention
293
+
294
+ a = Table(
295
+ "a_things_with_stuff",
296
+ metadata,
297
+ Column("id_long_column_name", Integer, primary_key=True),
298
+ Column("id_another_long_name", Integer),
299
+ )
300
+ cons = Index(None, a.c.id_long_column_name, a.c.id_another_long_name)
301
+ actual_name = cons.name
302
+
303
+ metadata.create_all(connection)
304
+ insp = inspect(connection)
305
+ ix = insp.get_indexes("a_things_with_stuff")
306
+ reflected_name = ix[0]["name"]
307
+ return actual_name, reflected_name
308
+
309
+ def uq(self, metadata, connection):
310
+ convention = {
311
+ "uq": "unique_constraint_%(table_name)s_"
312
+ "%(column_0_N_name)s"
313
+ + (
314
+ "_".join(
315
+ "".join(random.choice("abcdef") for j in range(30))
316
+ for i in range(10)
317
+ )
318
+ ),
319
+ }
320
+ metadata.naming_convention = convention
321
+
322
+ cons = UniqueConstraint("id_long_column_name", "id_another_long_name")
323
+ Table(
324
+ "a_things_with_stuff",
325
+ metadata,
326
+ Column("id_long_column_name", Integer, primary_key=True),
327
+ Column("id_another_long_name", Integer),
328
+ cons,
329
+ )
330
+ actual_name = cons.name
331
+
332
+ metadata.create_all(connection)
333
+ insp = inspect(connection)
334
+ uq = insp.get_unique_constraints("a_things_with_stuff")
335
+ reflected_name = uq[0]["name"]
336
+ return actual_name, reflected_name
337
+
338
+ def ck(self, metadata, connection):
339
+ convention = {
340
+ "ck": "check_constraint_%(table_name)s"
341
+ + (
342
+ "_".join(
343
+ "".join(random.choice("abcdef") for j in range(30))
344
+ for i in range(10)
345
+ )
346
+ ),
347
+ }
348
+ metadata.naming_convention = convention
349
+
350
+ cons = CheckConstraint("some_long_column_name > 5")
351
+ Table(
352
+ "a_things_with_stuff",
353
+ metadata,
354
+ Column("id_long_column_name", Integer, primary_key=True),
355
+ Column("some_long_column_name", Integer),
356
+ cons,
357
+ )
358
+ actual_name = cons.name
359
+
360
+ metadata.create_all(connection)
361
+ insp = inspect(connection)
362
+ ck = insp.get_check_constraints("a_things_with_stuff")
363
+ reflected_name = ck[0]["name"]
364
+ return actual_name, reflected_name
365
+
366
+ @testing.combinations(
367
+ ("fk",),
368
+ ("pk",),
369
+ ("ix",),
370
+ ("ck", testing.requires.check_constraint_reflection.as_skips()),
371
+ ("uq", testing.requires.unique_constraint_reflection.as_skips()),
372
+ argnames="type_",
373
+ )
374
+ def test_long_convention_name(self, type_, metadata, connection):
375
+ actual_name, reflected_name = getattr(self, type_)(
376
+ metadata, connection
377
+ )
378
+
379
+ assert len(actual_name) > 255
380
+
381
+ if reflected_name is not None:
382
+ overlap = actual_name[0 : len(reflected_name)]
383
+ if len(overlap) < len(actual_name):
384
+ eq_(overlap[0:-5], reflected_name[0 : len(overlap) - 5])
385
+ else:
386
+ eq_(overlap, reflected_name)
387
+
388
+
389
+ __all__ = ("TableDDLTest", "FutureTableDDLTest", "LongNameBlowoutTest")
@@ -0,0 +1,153 @@
1
+ # testing/suite/test_deprecations.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 Integer
14
+ from ... import select
15
+ from ... import testing
16
+ from ... import union
17
+
18
+
19
+ class DeprecatedCompoundSelectTest(fixtures.TablesTest):
20
+ __backend__ = True
21
+
22
+ @classmethod
23
+ def define_tables(cls, metadata):
24
+ Table(
25
+ "some_table",
26
+ metadata,
27
+ Column("id", Integer, primary_key=True),
28
+ Column("x", Integer),
29
+ Column("y", Integer),
30
+ )
31
+
32
+ @classmethod
33
+ def insert_data(cls, connection):
34
+ connection.execute(
35
+ cls.tables.some_table.insert(),
36
+ [
37
+ {"id": 1, "x": 1, "y": 2},
38
+ {"id": 2, "x": 2, "y": 3},
39
+ {"id": 3, "x": 3, "y": 4},
40
+ {"id": 4, "x": 4, "y": 5},
41
+ ],
42
+ )
43
+
44
+ def _assert_result(self, conn, select, result, params=()):
45
+ eq_(conn.execute(select, params).fetchall(), result)
46
+
47
+ def test_plain_union(self, connection):
48
+ table = self.tables.some_table
49
+ s1 = select(table).where(table.c.id == 2)
50
+ s2 = select(table).where(table.c.id == 3)
51
+
52
+ u1 = union(s1, s2)
53
+ with testing.expect_deprecated(
54
+ "The SelectBase.c and SelectBase.columns "
55
+ "attributes are deprecated"
56
+ ):
57
+ self._assert_result(
58
+ connection, u1.order_by(u1.c.id), [(2, 2, 3), (3, 3, 4)]
59
+ )
60
+
61
+ # note we've had to remove one use case entirely, which is this
62
+ # one. the Select gets its FROMS from the WHERE clause and the
63
+ # columns clause, but not the ORDER BY, which means the old ".c" system
64
+ # allowed you to "order_by(s.c.foo)" to get an unnamed column in the
65
+ # ORDER BY without adding the SELECT into the FROM and breaking the
66
+ # query. Users will have to adjust for this use case if they were doing
67
+ # it before.
68
+ def _dont_test_select_from_plain_union(self, connection):
69
+ table = self.tables.some_table
70
+ s1 = select(table).where(table.c.id == 2)
71
+ s2 = select(table).where(table.c.id == 3)
72
+
73
+ u1 = union(s1, s2).alias().select()
74
+ with testing.expect_deprecated(
75
+ "The SelectBase.c and SelectBase.columns "
76
+ "attributes are deprecated"
77
+ ):
78
+ self._assert_result(
79
+ connection, u1.order_by(u1.c.id), [(2, 2, 3), (3, 3, 4)]
80
+ )
81
+
82
+ @testing.requires.order_by_col_from_union
83
+ @testing.requires.parens_in_union_contained_select_w_limit_offset
84
+ def test_limit_offset_selectable_in_unions(self, connection):
85
+ table = self.tables.some_table
86
+ s1 = select(table).where(table.c.id == 2).limit(1).order_by(table.c.id)
87
+ s2 = select(table).where(table.c.id == 3).limit(1).order_by(table.c.id)
88
+
89
+ u1 = union(s1, s2).limit(2)
90
+ with testing.expect_deprecated(
91
+ "The SelectBase.c and SelectBase.columns "
92
+ "attributes are deprecated"
93
+ ):
94
+ self._assert_result(
95
+ connection, u1.order_by(u1.c.id), [(2, 2, 3), (3, 3, 4)]
96
+ )
97
+
98
+ @testing.requires.parens_in_union_contained_select_wo_limit_offset
99
+ def test_order_by_selectable_in_unions(self, connection):
100
+ table = self.tables.some_table
101
+ s1 = select(table).where(table.c.id == 2).order_by(table.c.id)
102
+ s2 = select(table).where(table.c.id == 3).order_by(table.c.id)
103
+
104
+ u1 = union(s1, s2).limit(2)
105
+ with testing.expect_deprecated(
106
+ "The SelectBase.c and SelectBase.columns "
107
+ "attributes are deprecated"
108
+ ):
109
+ self._assert_result(
110
+ connection, u1.order_by(u1.c.id), [(2, 2, 3), (3, 3, 4)]
111
+ )
112
+
113
+ def test_distinct_selectable_in_unions(self, connection):
114
+ table = self.tables.some_table
115
+ s1 = select(table).where(table.c.id == 2).distinct()
116
+ s2 = select(table).where(table.c.id == 3).distinct()
117
+
118
+ u1 = union(s1, s2).limit(2)
119
+ with testing.expect_deprecated(
120
+ "The SelectBase.c and SelectBase.columns "
121
+ "attributes are deprecated"
122
+ ):
123
+ self._assert_result(
124
+ connection, u1.order_by(u1.c.id), [(2, 2, 3), (3, 3, 4)]
125
+ )
126
+
127
+ def test_limit_offset_aliased_selectable_in_unions(self, connection):
128
+ table = self.tables.some_table
129
+ s1 = (
130
+ select(table)
131
+ .where(table.c.id == 2)
132
+ .limit(1)
133
+ .order_by(table.c.id)
134
+ .alias()
135
+ .select()
136
+ )
137
+ s2 = (
138
+ select(table)
139
+ .where(table.c.id == 3)
140
+ .limit(1)
141
+ .order_by(table.c.id)
142
+ .alias()
143
+ .select()
144
+ )
145
+
146
+ u1 = union(s1, s2).limit(2)
147
+ with testing.expect_deprecated(
148
+ "The SelectBase.c and SelectBase.columns "
149
+ "attributes are deprecated"
150
+ ):
151
+ self._assert_result(
152
+ connection, u1.order_by(u1.c.id), [(2, 2, 3), (3, 3, 4)]
153
+ )