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,285 @@
1
+ # dialects/mssql/information_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 ... import cast
10
+ from ... import Column
11
+ from ... import MetaData
12
+ from ... import Table
13
+ from ...ext.compiler import compiles
14
+ from ...sql import expression
15
+ from ...types import Boolean
16
+ from ...types import Integer
17
+ from ...types import Numeric
18
+ from ...types import NVARCHAR
19
+ from ...types import String
20
+ from ...types import TypeDecorator
21
+ from ...types import Unicode
22
+
23
+
24
+ ischema = MetaData()
25
+
26
+
27
+ class CoerceUnicode(TypeDecorator):
28
+ impl = Unicode
29
+ cache_ok = True
30
+
31
+ def bind_expression(self, bindvalue):
32
+ return _cast_on_2005(bindvalue)
33
+
34
+
35
+ class _cast_on_2005(expression.ColumnElement):
36
+ def __init__(self, bindvalue):
37
+ self.bindvalue = bindvalue
38
+
39
+
40
+ @compiles(_cast_on_2005)
41
+ def _compile(element, compiler, **kw):
42
+ from . import base
43
+
44
+ if (
45
+ compiler.dialect.server_version_info is None
46
+ or compiler.dialect.server_version_info < base.MS_2005_VERSION
47
+ ):
48
+ return compiler.process(element.bindvalue, **kw)
49
+ else:
50
+ return compiler.process(cast(element.bindvalue, Unicode), **kw)
51
+
52
+
53
+ schemata = Table(
54
+ "SCHEMATA",
55
+ ischema,
56
+ Column("CATALOG_NAME", CoerceUnicode, key="catalog_name"),
57
+ Column("SCHEMA_NAME", CoerceUnicode, key="schema_name"),
58
+ Column("SCHEMA_OWNER", CoerceUnicode, key="schema_owner"),
59
+ schema="INFORMATION_SCHEMA",
60
+ )
61
+
62
+ tables = Table(
63
+ "TABLES",
64
+ ischema,
65
+ Column("TABLE_CATALOG", CoerceUnicode, key="table_catalog"),
66
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
67
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
68
+ Column("TABLE_TYPE", CoerceUnicode, key="table_type"),
69
+ schema="INFORMATION_SCHEMA",
70
+ )
71
+
72
+ columns = Table(
73
+ "COLUMNS",
74
+ ischema,
75
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
76
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
77
+ Column("COLUMN_NAME", CoerceUnicode, key="column_name"),
78
+ Column("IS_NULLABLE", Integer, key="is_nullable"),
79
+ Column("DATA_TYPE", String, key="data_type"),
80
+ Column("ORDINAL_POSITION", Integer, key="ordinal_position"),
81
+ Column(
82
+ "CHARACTER_MAXIMUM_LENGTH", Integer, key="character_maximum_length"
83
+ ),
84
+ Column("NUMERIC_PRECISION", Integer, key="numeric_precision"),
85
+ Column("NUMERIC_SCALE", Integer, key="numeric_scale"),
86
+ Column("COLUMN_DEFAULT", Integer, key="column_default"),
87
+ Column("COLLATION_NAME", String, key="collation_name"),
88
+ schema="INFORMATION_SCHEMA",
89
+ )
90
+
91
+ sys_columns = Table(
92
+ "columns",
93
+ ischema,
94
+ Column("object_id", Integer),
95
+ Column("name", CoerceUnicode),
96
+ Column("column_id", Integer),
97
+ Column("default_object_id", Integer),
98
+ Column("user_type_id", Integer),
99
+ Column("is_nullable", Integer),
100
+ Column("ordinal_position", Integer),
101
+ Column("max_length", Integer),
102
+ Column("precision", Integer),
103
+ Column("scale", Integer),
104
+ Column("collation_name", String),
105
+ schema="sys",
106
+ )
107
+
108
+ sys_types = Table(
109
+ "types",
110
+ ischema,
111
+ Column("name", CoerceUnicode, key="name"),
112
+ Column("system_type_id", Integer, key="system_type_id"),
113
+ Column("user_type_id", Integer, key="user_type_id"),
114
+ Column("schema_id", Integer, key="schema_id"),
115
+ Column("max_length", Integer, key="max_length"),
116
+ Column("precision", Integer, key="precision"),
117
+ Column("scale", Integer, key="scale"),
118
+ Column("collation_name", CoerceUnicode, key="collation_name"),
119
+ Column("is_nullable", Boolean, key="is_nullable"),
120
+ Column("is_user_defined", Boolean, key="is_user_defined"),
121
+ Column("is_assembly_type", Boolean, key="is_assembly_type"),
122
+ Column("default_object_id", Integer, key="default_object_id"),
123
+ Column("rule_object_id", Integer, key="rule_object_id"),
124
+ Column("is_table_type", Boolean, key="is_table_type"),
125
+ schema="sys",
126
+ )
127
+
128
+ constraints = Table(
129
+ "TABLE_CONSTRAINTS",
130
+ ischema,
131
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
132
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
133
+ Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
134
+ Column("CONSTRAINT_TYPE", CoerceUnicode, key="constraint_type"),
135
+ schema="INFORMATION_SCHEMA",
136
+ )
137
+
138
+ sys_default_constraints = Table(
139
+ "default_constraints",
140
+ ischema,
141
+ Column("object_id", Integer),
142
+ Column("name", CoerceUnicode),
143
+ Column("schema_id", Integer),
144
+ Column("parent_column_id", Integer),
145
+ Column("definition", CoerceUnicode),
146
+ schema="sys",
147
+ )
148
+
149
+ column_constraints = Table(
150
+ "CONSTRAINT_COLUMN_USAGE",
151
+ ischema,
152
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
153
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
154
+ Column("COLUMN_NAME", CoerceUnicode, key="column_name"),
155
+ Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
156
+ schema="INFORMATION_SCHEMA",
157
+ )
158
+
159
+ key_constraints = Table(
160
+ "KEY_COLUMN_USAGE",
161
+ ischema,
162
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
163
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
164
+ Column("COLUMN_NAME", CoerceUnicode, key="column_name"),
165
+ Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
166
+ Column("CONSTRAINT_SCHEMA", CoerceUnicode, key="constraint_schema"),
167
+ Column("ORDINAL_POSITION", Integer, key="ordinal_position"),
168
+ schema="INFORMATION_SCHEMA",
169
+ )
170
+
171
+ ref_constraints = Table(
172
+ "REFERENTIAL_CONSTRAINTS",
173
+ ischema,
174
+ Column("CONSTRAINT_CATALOG", CoerceUnicode, key="constraint_catalog"),
175
+ Column("CONSTRAINT_SCHEMA", CoerceUnicode, key="constraint_schema"),
176
+ Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
177
+ # TODO: is CATLOG misspelled ?
178
+ Column(
179
+ "UNIQUE_CONSTRAINT_CATLOG",
180
+ CoerceUnicode,
181
+ key="unique_constraint_catalog",
182
+ ),
183
+ Column(
184
+ "UNIQUE_CONSTRAINT_SCHEMA",
185
+ CoerceUnicode,
186
+ key="unique_constraint_schema",
187
+ ),
188
+ Column(
189
+ "UNIQUE_CONSTRAINT_NAME", CoerceUnicode, key="unique_constraint_name"
190
+ ),
191
+ Column("MATCH_OPTION", String, key="match_option"),
192
+ Column("UPDATE_RULE", String, key="update_rule"),
193
+ Column("DELETE_RULE", String, key="delete_rule"),
194
+ schema="INFORMATION_SCHEMA",
195
+ )
196
+
197
+ views = Table(
198
+ "VIEWS",
199
+ ischema,
200
+ Column("TABLE_CATALOG", CoerceUnicode, key="table_catalog"),
201
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
202
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
203
+ Column("VIEW_DEFINITION", CoerceUnicode, key="view_definition"),
204
+ Column("CHECK_OPTION", String, key="check_option"),
205
+ Column("IS_UPDATABLE", String, key="is_updatable"),
206
+ schema="INFORMATION_SCHEMA",
207
+ )
208
+
209
+ computed_columns = Table(
210
+ "computed_columns",
211
+ ischema,
212
+ Column("object_id", Integer),
213
+ Column("name", CoerceUnicode),
214
+ Column("column_id", Integer),
215
+ Column("is_computed", Boolean),
216
+ Column("is_persisted", Boolean),
217
+ Column("definition", CoerceUnicode),
218
+ schema="sys",
219
+ )
220
+
221
+ sequences = Table(
222
+ "SEQUENCES",
223
+ ischema,
224
+ Column("SEQUENCE_CATALOG", CoerceUnicode, key="sequence_catalog"),
225
+ Column("SEQUENCE_SCHEMA", CoerceUnicode, key="sequence_schema"),
226
+ Column("SEQUENCE_NAME", CoerceUnicode, key="sequence_name"),
227
+ schema="INFORMATION_SCHEMA",
228
+ )
229
+
230
+
231
+ class NumericSqlVariant(TypeDecorator):
232
+ r"""This type casts sql_variant columns in the identity_columns view
233
+ to numeric. This is required because:
234
+
235
+ * pyodbc does not support sql_variant
236
+ * pymssql under python 2 return the byte representation of the number,
237
+ int 1 is returned as "\x01\x00\x00\x00". On python 3 it returns the
238
+ correct value as string.
239
+ """
240
+
241
+ impl = Unicode
242
+ cache_ok = True
243
+
244
+ def column_expression(self, colexpr):
245
+ return cast(colexpr, Numeric(38, 0))
246
+
247
+
248
+ identity_columns = Table(
249
+ "identity_columns",
250
+ ischema,
251
+ Column("object_id", Integer),
252
+ Column("name", CoerceUnicode),
253
+ Column("column_id", Integer),
254
+ Column("is_identity", Boolean),
255
+ Column("seed_value", NumericSqlVariant),
256
+ Column("increment_value", NumericSqlVariant),
257
+ Column("last_value", NumericSqlVariant),
258
+ Column("is_not_for_replication", Boolean),
259
+ schema="sys",
260
+ )
261
+
262
+
263
+ class NVarcharSqlVariant(TypeDecorator):
264
+ """This type casts sql_variant columns in the extended_properties view
265
+ to nvarchar. This is required because pyodbc does not support sql_variant
266
+ """
267
+
268
+ impl = Unicode
269
+ cache_ok = True
270
+
271
+ def column_expression(self, colexpr):
272
+ return cast(colexpr, NVARCHAR)
273
+
274
+
275
+ extended_properties = Table(
276
+ "extended_properties",
277
+ ischema,
278
+ Column("class", Integer), # TINYINT
279
+ Column("class_desc", CoerceUnicode),
280
+ Column("major_id", Integer),
281
+ Column("minor_id", Integer),
282
+ Column("name", CoerceUnicode),
283
+ Column("value", NVarcharSqlVariant),
284
+ schema="sys",
285
+ )
@@ -0,0 +1,140 @@
1
+ # dialects/mssql/json.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+ from typing import TYPE_CHECKING
11
+
12
+ from ... import types as sqltypes
13
+ from ...sql.sqltypes import _T_JSON
14
+
15
+ if TYPE_CHECKING:
16
+ from ...engine.interfaces import Dialect
17
+ from ...sql.type_api import _BindProcessorType
18
+ from ...sql.type_api import _LiteralProcessorType
19
+
20
+ # technically, all the dialect-specific datatypes that don't have any special
21
+ # behaviors would be private with names like _MSJson. However, we haven't been
22
+ # doing this for mysql.JSON or sqlite.JSON which both have JSON / JSONIndexType
23
+ # / JSONPathType in their json.py files, so keep consistent with that
24
+ # sub-convention for now. A future change can update them all to be
25
+ # package-private at once.
26
+
27
+
28
+ class JSON(sqltypes.JSON[_T_JSON]):
29
+ """MSSQL JSON type.
30
+
31
+ MSSQL supports JSON-formatted data as of SQL Server 2016.
32
+
33
+ The :class:`_mssql.JSON` datatype at the DDL level will represent the
34
+ datatype as ``NVARCHAR(max)``, but provides for JSON-level comparison
35
+ functions as well as Python coercion behavior.
36
+
37
+ :class:`_mssql.JSON` is used automatically whenever the base
38
+ :class:`_types.JSON` datatype is used against a SQL Server backend.
39
+
40
+ .. seealso::
41
+
42
+ :class:`_types.JSON` - main documentation for the generic
43
+ cross-platform JSON datatype.
44
+
45
+ The :class:`_mssql.JSON` type supports persistence of JSON values
46
+ as well as the core index operations provided by :class:`_types.JSON`
47
+ datatype, by adapting the operations to render the ``JSON_VALUE``
48
+ or ``JSON_QUERY`` functions at the database level.
49
+
50
+ The SQL Server :class:`_mssql.JSON` type necessarily makes use of the
51
+ ``JSON_QUERY`` and ``JSON_VALUE`` functions when querying for elements
52
+ of a JSON object. These two functions have a major restriction in that
53
+ they are **mutually exclusive** based on the type of object to be returned.
54
+ The ``JSON_QUERY`` function **only** returns a JSON dictionary or list,
55
+ but not an individual string, numeric, or boolean element; the
56
+ ``JSON_VALUE`` function **only** returns an individual string, numeric,
57
+ or boolean element. **both functions either return NULL or raise
58
+ an error if they are not used against the correct expected value**.
59
+
60
+ To handle this awkward requirement, indexed access rules are as follows:
61
+
62
+ 1. When extracting a sub element from a JSON that is itself a JSON
63
+ dictionary or list, the :meth:`_types.JSON.Comparator.as_json` accessor
64
+ should be used::
65
+
66
+ stmt = select(data_table.c.data["some key"].as_json()).where(
67
+ data_table.c.data["some key"].as_json() == {"sub": "structure"}
68
+ )
69
+
70
+ 2. When extracting a sub element from a JSON that is a plain boolean,
71
+ string, integer, or float, use the appropriate method among
72
+ :meth:`_types.JSON.Comparator.as_boolean`,
73
+ :meth:`_types.JSON.Comparator.as_string`,
74
+ :meth:`_types.JSON.Comparator.as_integer`,
75
+ :meth:`_types.JSON.Comparator.as_float`::
76
+
77
+ stmt = select(data_table.c.data["some key"].as_string()).where(
78
+ data_table.c.data["some key"].as_string() == "some string"
79
+ )
80
+
81
+ .. versionadded:: 1.4
82
+
83
+
84
+ """
85
+
86
+ # note there was a result processor here that was looking for "number",
87
+ # but none of the tests seem to exercise it.
88
+
89
+
90
+ # Note: these objects currently match exactly those of MySQL, however since
91
+ # these are not generalizable to all JSON implementations, remain separately
92
+ # implemented for each dialect.
93
+ class _FormatTypeMixin:
94
+ def _format_value(self, value: Any) -> str:
95
+ raise NotImplementedError()
96
+
97
+ def bind_processor(self, dialect: Dialect) -> _BindProcessorType[Any]:
98
+ super_proc = self.string_bind_processor(dialect) # type: ignore[attr-defined] # noqa: E501
99
+
100
+ def process(value: Any) -> Any:
101
+ value = self._format_value(value)
102
+ if super_proc:
103
+ value = super_proc(value)
104
+ return value
105
+
106
+ return process
107
+
108
+ def literal_processor(
109
+ self, dialect: Dialect
110
+ ) -> _LiteralProcessorType[Any]:
111
+ super_proc = self.string_literal_processor(dialect) # type: ignore[attr-defined] # noqa: E501
112
+
113
+ def process(value: Any) -> str:
114
+ value = self._format_value(value)
115
+ if super_proc:
116
+ value = super_proc(value)
117
+ return value # type: ignore[no-any-return]
118
+
119
+ return process
120
+
121
+
122
+ class JSONIndexType(_FormatTypeMixin, sqltypes.JSON.JSONIndexType):
123
+ def _format_value(self, value: Any) -> str:
124
+ if isinstance(value, int):
125
+ formatted_value = "$[%s]" % value
126
+ else:
127
+ formatted_value = '$."%s"' % value
128
+ return formatted_value
129
+
130
+
131
+ class JSONPathType(_FormatTypeMixin, sqltypes.JSON.JSONPathType):
132
+ def _format_value(self, value: Any) -> str:
133
+ return "$%s" % (
134
+ "".join(
135
+ [
136
+ "[%s]" % elem if isinstance(elem, int) else '."%s"' % elem
137
+ for elem in value
138
+ ]
139
+ )
140
+ )
@@ -0,0 +1,220 @@
1
+ # dialects/mssql/mssqlpython.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
+ """
10
+ .. dialect:: mssql+mssqlpython
11
+ :name: mssqlpython
12
+ :dbapi: mssql-python
13
+ :connectstring: mssql+mssqlpython://<username>:<password>@<host>:<port>/<dbname>
14
+ :url: https://github.com/microsoft/mssql-python
15
+
16
+ mssql-python is a driver for Microsoft SQL Server produced by Microsoft.
17
+
18
+ .. versionadded:: 2.1.0b2
19
+
20
+
21
+ The driver is generally similar to pyodbc in most aspects as it is based
22
+ on the same ODBC framework.
23
+
24
+ Connection Strings
25
+ ------------------
26
+
27
+ Examples of connecting with the mssql-python driver::
28
+
29
+ from sqlalchemy import create_engine
30
+
31
+ # Basic connection
32
+ engine = create_engine(
33
+ "mssql+mssqlpython://user:password@hostname/database"
34
+ )
35
+
36
+ # With Windows Authentication
37
+ engine = create_engine(
38
+ "mssql+mssqlpython://hostname/database?authentication=ActiveDirectoryIntegrated"
39
+ )
40
+
41
+ """ # noqa
42
+
43
+ from __future__ import annotations
44
+
45
+ import re
46
+ from typing import Any
47
+ from typing import Dict
48
+ from typing import List
49
+ from typing import Optional
50
+ from typing import TYPE_CHECKING
51
+ from typing import Union
52
+
53
+ from .base import MSDialect
54
+ from .pyodbc import _ms_numeric_pyodbc
55
+ from ... import util
56
+ from ...sql import sqltypes
57
+
58
+ if TYPE_CHECKING:
59
+ from ... import pool
60
+ from ...engine import interfaces
61
+ from ...engine.interfaces import ConnectArgsType
62
+ from ...engine.interfaces import DBAPIModule
63
+ from ...engine.interfaces import IsolationLevel
64
+ from ...engine.interfaces import URL
65
+
66
+
67
+ class _MSNumeric_mssqlpython(_ms_numeric_pyodbc, sqltypes.Numeric):
68
+ pass
69
+
70
+
71
+ class _MSFloat_mssqlpython(_ms_numeric_pyodbc, sqltypes.Float):
72
+ pass
73
+
74
+
75
+ class MSDialect_mssqlpython(MSDialect):
76
+ driver = "mssqlpython"
77
+ supports_statement_cache = True
78
+
79
+ supports_sane_rowcount_returning = True
80
+ supports_sane_multi_rowcount = True
81
+ supports_native_uuid = True
82
+ scope_identity_must_be_embedded = True
83
+
84
+ supports_native_decimal = True
85
+
86
+ # used by pyodbc _ms_numeric_pyodbc class
87
+ _need_decimal_fix = True
88
+
89
+ colspecs = util.update_copy(
90
+ MSDialect.colspecs,
91
+ {
92
+ sqltypes.Numeric: _MSNumeric_mssqlpython,
93
+ sqltypes.Float: _MSFloat_mssqlpython,
94
+ },
95
+ )
96
+
97
+ def __init__(self, enable_pooling=False, **kw):
98
+ super().__init__(**kw)
99
+ if not enable_pooling and self.dbapi is not None:
100
+ self.loaded_dbapi.pooling(enabled=False)
101
+
102
+ @classmethod
103
+ def import_dbapi(cls) -> DBAPIModule:
104
+ return __import__("mssql_python")
105
+
106
+ def create_connect_args(self, url: URL) -> ConnectArgsType:
107
+ opts = url.translate_connect_args(username="user")
108
+ opts.update(url.query)
109
+
110
+ keys = opts
111
+
112
+ query = url.query
113
+
114
+ connect_args: Dict[str, Any] = {}
115
+ connectors: List[str]
116
+
117
+ def check_quote(token: str) -> str:
118
+ if ";" in str(token) or str(token).startswith("{"):
119
+ token = "{%s}" % token.replace("}", "}}")
120
+ return token
121
+
122
+ keys = {k: check_quote(v) for k, v in keys.items()}
123
+
124
+ port = ""
125
+ if "port" in keys and "port" not in query:
126
+ port = ",%d" % int(keys.pop("port"))
127
+
128
+ connectors = []
129
+
130
+ connectors.extend(
131
+ [
132
+ "Server=%s%s" % (keys.pop("host", ""), port),
133
+ "Database=%s" % keys.pop("database", ""),
134
+ ]
135
+ )
136
+
137
+ user = keys.pop("user", None)
138
+ if user:
139
+ connectors.append("UID=%s" % user)
140
+ pwd = keys.pop("password", "")
141
+ if pwd:
142
+ connectors.append("PWD=%s" % pwd)
143
+ else:
144
+ authentication = keys.pop("authentication", None)
145
+ if authentication:
146
+ connectors.append("Authentication=%s" % authentication)
147
+
148
+ connectors.extend(["%s=%s" % (k, v) for k, v in keys.items()])
149
+
150
+ return ((";".join(connectors),), connect_args)
151
+
152
+ def is_disconnect(
153
+ self,
154
+ e: Exception,
155
+ connection: Optional[
156
+ Union[pool.PoolProxiedConnection, interfaces.DBAPIConnection]
157
+ ],
158
+ cursor: Optional[interfaces.DBAPICursor],
159
+ ) -> bool:
160
+ if isinstance(e, self.loaded_dbapi.ProgrammingError):
161
+ return (
162
+ "The cursor's connection has been closed." in str(e)
163
+ or "Attempt to use a closed connection." in str(e)
164
+ or "Driver Error: Operation cannot be performed" in str(e)
165
+ )
166
+ elif isinstance(e, self.loaded_dbapi.InterfaceError):
167
+ return bool(re.search(r"Cannot .* on closed connection", str(e)))
168
+ else:
169
+ return False
170
+
171
+ def _dbapi_version(self) -> interfaces.VersionInfoType:
172
+ if not self.dbapi:
173
+ return ()
174
+ return self._parse_dbapi_version(self.dbapi.version)
175
+
176
+ def _parse_dbapi_version(self, vers: str) -> interfaces.VersionInfoType:
177
+ m = re.match(r"(?:py.*-)?([\d\.]+)(?:-(\w+))?", vers)
178
+ if not m:
179
+ return ()
180
+ vers_tuple: interfaces.VersionInfoType = tuple(
181
+ [int(x) for x in m.group(1).split(".")]
182
+ )
183
+ if m.group(2):
184
+ vers_tuple += (m.group(2),)
185
+ return vers_tuple
186
+
187
+ def _get_server_version_info(self, connection):
188
+ vers = connection.exec_driver_sql("select @@version").scalar()
189
+ m = re.match(r"Microsoft .*? - (\d+)\.(\d+)\.(\d+)\.(\d+)", vers)
190
+ if m:
191
+ return tuple(int(x) for x in m.group(1, 2, 3, 4))
192
+ else:
193
+ return None
194
+
195
+ def get_isolation_level_values(
196
+ self, dbapi_connection: interfaces.DBAPIConnection
197
+ ) -> List[IsolationLevel]:
198
+ return [
199
+ *super().get_isolation_level_values(dbapi_connection),
200
+ "AUTOCOMMIT",
201
+ ]
202
+
203
+ def set_isolation_level(
204
+ self,
205
+ dbapi_connection: interfaces.DBAPIConnection,
206
+ level: IsolationLevel,
207
+ ) -> None:
208
+ if level == "AUTOCOMMIT":
209
+ dbapi_connection.autocommit = True
210
+ else:
211
+ dbapi_connection.autocommit = False
212
+ super().set_isolation_level(dbapi_connection, level)
213
+
214
+ def detect_autocommit_setting(
215
+ self, dbapi_conn: interfaces.DBAPIConnection
216
+ ) -> bool:
217
+ return bool(dbapi_conn.autocommit)
218
+
219
+
220
+ dialect = MSDialect_mssqlpython