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,250 @@
1
+ # connectors/pyodbc.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+
8
+ from __future__ import annotations
9
+
10
+ import re
11
+ import typing
12
+ from typing import Any
13
+ from typing import Dict
14
+ from typing import List
15
+ from typing import Optional
16
+ from typing import Tuple
17
+ from typing import Union
18
+
19
+ from . import Connector
20
+ from .. import ExecutionContext
21
+ from .. import pool
22
+ from .. import util
23
+ from ..engine import ConnectArgsType
24
+ from ..engine import Connection
25
+ from ..engine import interfaces
26
+ from ..engine import URL
27
+ from ..sql.type_api import TypeEngine
28
+
29
+ if typing.TYPE_CHECKING:
30
+ from ..engine.interfaces import DBAPIModule
31
+ from ..engine.interfaces import IsolationLevel
32
+
33
+
34
+ class PyODBCConnector(Connector):
35
+ driver = "pyodbc"
36
+
37
+ # this is no longer False for pyodbc in general
38
+ supports_sane_rowcount_returning = True
39
+ supports_sane_multi_rowcount = False
40
+
41
+ supports_native_decimal = True
42
+ default_paramstyle = "named"
43
+
44
+ fast_executemany = False
45
+
46
+ # for non-DSN connections, this *may* be used to
47
+ # hold the desired driver name
48
+ pyodbc_driver_name: Optional[str] = None
49
+
50
+ def __init__(self, use_setinputsizes: bool = False, **kw: Any):
51
+ super().__init__(**kw)
52
+ if use_setinputsizes:
53
+ self.bind_typing = interfaces.BindTyping.SETINPUTSIZES
54
+
55
+ @classmethod
56
+ def import_dbapi(cls) -> DBAPIModule:
57
+ return __import__("pyodbc")
58
+
59
+ def create_connect_args(self, url: URL) -> ConnectArgsType:
60
+ opts = url.translate_connect_args(username="user")
61
+ opts.update(url.query)
62
+
63
+ keys = opts
64
+
65
+ query = url.query
66
+
67
+ connect_args: Dict[str, Any] = {}
68
+ connectors: List[str]
69
+
70
+ for param in ("ansi", "unicode_results", "autocommit"):
71
+ if param in keys:
72
+ connect_args[param] = util.asbool(keys.pop(param))
73
+
74
+ if "odbc_connect" in keys:
75
+ # (potential breaking change for issue #11250)
76
+ connectors = [keys.pop("odbc_connect")]
77
+ else:
78
+
79
+ def check_quote(token: str) -> str:
80
+ if ";" in str(token) or str(token).startswith("{"):
81
+ token = "{%s}" % token.replace("}", "}}")
82
+ return token
83
+
84
+ keys = {k: check_quote(v) for k, v in keys.items()}
85
+
86
+ dsn_connection = "dsn" in keys or (
87
+ "host" in keys and "database" not in keys
88
+ )
89
+ if dsn_connection:
90
+ connectors = [
91
+ "dsn=%s" % (keys.pop("host", "") or keys.pop("dsn", ""))
92
+ ]
93
+ else:
94
+ port = ""
95
+ if "port" in keys and "port" not in query:
96
+ port = ",%d" % int(keys.pop("port"))
97
+
98
+ connectors = []
99
+ driver = keys.pop("driver", self.pyodbc_driver_name)
100
+ if driver is None and keys:
101
+ # note if keys is empty, this is a totally blank URL
102
+ util.warn(
103
+ "No driver name specified; "
104
+ "this is expected by PyODBC when using "
105
+ "DSN-less connections"
106
+ )
107
+ else:
108
+ connectors.append("DRIVER={%s}" % driver)
109
+
110
+ connectors.extend(
111
+ [
112
+ "Server=%s%s" % (keys.pop("host", ""), port),
113
+ "Database=%s" % keys.pop("database", ""),
114
+ ]
115
+ )
116
+
117
+ user = keys.pop("user", None)
118
+ if user:
119
+ connectors.append("UID=%s" % user)
120
+ pwd = keys.pop("password", "")
121
+ if pwd:
122
+ connectors.append("PWD=%s" % pwd)
123
+ else:
124
+ authentication = keys.pop("authentication", None)
125
+ if authentication:
126
+ connectors.append("Authentication=%s" % authentication)
127
+ else:
128
+ connectors.append("Trusted_Connection=Yes")
129
+
130
+ # if set to 'Yes', the ODBC layer will try to automagically
131
+ # convert textual data from your database encoding to your
132
+ # client encoding. This should obviously be set to 'No' if
133
+ # you query a cp1253 encoded database from a latin1 client...
134
+ if "odbc_autotranslate" in keys:
135
+ connectors.append(
136
+ "AutoTranslate=%s" % keys.pop("odbc_autotranslate")
137
+ )
138
+
139
+ connectors.extend(["%s=%s" % (k, v) for k, v in keys.items()])
140
+
141
+ return ((";".join(connectors),), connect_args)
142
+
143
+ def is_disconnect(
144
+ self,
145
+ e: Exception,
146
+ connection: Optional[
147
+ Union[pool.PoolProxiedConnection, interfaces.DBAPIConnection]
148
+ ],
149
+ cursor: Optional[interfaces.DBAPICursor],
150
+ ) -> bool:
151
+ if isinstance(e, self.loaded_dbapi.ProgrammingError):
152
+ return "The cursor's connection has been closed." in str(
153
+ e
154
+ ) or "Attempt to use a closed connection." in str(e)
155
+ else:
156
+ return False
157
+
158
+ def _dbapi_version(self) -> interfaces.VersionInfoType:
159
+ if not self.dbapi:
160
+ return ()
161
+ return self._parse_dbapi_version(self.dbapi.version)
162
+
163
+ def _parse_dbapi_version(self, vers: str) -> interfaces.VersionInfoType:
164
+ m = re.match(r"(?:py.*-)?([\d\.]+)(?:-(\w+))?", vers)
165
+ if not m:
166
+ return ()
167
+ vers_tuple: interfaces.VersionInfoType = tuple(
168
+ [int(x) for x in m.group(1).split(".")]
169
+ )
170
+ if m.group(2):
171
+ vers_tuple += (m.group(2),)
172
+ return vers_tuple
173
+
174
+ def _get_server_version_info(
175
+ self, connection: Connection
176
+ ) -> interfaces.VersionInfoType:
177
+ # NOTE: this function is not reliable, particularly when
178
+ # freetds is in use. Implement database-specific server version
179
+ # queries.
180
+ dbapi_con = connection.connection.dbapi_connection
181
+ version: Tuple[Union[int, str], ...] = ()
182
+ r = re.compile(r"[.\-]")
183
+ for n in r.split(dbapi_con.getinfo(self.dbapi.SQL_DBMS_VER)): # type: ignore[union-attr] # noqa: E501
184
+ try:
185
+ version += (int(n),)
186
+ except ValueError:
187
+ pass
188
+ return tuple(version)
189
+
190
+ def do_set_input_sizes(
191
+ self,
192
+ cursor: interfaces.DBAPICursor,
193
+ list_of_tuples: List[Tuple[str, Any, TypeEngine[Any]]],
194
+ context: ExecutionContext,
195
+ ) -> None:
196
+ # the rules for these types seems a little strange, as you can pass
197
+ # non-tuples as well as tuples, however it seems to assume "0"
198
+ # for the subsequent values if you don't pass a tuple which fails
199
+ # for types such as pyodbc.SQL_WLONGVARCHAR, which is the datatype
200
+ # that ticket #5649 is targeting.
201
+
202
+ # NOTE: as of #6058, this won't be called if the use_setinputsizes
203
+ # parameter were not passed to the dialect, or if no types were
204
+ # specified in list_of_tuples
205
+
206
+ # as of #8177 for 2.0 we assume use_setinputsizes=True and only
207
+ # omit the setinputsizes calls for .executemany() with
208
+ # fast_executemany=True
209
+
210
+ if (
211
+ context.execute_style is interfaces.ExecuteStyle.EXECUTEMANY
212
+ and self.fast_executemany
213
+ ):
214
+ return
215
+
216
+ cursor.setinputsizes(
217
+ [
218
+ (
219
+ (dbtype, None, None)
220
+ if not isinstance(dbtype, tuple)
221
+ else dbtype
222
+ )
223
+ for key, dbtype, sqltype in list_of_tuples
224
+ ]
225
+ )
226
+
227
+ def get_isolation_level_values(
228
+ self, dbapi_conn: interfaces.DBAPIConnection
229
+ ) -> List[IsolationLevel]:
230
+ return [*super().get_isolation_level_values(dbapi_conn), "AUTOCOMMIT"]
231
+
232
+ def set_isolation_level(
233
+ self,
234
+ dbapi_connection: interfaces.DBAPIConnection,
235
+ level: IsolationLevel,
236
+ ) -> None:
237
+ # adjust for ConnectionFairy being present
238
+ # allows attribute set e.g. "connection.autocommit = True"
239
+ # to work properly
240
+
241
+ if level == "AUTOCOMMIT":
242
+ dbapi_connection.autocommit = True
243
+ else:
244
+ dbapi_connection.autocommit = False
245
+ super().set_isolation_level(dbapi_connection, level)
246
+
247
+ def detect_autocommit_setting(
248
+ self, dbapi_conn: interfaces.DBAPIConnection
249
+ ) -> bool:
250
+ return bool(dbapi_conn.autocommit)
@@ -0,0 +1,62 @@
1
+ # dialects/__init__.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Any
11
+ from typing import Callable
12
+ from typing import Optional
13
+ from typing import Type
14
+ from typing import TYPE_CHECKING
15
+
16
+ from .. import util
17
+
18
+ if TYPE_CHECKING:
19
+ from ..engine.interfaces import Dialect
20
+
21
+ __all__ = ("mssql", "mysql", "oracle", "postgresql", "sqlite")
22
+
23
+
24
+ def _auto_fn(name: str) -> Optional[Callable[[], Type[Dialect]]]:
25
+ """default dialect importer.
26
+
27
+ plugs into the :class:`.PluginLoader`
28
+ as a first-hit system.
29
+
30
+ """
31
+ if "." in name:
32
+ dialect, driver = name.split(".")
33
+ else:
34
+ dialect = name
35
+ driver = "base"
36
+
37
+ try:
38
+ if dialect == "mariadb":
39
+ # it's "OK" for us to hardcode here since _auto_fn is already
40
+ # hardcoded. if mysql / mariadb etc were third party dialects
41
+ # they would just publish all the entrypoints, which would actually
42
+ # look much nicer.
43
+ module: Any = __import__(
44
+ "sqlalchemy.dialects.mysql.mariadb"
45
+ ).dialects.mysql.mariadb
46
+ return module.loader(driver) # type: ignore
47
+ else:
48
+ module = __import__("sqlalchemy.dialects.%s" % (dialect,)).dialects
49
+ module = getattr(module, dialect)
50
+ except ImportError:
51
+ return None
52
+
53
+ if hasattr(module, driver):
54
+ module = getattr(module, driver)
55
+ return lambda: module.dialect
56
+ else:
57
+ return None
58
+
59
+
60
+ registry = util.PluginLoader("sqlalchemy.dialects", auto_fn=_auto_fn)
61
+
62
+ plugins = util.PluginLoader("sqlalchemy.plugins")
@@ -0,0 +1,30 @@
1
+ # dialects/_typing.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 Iterable
11
+ from typing import Mapping
12
+ from typing import Optional
13
+ from typing import Union
14
+
15
+ from ..sql import roles
16
+ from ..sql.base import ColumnCollection
17
+ from ..sql.schema import Column
18
+ from ..sql.schema import ColumnCollectionConstraint
19
+ from ..sql.schema import Index
20
+
21
+
22
+ _OnConflictConstraintT = Union[str, ColumnCollectionConstraint, Index, None]
23
+ _OnConflictIndexElementsT = Optional[
24
+ Iterable[Union[Column[Any], str, roles.DDLConstraintColumnRole]]
25
+ ]
26
+ _OnConflictIndexWhereT = Optional[roles.WhereHavingRole]
27
+ _OnConflictSetT = Optional[
28
+ Union[Mapping[Any, Any], ColumnCollection[Any, Any]]
29
+ ]
30
+ _OnConflictWhereT = Optional[roles.WhereHavingRole]
@@ -0,0 +1,89 @@
1
+ # dialects/mssql/__init__.py
2
+ # Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3
+ # <see AUTHORS file>
4
+ #
5
+ # This module is part of SQLAlchemy and is released under
6
+ # the MIT License: https://www.opensource.org/licenses/mit-license.php
7
+ # mypy: ignore-errors
8
+
9
+ from . import aioodbc # noqa
10
+ from . import base # noqa
11
+ from . import mssqlpython # noqa
12
+ from . import pymssql # noqa
13
+ from . import pyodbc # noqa
14
+ from .base import BIGINT
15
+ from .base import BINARY
16
+ from .base import BIT
17
+ from .base import CHAR
18
+ from .base import DATE
19
+ from .base import DATETIME
20
+ from .base import DATETIME2
21
+ from .base import DATETIMEOFFSET
22
+ from .base import DECIMAL
23
+ from .base import DOUBLE_PRECISION
24
+ from .base import FLOAT
25
+ from .base import IMAGE
26
+ from .base import INTEGER
27
+ from .base import JSON
28
+ from .base import MONEY
29
+ from .base import NCHAR
30
+ from .base import NTEXT
31
+ from .base import NUMERIC
32
+ from .base import NVARCHAR
33
+ from .base import REAL
34
+ from .base import ROWVERSION
35
+ from .base import SMALLDATETIME
36
+ from .base import SMALLINT
37
+ from .base import SMALLMONEY
38
+ from .base import SQL_VARIANT
39
+ from .base import TEXT
40
+ from .base import TIME
41
+ from .base import TIMESTAMP
42
+ from .base import TINYINT
43
+ from .base import UNIQUEIDENTIFIER
44
+ from .base import VARBINARY
45
+ from .base import VARCHAR
46
+ from .base import XML
47
+ from ...sql import try_cast
48
+
49
+
50
+ base.dialect = dialect = pyodbc.dialect
51
+
52
+
53
+ __all__ = (
54
+ "JSON",
55
+ "INTEGER",
56
+ "BIGINT",
57
+ "SMALLINT",
58
+ "TINYINT",
59
+ "VARCHAR",
60
+ "NVARCHAR",
61
+ "CHAR",
62
+ "NCHAR",
63
+ "TEXT",
64
+ "NTEXT",
65
+ "DECIMAL",
66
+ "NUMERIC",
67
+ "FLOAT",
68
+ "DATETIME",
69
+ "DATETIME2",
70
+ "DATETIMEOFFSET",
71
+ "DATE",
72
+ "DOUBLE_PRECISION",
73
+ "TIME",
74
+ "SMALLDATETIME",
75
+ "BINARY",
76
+ "VARBINARY",
77
+ "BIT",
78
+ "REAL",
79
+ "IMAGE",
80
+ "TIMESTAMP",
81
+ "ROWVERSION",
82
+ "MONEY",
83
+ "SMALLMONEY",
84
+ "UNIQUEIDENTIFIER",
85
+ "SQL_VARIANT",
86
+ "XML",
87
+ "dialect",
88
+ "try_cast",
89
+ )
@@ -0,0 +1,63 @@
1
+ # dialects/mssql/aioodbc.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
+ r"""
9
+ .. dialect:: mssql+aioodbc
10
+ :name: aioodbc
11
+ :dbapi: aioodbc
12
+ :connectstring: mssql+aioodbc://<username>:<password>@<dsnname>
13
+ :url: https://pypi.org/project/aioodbc/
14
+
15
+
16
+ Support for the SQL Server database in asyncio style, using the aioodbc
17
+ driver which itself is a thread-wrapper around pyodbc.
18
+
19
+ .. versionadded:: 2.0.23 Added the mssql+aioodbc dialect which builds
20
+ on top of the pyodbc and general aio* dialect architecture.
21
+
22
+ Using a special asyncio mediation layer, the aioodbc dialect is usable
23
+ as the backend for the :ref:`SQLAlchemy asyncio <asyncio_toplevel>`
24
+ extension package.
25
+
26
+ Most behaviors and caveats for this driver are the same as that of the
27
+ pyodbc dialect used on SQL Server; see :ref:`mssql_pyodbc` for general
28
+ background.
29
+
30
+ This dialect should normally be used only with the
31
+ :func:`_asyncio.create_async_engine` engine creation function; connection
32
+ styles are otherwise equivalent to those documented in the pyodbc section::
33
+
34
+ from sqlalchemy.ext.asyncio import create_async_engine
35
+
36
+ engine = create_async_engine(
37
+ "mssql+aioodbc://scott:tiger@mssql2017:1433/test?"
38
+ "driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes"
39
+ )
40
+
41
+ """
42
+
43
+ from __future__ import annotations
44
+
45
+ from .base import MSExecutionContext
46
+ from .pyodbc import MSDialect_pyodbc
47
+ from ...connectors.aioodbc import aiodbcConnector
48
+
49
+
50
+ class MSExecutionContext_aioodbc(MSExecutionContext):
51
+ def create_server_side_cursor(self):
52
+ return self._dbapi_connection.cursor(server_side=True)
53
+
54
+
55
+ class MSDialectAsync_aioodbc(aiodbcConnector, MSDialect_pyodbc):
56
+ driver = "aioodbc"
57
+
58
+ supports_statement_cache = True
59
+
60
+ execution_ctx_cls = MSExecutionContext_aioodbc
61
+
62
+
63
+ dialect = MSDialectAsync_aioodbc