SQLAlchemy 2.1.0rc1__cp315-cp315-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 (276) hide show
  1. sqlalchemy/__init__.py +299 -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 +248 -0
  6. sqlalchemy/dialects/__init__.py +62 -0
  7. sqlalchemy/dialects/_typing.py +29 -0
  8. sqlalchemy/dialects/mssql/__init__.py +88 -0
  9. sqlalchemy/dialects/mssql/aioodbc.py +63 -0
  10. sqlalchemy/dialects/mssql/base.py +4833 -0
  11. sqlalchemy/dialects/mssql/information_schema.py +345 -0
  12. sqlalchemy/dialects/mssql/json.py +140 -0
  13. sqlalchemy/dialects/mssql/mssqlpython.py +242 -0
  14. sqlalchemy/dialects/mssql/provision.py +196 -0
  15. sqlalchemy/dialects/mssql/pymssql.py +130 -0
  16. sqlalchemy/dialects/mssql/pyodbc.py +697 -0
  17. sqlalchemy/dialects/mysql/__init__.py +106 -0
  18. sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
  19. sqlalchemy/dialects/mysql/aiomysql.py +260 -0
  20. sqlalchemy/dialects/mysql/asyncmy.py +241 -0
  21. sqlalchemy/dialects/mysql/base.py +3896 -0
  22. sqlalchemy/dialects/mysql/cymysql.py +107 -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 +314 -0
  29. sqlalchemy/dialects/mysql/mysqlconnector.py +291 -0
  30. sqlalchemy/dialects/mysql/mysqldb.py +318 -0
  31. sqlalchemy/dialects/mysql/provision.py +153 -0
  32. sqlalchemy/dialects/mysql/pymysql.py +188 -0
  33. sqlalchemy/dialects/mysql/pyodbc.py +157 -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 +3847 -0
  39. sqlalchemy/dialects/oracle/cx_oracle.py +1736 -0
  40. sqlalchemy/dialects/oracle/dictionary.py +507 -0
  41. sqlalchemy/dialects/oracle/json.py +157 -0
  42. sqlalchemy/dialects/oracle/oracledb.py +898 -0
  43. sqlalchemy/dialects/oracle/provision.py +288 -0
  44. sqlalchemy/dialects/oracle/types.py +367 -0
  45. sqlalchemy/dialects/oracle/vector.py +366 -0
  46. sqlalchemy/dialects/postgresql/__init__.py +170 -0
  47. sqlalchemy/dialects/postgresql/_psycopg_common.py +232 -0
  48. sqlalchemy/dialects/postgresql/array.py +534 -0
  49. sqlalchemy/dialects/postgresql/asyncpg.py +1318 -0
  50. sqlalchemy/dialects/postgresql/base.py +5935 -0
  51. sqlalchemy/dialects/postgresql/bitstring.py +327 -0
  52. sqlalchemy/dialects/postgresql/dml.py +360 -0
  53. sqlalchemy/dialects/postgresql/ext.py +599 -0
  54. sqlalchemy/dialects/postgresql/hstore.py +422 -0
  55. sqlalchemy/dialects/postgresql/json.py +411 -0
  56. sqlalchemy/dialects/postgresql/named_types.py +535 -0
  57. sqlalchemy/dialects/postgresql/operators.py +129 -0
  58. sqlalchemy/dialects/postgresql/pg8000.py +655 -0
  59. sqlalchemy/dialects/postgresql/pg_catalog.py +345 -0
  60. sqlalchemy/dialects/postgresql/provision.py +202 -0
  61. sqlalchemy/dialects/postgresql/psycopg.py +800 -0
  62. sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
  63. sqlalchemy/dialects/postgresql/psycopg2cffi.py +62 -0
  64. sqlalchemy/dialects/postgresql/ranges.py +1002 -0
  65. sqlalchemy/dialects/postgresql/types.py +388 -0
  66. sqlalchemy/dialects/sqlite/__init__.py +59 -0
  67. sqlalchemy/dialects/sqlite/aiosqlite.py +375 -0
  68. sqlalchemy/dialects/sqlite/base.py +3103 -0
  69. sqlalchemy/dialects/sqlite/dml.py +314 -0
  70. sqlalchemy/dialects/sqlite/json.py +134 -0
  71. sqlalchemy/dialects/sqlite/provision.py +237 -0
  72. sqlalchemy/dialects/sqlite/pysqlcipher.py +166 -0
  73. sqlalchemy/dialects/sqlite/pysqlite.py +959 -0
  74. sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
  75. sqlalchemy/engine/__init__.py +62 -0
  76. sqlalchemy/engine/_processors_cy.cp315-win32.pyd +0 -0
  77. sqlalchemy/engine/_processors_cy.py +92 -0
  78. sqlalchemy/engine/_result_cy.cp315-win32.pyd +0 -0
  79. sqlalchemy/engine/_result_cy.py +711 -0
  80. sqlalchemy/engine/_row_cy.cp315-win32.pyd +0 -0
  81. sqlalchemy/engine/_row_cy.py +232 -0
  82. sqlalchemy/engine/_util_cy.cp315-win32.pyd +0 -0
  83. sqlalchemy/engine/_util_cy.py +136 -0
  84. sqlalchemy/engine/base.py +3357 -0
  85. sqlalchemy/engine/characteristics.py +155 -0
  86. sqlalchemy/engine/create.py +877 -0
  87. sqlalchemy/engine/cursor.py +2425 -0
  88. sqlalchemy/engine/default.py +2627 -0
  89. sqlalchemy/engine/events.py +965 -0
  90. sqlalchemy/engine/interfaces.py +3636 -0
  91. sqlalchemy/engine/mock.py +133 -0
  92. sqlalchemy/engine/processors.py +83 -0
  93. sqlalchemy/engine/reflection.py +2141 -0
  94. sqlalchemy/engine/result.py +2012 -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 +164 -0
  99. sqlalchemy/event/__init__.py +26 -0
  100. sqlalchemy/event/api.py +220 -0
  101. sqlalchemy/event/attr.py +675 -0
  102. sqlalchemy/event/base.py +473 -0
  103. sqlalchemy/event/legacy.py +259 -0
  104. sqlalchemy/event/registry.py +391 -0
  105. sqlalchemy/events.py +17 -0
  106. sqlalchemy/exc.py +939 -0
  107. sqlalchemy/ext/__init__.py +10 -0
  108. sqlalchemy/ext/associationproxy.py +2073 -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 +2006 -0
  116. sqlalchemy/ext/automap.py +1702 -0
  117. sqlalchemy/ext/baked.py +558 -0
  118. sqlalchemy/ext/compiler.py +601 -0
  119. sqlalchemy/ext/declarative/__init__.py +65 -0
  120. sqlalchemy/ext/declarative/extensions.py +561 -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 +440 -0
  127. sqlalchemy/ext/serializer.py +184 -0
  128. sqlalchemy/future/__init__.py +17 -0
  129. sqlalchemy/future/engine.py +15 -0
  130. sqlalchemy/inspection.py +188 -0
  131. sqlalchemy/log.py +279 -0
  132. sqlalchemy/orm/__init__.py +176 -0
  133. sqlalchemy/orm/_orm_constructors.py +2694 -0
  134. sqlalchemy/orm/_typing.py +180 -0
  135. sqlalchemy/orm/attributes.py +2868 -0
  136. sqlalchemy/orm/base.py +991 -0
  137. sqlalchemy/orm/bulk_persistence.py +2168 -0
  138. sqlalchemy/orm/clsregistry.py +630 -0
  139. sqlalchemy/orm/collections.py +1569 -0
  140. sqlalchemy/orm/context.py +3475 -0
  141. sqlalchemy/orm/decl_api.py +2283 -0
  142. sqlalchemy/orm/decl_base.py +2320 -0
  143. sqlalchemy/orm/dependency.py +1306 -0
  144. sqlalchemy/orm/descriptor_props.py +1183 -0
  145. sqlalchemy/orm/dynamic.py +306 -0
  146. sqlalchemy/orm/evaluator.py +378 -0
  147. sqlalchemy/orm/events.py +3387 -0
  148. sqlalchemy/orm/exc.py +237 -0
  149. sqlalchemy/orm/identity.py +302 -0
  150. sqlalchemy/orm/instrumentation.py +749 -0
  151. sqlalchemy/orm/interfaces.py +1595 -0
  152. sqlalchemy/orm/loading.py +1712 -0
  153. sqlalchemy/orm/mapped_collection.py +557 -0
  154. sqlalchemy/orm/mapper.py +4465 -0
  155. sqlalchemy/orm/path_registry.py +907 -0
  156. sqlalchemy/orm/persistence.py +1790 -0
  157. sqlalchemy/orm/properties.py +972 -0
  158. sqlalchemy/orm/query.py +3528 -0
  159. sqlalchemy/orm/relationships.py +3608 -0
  160. sqlalchemy/orm/scoping.py +2233 -0
  161. sqlalchemy/orm/session.py +5468 -0
  162. sqlalchemy/orm/state.py +1175 -0
  163. sqlalchemy/orm/state_changes.py +196 -0
  164. sqlalchemy/orm/strategies.py +3552 -0
  165. sqlalchemy/orm/strategy_options.py +2648 -0
  166. sqlalchemy/orm/sync.py +164 -0
  167. sqlalchemy/orm/unitofwork.py +797 -0
  168. sqlalchemy/orm/util.py +2461 -0
  169. sqlalchemy/orm/writeonly.py +701 -0
  170. sqlalchemy/pool/__init__.py +41 -0
  171. sqlalchemy/pool/base.py +1540 -0
  172. sqlalchemy/pool/events.py +375 -0
  173. sqlalchemy/pool/impl.py +583 -0
  174. sqlalchemy/py.typed +0 -0
  175. sqlalchemy/schema.py +75 -0
  176. sqlalchemy/sql/__init__.py +156 -0
  177. sqlalchemy/sql/_annotated_cols.py +402 -0
  178. sqlalchemy/sql/_cache_key_cy.cp315-win32.pyd +0 -0
  179. sqlalchemy/sql/_cache_key_cy.py +363 -0
  180. sqlalchemy/sql/_dml_constructors.py +132 -0
  181. sqlalchemy/sql/_elements_constructors.py +2190 -0
  182. sqlalchemy/sql/_orm_types.py +19 -0
  183. sqlalchemy/sql/_selectable_constructors.py +840 -0
  184. sqlalchemy/sql/_typing.py +500 -0
  185. sqlalchemy/sql/_util_cy.cp315-win32.pyd +0 -0
  186. sqlalchemy/sql/_util_cy.pxd +11 -0
  187. sqlalchemy/sql/_util_cy.py +127 -0
  188. sqlalchemy/sql/annotation.py +590 -0
  189. sqlalchemy/sql/base.py +2702 -0
  190. sqlalchemy/sql/cache_key.py +915 -0
  191. sqlalchemy/sql/coercions.py +1373 -0
  192. sqlalchemy/sql/compiler.py +8453 -0
  193. sqlalchemy/sql/crud.py +1816 -0
  194. sqlalchemy/sql/ddl.py +1962 -0
  195. sqlalchemy/sql/default_comparator.py +660 -0
  196. sqlalchemy/sql/dml.py +2018 -0
  197. sqlalchemy/sql/elements.py +6057 -0
  198. sqlalchemy/sql/events.py +458 -0
  199. sqlalchemy/sql/expression.py +171 -0
  200. sqlalchemy/sql/functions.py +2380 -0
  201. sqlalchemy/sql/lambdas.py +1442 -0
  202. sqlalchemy/sql/naming.py +204 -0
  203. sqlalchemy/sql/operators.py +2909 -0
  204. sqlalchemy/sql/roles.py +332 -0
  205. sqlalchemy/sql/schema.py +7075 -0
  206. sqlalchemy/sql/selectable.py +7634 -0
  207. sqlalchemy/sql/sqltypes.py +4130 -0
  208. sqlalchemy/sql/traversals.py +1041 -0
  209. sqlalchemy/sql/type_api.py +2450 -0
  210. sqlalchemy/sql/util.py +1496 -0
  211. sqlalchemy/sql/visitors.py +1153 -0
  212. sqlalchemy/testing/__init__.py +97 -0
  213. sqlalchemy/testing/assertions.py +1007 -0
  214. sqlalchemy/testing/assertsql.py +519 -0
  215. sqlalchemy/testing/asyncio.py +128 -0
  216. sqlalchemy/testing/cancellation.py +237 -0
  217. sqlalchemy/testing/config.py +440 -0
  218. sqlalchemy/testing/engines.py +482 -0
  219. sqlalchemy/testing/entities.py +117 -0
  220. sqlalchemy/testing/exclusions.py +501 -0
  221. sqlalchemy/testing/fixtures/__init__.py +30 -0
  222. sqlalchemy/testing/fixtures/base.py +426 -0
  223. sqlalchemy/testing/fixtures/mypy.py +247 -0
  224. sqlalchemy/testing/fixtures/orm.py +227 -0
  225. sqlalchemy/testing/fixtures/sql.py +538 -0
  226. sqlalchemy/testing/pickleable.py +155 -0
  227. sqlalchemy/testing/plugin/__init__.py +6 -0
  228. sqlalchemy/testing/plugin/bootstrap.py +50 -0
  229. sqlalchemy/testing/plugin/plugin_base.py +828 -0
  230. sqlalchemy/testing/plugin/pytestplugin.py +896 -0
  231. sqlalchemy/testing/profiles_file.py +350 -0
  232. sqlalchemy/testing/profiling.py +294 -0
  233. sqlalchemy/testing/provision.py +633 -0
  234. sqlalchemy/testing/requirements.py +1971 -0
  235. sqlalchemy/testing/schema.py +198 -0
  236. sqlalchemy/testing/suite/__init__.py +19 -0
  237. sqlalchemy/testing/suite/test_cte.py +237 -0
  238. sqlalchemy/testing/suite/test_ddl.py +420 -0
  239. sqlalchemy/testing/suite/test_dialect.py +776 -0
  240. sqlalchemy/testing/suite/test_insert.py +630 -0
  241. sqlalchemy/testing/suite/test_reflection.py +3815 -0
  242. sqlalchemy/testing/suite/test_results.py +660 -0
  243. sqlalchemy/testing/suite/test_rowcount.py +258 -0
  244. sqlalchemy/testing/suite/test_select.py +2112 -0
  245. sqlalchemy/testing/suite/test_sequence.py +317 -0
  246. sqlalchemy/testing/suite/test_table_via_select.py +686 -0
  247. sqlalchemy/testing/suite/test_types.py +2271 -0
  248. sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
  249. sqlalchemy/testing/suite/test_update_delete.py +139 -0
  250. sqlalchemy/testing/util.py +575 -0
  251. sqlalchemy/testing/warnings.py +52 -0
  252. sqlalchemy/types.py +75 -0
  253. sqlalchemy/util/__init__.py +165 -0
  254. sqlalchemy/util/_collections.py +688 -0
  255. sqlalchemy/util/_collections_cy.cp315-win32.pyd +0 -0
  256. sqlalchemy/util/_collections_cy.pxd +8 -0
  257. sqlalchemy/util/_collections_cy.py +516 -0
  258. sqlalchemy/util/_has_cython.py +48 -0
  259. sqlalchemy/util/_immutabledict_cy.cp315-win32.pyd +0 -0
  260. sqlalchemy/util/_immutabledict_cy.py +240 -0
  261. sqlalchemy/util/compat.py +298 -0
  262. sqlalchemy/util/concurrency.py +272 -0
  263. sqlalchemy/util/cython.py +95 -0
  264. sqlalchemy/util/deprecations.py +401 -0
  265. sqlalchemy/util/langhelpers.py +2797 -0
  266. sqlalchemy/util/preloaded.py +153 -0
  267. sqlalchemy/util/queue.py +304 -0
  268. sqlalchemy/util/tool_support.py +202 -0
  269. sqlalchemy/util/topological.py +120 -0
  270. sqlalchemy/util/typing.py +709 -0
  271. sqlalchemy-2.1.0rc1.dist-info/METADATA +270 -0
  272. sqlalchemy-2.1.0rc1.dist-info/RECORD +276 -0
  273. sqlalchemy-2.1.0rc1.dist-info/WHEEL +5 -0
  274. sqlalchemy-2.1.0rc1.dist-info/licenses/AUTHORS +30 -0
  275. sqlalchemy-2.1.0rc1.dist-info/licenses/LICENSE +19 -0
  276. sqlalchemy-2.1.0rc1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,345 @@
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
+ ischema = MetaData()
24
+
25
+
26
+ class CoerceUnicode(TypeDecorator):
27
+ impl = Unicode
28
+ cache_ok = True
29
+
30
+ def bind_expression(self, bindvalue):
31
+ return _cast_on_2005(bindvalue)
32
+
33
+
34
+ class _cast_on_2005(expression.ColumnElement):
35
+ def __init__(self, bindvalue):
36
+ self.bindvalue = bindvalue
37
+
38
+
39
+ @compiles(_cast_on_2005)
40
+ def _compile(element, compiler, **kw):
41
+ from . import base
42
+
43
+ if (
44
+ compiler.dialect.server_version_info is None
45
+ or compiler.dialect.server_version_info < base.MS_2005_VERSION
46
+ ):
47
+ return compiler.process(element.bindvalue, **kw)
48
+ else:
49
+ return compiler.process(cast(element.bindvalue, Unicode), **kw)
50
+
51
+
52
+ schemata = Table(
53
+ "SCHEMATA",
54
+ ischema,
55
+ Column("CATALOG_NAME", CoerceUnicode, key="catalog_name"),
56
+ Column("SCHEMA_NAME", CoerceUnicode, key="schema_name"),
57
+ Column("SCHEMA_OWNER", CoerceUnicode, key="schema_owner"),
58
+ schema="INFORMATION_SCHEMA",
59
+ )
60
+
61
+ tables = Table(
62
+ "TABLES",
63
+ ischema,
64
+ Column("TABLE_CATALOG", CoerceUnicode, key="table_catalog"),
65
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
66
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
67
+ Column("TABLE_TYPE", CoerceUnicode, key="table_type"),
68
+ schema="INFORMATION_SCHEMA",
69
+ )
70
+
71
+ columns = Table(
72
+ "COLUMNS",
73
+ ischema,
74
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
75
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
76
+ Column("COLUMN_NAME", CoerceUnicode, key="column_name"),
77
+ Column("IS_NULLABLE", Integer, key="is_nullable"),
78
+ Column("DATA_TYPE", String, key="data_type"),
79
+ Column("ORDINAL_POSITION", Integer, key="ordinal_position"),
80
+ Column(
81
+ "CHARACTER_MAXIMUM_LENGTH", Integer, key="character_maximum_length"
82
+ ),
83
+ Column("NUMERIC_PRECISION", Integer, key="numeric_precision"),
84
+ Column("NUMERIC_SCALE", Integer, key="numeric_scale"),
85
+ Column("COLUMN_DEFAULT", Integer, key="column_default"),
86
+ Column("COLLATION_NAME", String, key="collation_name"),
87
+ schema="INFORMATION_SCHEMA",
88
+ )
89
+
90
+ sys_columns = Table(
91
+ "columns",
92
+ ischema,
93
+ Column("object_id", Integer),
94
+ Column("name", CoerceUnicode),
95
+ Column("column_id", Integer),
96
+ Column("default_object_id", Integer),
97
+ Column("user_type_id", Integer),
98
+ Column("is_nullable", Integer),
99
+ Column("ordinal_position", Integer),
100
+ Column("max_length", Integer),
101
+ Column("precision", Integer),
102
+ Column("scale", Integer),
103
+ Column("collation_name", String),
104
+ schema="sys",
105
+ )
106
+
107
+ sys_types = Table(
108
+ "types",
109
+ ischema,
110
+ Column("name", CoerceUnicode, key="name"),
111
+ Column("system_type_id", Integer, key="system_type_id"),
112
+ Column("user_type_id", Integer, key="user_type_id"),
113
+ Column("schema_id", Integer, key="schema_id"),
114
+ Column("max_length", Integer, key="max_length"),
115
+ Column("precision", Integer, key="precision"),
116
+ Column("scale", Integer, key="scale"),
117
+ Column("collation_name", CoerceUnicode, key="collation_name"),
118
+ Column("is_nullable", Boolean, key="is_nullable"),
119
+ Column("is_user_defined", Boolean, key="is_user_defined"),
120
+ Column("is_assembly_type", Boolean, key="is_assembly_type"),
121
+ Column("default_object_id", Integer, key="default_object_id"),
122
+ Column("rule_object_id", Integer, key="rule_object_id"),
123
+ Column("is_table_type", Boolean, key="is_table_type"),
124
+ schema="sys",
125
+ )
126
+
127
+ constraints = Table(
128
+ "TABLE_CONSTRAINTS",
129
+ ischema,
130
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
131
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
132
+ Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
133
+ Column("CONSTRAINT_TYPE", CoerceUnicode, key="constraint_type"),
134
+ schema="INFORMATION_SCHEMA",
135
+ )
136
+
137
+ sys_default_constraints = Table(
138
+ "default_constraints",
139
+ ischema,
140
+ Column("object_id", Integer),
141
+ Column("name", CoerceUnicode),
142
+ Column("schema_id", Integer),
143
+ Column("parent_column_id", Integer),
144
+ Column("definition", CoerceUnicode),
145
+ schema="sys",
146
+ )
147
+
148
+ column_constraints = Table(
149
+ "CONSTRAINT_COLUMN_USAGE",
150
+ ischema,
151
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
152
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
153
+ Column("COLUMN_NAME", CoerceUnicode, key="column_name"),
154
+ Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
155
+ schema="INFORMATION_SCHEMA",
156
+ )
157
+
158
+ key_constraints = Table(
159
+ "KEY_COLUMN_USAGE",
160
+ ischema,
161
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
162
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
163
+ Column("COLUMN_NAME", CoerceUnicode, key="column_name"),
164
+ Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
165
+ Column("CONSTRAINT_SCHEMA", CoerceUnicode, key="constraint_schema"),
166
+ Column("ORDINAL_POSITION", Integer, key="ordinal_position"),
167
+ schema="INFORMATION_SCHEMA",
168
+ )
169
+
170
+ ref_constraints = Table(
171
+ "REFERENTIAL_CONSTRAINTS",
172
+ ischema,
173
+ Column("CONSTRAINT_CATALOG", CoerceUnicode, key="constraint_catalog"),
174
+ Column("CONSTRAINT_SCHEMA", CoerceUnicode, key="constraint_schema"),
175
+ Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"),
176
+ # TODO: is CATLOG misspelled ?
177
+ Column(
178
+ "UNIQUE_CONSTRAINT_CATLOG",
179
+ CoerceUnicode,
180
+ key="unique_constraint_catalog",
181
+ ),
182
+ Column(
183
+ "UNIQUE_CONSTRAINT_SCHEMA",
184
+ CoerceUnicode,
185
+ key="unique_constraint_schema",
186
+ ),
187
+ Column(
188
+ "UNIQUE_CONSTRAINT_NAME", CoerceUnicode, key="unique_constraint_name"
189
+ ),
190
+ Column("MATCH_OPTION", String, key="match_option"),
191
+ Column("UPDATE_RULE", String, key="update_rule"),
192
+ Column("DELETE_RULE", String, key="delete_rule"),
193
+ schema="INFORMATION_SCHEMA",
194
+ )
195
+
196
+ views = Table(
197
+ "VIEWS",
198
+ ischema,
199
+ Column("TABLE_CATALOG", CoerceUnicode, key="table_catalog"),
200
+ Column("TABLE_SCHEMA", CoerceUnicode, key="table_schema"),
201
+ Column("TABLE_NAME", CoerceUnicode, key="table_name"),
202
+ Column("VIEW_DEFINITION", CoerceUnicode, key="view_definition"),
203
+ Column("CHECK_OPTION", String, key="check_option"),
204
+ Column("IS_UPDATABLE", String, key="is_updatable"),
205
+ schema="INFORMATION_SCHEMA",
206
+ )
207
+
208
+ computed_columns = Table(
209
+ "computed_columns",
210
+ ischema,
211
+ Column("object_id", Integer),
212
+ Column("name", CoerceUnicode),
213
+ Column("column_id", Integer),
214
+ Column("is_computed", Boolean),
215
+ Column("is_persisted", Boolean),
216
+ Column("definition", CoerceUnicode),
217
+ schema="sys",
218
+ )
219
+
220
+ sequences = Table(
221
+ "SEQUENCES",
222
+ ischema,
223
+ Column("SEQUENCE_CATALOG", CoerceUnicode, key="sequence_catalog"),
224
+ Column("SEQUENCE_SCHEMA", CoerceUnicode, key="sequence_schema"),
225
+ Column("SEQUENCE_NAME", CoerceUnicode, key="sequence_name"),
226
+ schema="INFORMATION_SCHEMA",
227
+ )
228
+
229
+
230
+ class NumericSqlVariant(TypeDecorator):
231
+ r"""This type casts sql_variant columns in the identity_columns view
232
+ to numeric. This is required because:
233
+
234
+ * pyodbc does not support sql_variant
235
+ * pymssql under python 2 return the byte representation of the number,
236
+ int 1 is returned as "\x01\x00\x00\x00". On python 3 it returns the
237
+ correct value as string.
238
+ """
239
+
240
+ impl = Unicode
241
+ cache_ok = True
242
+
243
+ def column_expression(self, colexpr):
244
+ return cast(colexpr, Numeric(38, 0))
245
+
246
+
247
+ identity_columns = Table(
248
+ "identity_columns",
249
+ ischema,
250
+ Column("object_id", Integer),
251
+ Column("name", CoerceUnicode),
252
+ Column("column_id", Integer),
253
+ Column("is_identity", Boolean),
254
+ Column("seed_value", NumericSqlVariant),
255
+ Column("increment_value", NumericSqlVariant),
256
+ Column("last_value", NumericSqlVariant),
257
+ Column("is_not_for_replication", Boolean),
258
+ schema="sys",
259
+ )
260
+
261
+
262
+ class NVarcharSqlVariant(TypeDecorator):
263
+ """This type casts sql_variant columns in the extended_properties view
264
+ to nvarchar. This is required because pyodbc does not support sql_variant
265
+ """
266
+
267
+ impl = Unicode
268
+ cache_ok = True
269
+
270
+ def column_expression(self, colexpr):
271
+ return cast(colexpr, NVARCHAR)
272
+
273
+
274
+ extended_properties = Table(
275
+ "extended_properties",
276
+ ischema,
277
+ Column("class", Integer), # TINYINT
278
+ Column("class_desc", CoerceUnicode),
279
+ Column("major_id", Integer),
280
+ Column("minor_id", Integer),
281
+ Column("name", CoerceUnicode),
282
+ Column("value", NVarcharSqlVariant),
283
+ schema="sys",
284
+ )
285
+
286
+ sys_schemas = Table(
287
+ "schemas",
288
+ ischema,
289
+ Column("schema_id", Integer),
290
+ Column("name", CoerceUnicode),
291
+ Column("principal_id", Integer),
292
+ schema="sys",
293
+ )
294
+
295
+ sys_objects = Table(
296
+ "objects",
297
+ ischema,
298
+ Column("object_id", Integer),
299
+ Column("name", CoerceUnicode),
300
+ Column("schema_id", Integer),
301
+ Column("parent_object_id", Integer),
302
+ Column("type", String), # CHAR(2)
303
+ Column("type_desc", CoerceUnicode),
304
+ schema="sys",
305
+ )
306
+
307
+ sys_key_constraints = Table(
308
+ "key_constraints",
309
+ ischema,
310
+ Column("object_id", Integer),
311
+ Column("name", CoerceUnicode),
312
+ Column("schema_id", Integer),
313
+ Column("parent_object_id", Integer),
314
+ Column("type", String), # CHAR(2) ('PK', 'UQ')
315
+ Column("unique_index_id", Integer),
316
+ schema="sys",
317
+ )
318
+
319
+ sys_indexes = Table(
320
+ "indexes",
321
+ ischema,
322
+ Column("object_id", Integer),
323
+ Column("index_id", Integer),
324
+ Column("name", CoerceUnicode),
325
+ Column("type", Integer), # TINYINT: 1=clustered, 2=nonclustered
326
+ Column("type_desc", CoerceUnicode),
327
+ Column("is_unique", Boolean),
328
+ Column("is_primary_key", Boolean),
329
+ Column("is_unique_constraint", Boolean),
330
+ Column("filter_definition", CoerceUnicode),
331
+ schema="sys",
332
+ )
333
+
334
+ sys_index_columns = Table(
335
+ "index_columns",
336
+ ischema,
337
+ Column("object_id", Integer),
338
+ Column("index_id", Integer),
339
+ Column("index_column_id", Integer),
340
+ Column("column_id", Integer),
341
+ Column("key_ordinal", Integer),
342
+ Column("is_descending_key", Boolean),
343
+ Column("is_included_column", Boolean),
344
+ schema="sys",
345
+ )
@@ -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
+ )