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.
- sqlalchemy/__init__.py +298 -0
- sqlalchemy/connectors/__init__.py +18 -0
- sqlalchemy/connectors/aioodbc.py +171 -0
- sqlalchemy/connectors/asyncio.py +476 -0
- sqlalchemy/connectors/pyodbc.py +250 -0
- sqlalchemy/dialects/__init__.py +62 -0
- sqlalchemy/dialects/_typing.py +30 -0
- sqlalchemy/dialects/mssql/__init__.py +89 -0
- sqlalchemy/dialects/mssql/aioodbc.py +63 -0
- sqlalchemy/dialects/mssql/base.py +4166 -0
- sqlalchemy/dialects/mssql/information_schema.py +285 -0
- sqlalchemy/dialects/mssql/json.py +140 -0
- sqlalchemy/dialects/mssql/mssqlpython.py +220 -0
- sqlalchemy/dialects/mssql/provision.py +196 -0
- sqlalchemy/dialects/mssql/pymssql.py +126 -0
- sqlalchemy/dialects/mssql/pyodbc.py +698 -0
- sqlalchemy/dialects/mysql/__init__.py +106 -0
- sqlalchemy/dialects/mysql/_mariadb_shim.py +312 -0
- sqlalchemy/dialects/mysql/aiomysql.py +226 -0
- sqlalchemy/dialects/mysql/asyncmy.py +214 -0
- sqlalchemy/dialects/mysql/base.py +3877 -0
- sqlalchemy/dialects/mysql/cymysql.py +106 -0
- sqlalchemy/dialects/mysql/dml.py +279 -0
- sqlalchemy/dialects/mysql/enumerated.py +277 -0
- sqlalchemy/dialects/mysql/expression.py +146 -0
- sqlalchemy/dialects/mysql/json.py +92 -0
- sqlalchemy/dialects/mysql/mariadb.py +67 -0
- sqlalchemy/dialects/mysql/mariadbconnector.py +330 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +296 -0
- sqlalchemy/dialects/mysql/mysqldb.py +312 -0
- sqlalchemy/dialects/mysql/provision.py +153 -0
- sqlalchemy/dialects/mysql/pymysql.py +157 -0
- sqlalchemy/dialects/mysql/pyodbc.py +156 -0
- sqlalchemy/dialects/mysql/reflection.py +724 -0
- sqlalchemy/dialects/mysql/reserved_words.py +570 -0
- sqlalchemy/dialects/mysql/types.py +845 -0
- sqlalchemy/dialects/oracle/__init__.py +85 -0
- sqlalchemy/dialects/oracle/base.py +3977 -0
- sqlalchemy/dialects/oracle/cx_oracle.py +1601 -0
- sqlalchemy/dialects/oracle/dictionary.py +507 -0
- sqlalchemy/dialects/oracle/json.py +158 -0
- sqlalchemy/dialects/oracle/oracledb.py +909 -0
- sqlalchemy/dialects/oracle/provision.py +288 -0
- sqlalchemy/dialects/oracle/types.py +367 -0
- sqlalchemy/dialects/oracle/vector.py +368 -0
- sqlalchemy/dialects/postgresql/__init__.py +171 -0
- sqlalchemy/dialects/postgresql/_psycopg_common.py +229 -0
- sqlalchemy/dialects/postgresql/array.py +534 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +1323 -0
- sqlalchemy/dialects/postgresql/base.py +5789 -0
- sqlalchemy/dialects/postgresql/bitstring.py +327 -0
- sqlalchemy/dialects/postgresql/dml.py +360 -0
- sqlalchemy/dialects/postgresql/ext.py +593 -0
- sqlalchemy/dialects/postgresql/hstore.py +423 -0
- sqlalchemy/dialects/postgresql/json.py +408 -0
- sqlalchemy/dialects/postgresql/named_types.py +521 -0
- sqlalchemy/dialects/postgresql/operators.py +130 -0
- sqlalchemy/dialects/postgresql/pg8000.py +670 -0
- sqlalchemy/dialects/postgresql/pg_catalog.py +344 -0
- sqlalchemy/dialects/postgresql/provision.py +184 -0
- sqlalchemy/dialects/postgresql/psycopg.py +799 -0
- sqlalchemy/dialects/postgresql/psycopg2.py +860 -0
- sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
- sqlalchemy/dialects/postgresql/ranges.py +1002 -0
- sqlalchemy/dialects/postgresql/types.py +388 -0
- sqlalchemy/dialects/sqlite/__init__.py +57 -0
- sqlalchemy/dialects/sqlite/aiosqlite.py +321 -0
- sqlalchemy/dialects/sqlite/base.py +3063 -0
- sqlalchemy/dialects/sqlite/dml.py +279 -0
- sqlalchemy/dialects/sqlite/json.py +100 -0
- sqlalchemy/dialects/sqlite/provision.py +229 -0
- sqlalchemy/dialects/sqlite/pysqlcipher.py +161 -0
- sqlalchemy/dialects/sqlite/pysqlite.py +754 -0
- sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
- sqlalchemy/engine/__init__.py +62 -0
- sqlalchemy/engine/_processors_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_processors_cy.py +92 -0
- sqlalchemy/engine/_result_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_result_cy.py +633 -0
- sqlalchemy/engine/_row_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_row_cy.py +232 -0
- sqlalchemy/engine/_util_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/engine/_util_cy.py +136 -0
- sqlalchemy/engine/base.py +3354 -0
- sqlalchemy/engine/characteristics.py +155 -0
- sqlalchemy/engine/create.py +877 -0
- sqlalchemy/engine/cursor.py +2421 -0
- sqlalchemy/engine/default.py +2402 -0
- sqlalchemy/engine/events.py +965 -0
- sqlalchemy/engine/interfaces.py +3495 -0
- sqlalchemy/engine/mock.py +134 -0
- sqlalchemy/engine/processors.py +82 -0
- sqlalchemy/engine/reflection.py +2100 -0
- sqlalchemy/engine/result.py +1966 -0
- sqlalchemy/engine/row.py +397 -0
- sqlalchemy/engine/strategies.py +16 -0
- sqlalchemy/engine/url.py +922 -0
- sqlalchemy/engine/util.py +156 -0
- sqlalchemy/event/__init__.py +26 -0
- sqlalchemy/event/api.py +220 -0
- sqlalchemy/event/attr.py +674 -0
- sqlalchemy/event/base.py +472 -0
- sqlalchemy/event/legacy.py +258 -0
- sqlalchemy/event/registry.py +390 -0
- sqlalchemy/events.py +17 -0
- sqlalchemy/exc.py +922 -0
- sqlalchemy/ext/__init__.py +11 -0
- sqlalchemy/ext/associationproxy.py +2072 -0
- sqlalchemy/ext/asyncio/__init__.py +29 -0
- sqlalchemy/ext/asyncio/base.py +281 -0
- sqlalchemy/ext/asyncio/engine.py +1487 -0
- sqlalchemy/ext/asyncio/exc.py +21 -0
- sqlalchemy/ext/asyncio/result.py +994 -0
- sqlalchemy/ext/asyncio/scoping.py +1679 -0
- sqlalchemy/ext/asyncio/session.py +2007 -0
- sqlalchemy/ext/automap.py +1701 -0
- sqlalchemy/ext/baked.py +559 -0
- sqlalchemy/ext/compiler.py +600 -0
- sqlalchemy/ext/declarative/__init__.py +65 -0
- sqlalchemy/ext/declarative/extensions.py +560 -0
- sqlalchemy/ext/horizontal_shard.py +481 -0
- sqlalchemy/ext/hybrid.py +1877 -0
- sqlalchemy/ext/indexable.py +364 -0
- sqlalchemy/ext/instrumentation.py +450 -0
- sqlalchemy/ext/mutable.py +1081 -0
- sqlalchemy/ext/orderinglist.py +439 -0
- sqlalchemy/ext/serializer.py +185 -0
- sqlalchemy/future/__init__.py +16 -0
- sqlalchemy/future/engine.py +15 -0
- sqlalchemy/inspection.py +174 -0
- sqlalchemy/log.py +283 -0
- sqlalchemy/orm/__init__.py +176 -0
- sqlalchemy/orm/_orm_constructors.py +2694 -0
- sqlalchemy/orm/_typing.py +179 -0
- sqlalchemy/orm/attributes.py +2868 -0
- sqlalchemy/orm/base.py +976 -0
- sqlalchemy/orm/bulk_persistence.py +2152 -0
- sqlalchemy/orm/clsregistry.py +582 -0
- sqlalchemy/orm/collections.py +1568 -0
- sqlalchemy/orm/context.py +3471 -0
- sqlalchemy/orm/decl_api.py +2280 -0
- sqlalchemy/orm/decl_base.py +2309 -0
- sqlalchemy/orm/dependency.py +1306 -0
- sqlalchemy/orm/descriptor_props.py +1183 -0
- sqlalchemy/orm/dynamic.py +307 -0
- sqlalchemy/orm/evaluator.py +379 -0
- sqlalchemy/orm/events.py +3386 -0
- sqlalchemy/orm/exc.py +237 -0
- sqlalchemy/orm/identity.py +302 -0
- sqlalchemy/orm/instrumentation.py +746 -0
- sqlalchemy/orm/interfaces.py +1589 -0
- sqlalchemy/orm/loading.py +1684 -0
- sqlalchemy/orm/mapped_collection.py +557 -0
- sqlalchemy/orm/mapper.py +4411 -0
- sqlalchemy/orm/path_registry.py +829 -0
- sqlalchemy/orm/persistence.py +1789 -0
- sqlalchemy/orm/properties.py +973 -0
- sqlalchemy/orm/query.py +3528 -0
- sqlalchemy/orm/relationships.py +3570 -0
- sqlalchemy/orm/scoping.py +2232 -0
- sqlalchemy/orm/session.py +5403 -0
- sqlalchemy/orm/state.py +1175 -0
- sqlalchemy/orm/state_changes.py +196 -0
- sqlalchemy/orm/strategies.py +3492 -0
- sqlalchemy/orm/strategy_options.py +2562 -0
- sqlalchemy/orm/sync.py +164 -0
- sqlalchemy/orm/unitofwork.py +798 -0
- sqlalchemy/orm/util.py +2438 -0
- sqlalchemy/orm/writeonly.py +694 -0
- sqlalchemy/pool/__init__.py +41 -0
- sqlalchemy/pool/base.py +1522 -0
- sqlalchemy/pool/events.py +375 -0
- sqlalchemy/pool/impl.py +582 -0
- sqlalchemy/py.typed +0 -0
- sqlalchemy/schema.py +74 -0
- sqlalchemy/sql/__init__.py +156 -0
- sqlalchemy/sql/_annotated_cols.py +397 -0
- sqlalchemy/sql/_dml_constructors.py +132 -0
- sqlalchemy/sql/_elements_constructors.py +2164 -0
- sqlalchemy/sql/_orm_types.py +20 -0
- sqlalchemy/sql/_selectable_constructors.py +840 -0
- sqlalchemy/sql/_typing.py +487 -0
- sqlalchemy/sql/_util_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/sql/_util_cy.py +127 -0
- sqlalchemy/sql/annotation.py +590 -0
- sqlalchemy/sql/base.py +2699 -0
- sqlalchemy/sql/cache_key.py +1066 -0
- sqlalchemy/sql/coercions.py +1373 -0
- sqlalchemy/sql/compiler.py +8327 -0
- sqlalchemy/sql/crud.py +1815 -0
- sqlalchemy/sql/ddl.py +1928 -0
- sqlalchemy/sql/default_comparator.py +654 -0
- sqlalchemy/sql/dml.py +1977 -0
- sqlalchemy/sql/elements.py +6033 -0
- sqlalchemy/sql/events.py +458 -0
- sqlalchemy/sql/expression.py +172 -0
- sqlalchemy/sql/functions.py +2305 -0
- sqlalchemy/sql/lambdas.py +1443 -0
- sqlalchemy/sql/naming.py +209 -0
- sqlalchemy/sql/operators.py +2897 -0
- sqlalchemy/sql/roles.py +332 -0
- sqlalchemy/sql/schema.py +6703 -0
- sqlalchemy/sql/selectable.py +7553 -0
- sqlalchemy/sql/sqltypes.py +4093 -0
- sqlalchemy/sql/traversals.py +1042 -0
- sqlalchemy/sql/type_api.py +2446 -0
- sqlalchemy/sql/util.py +1495 -0
- sqlalchemy/sql/visitors.py +1157 -0
- sqlalchemy/testing/__init__.py +96 -0
- sqlalchemy/testing/assertions.py +1007 -0
- sqlalchemy/testing/assertsql.py +519 -0
- sqlalchemy/testing/asyncio.py +128 -0
- sqlalchemy/testing/config.py +440 -0
- sqlalchemy/testing/engines.py +483 -0
- sqlalchemy/testing/entities.py +117 -0
- sqlalchemy/testing/exclusions.py +476 -0
- sqlalchemy/testing/fixtures/__init__.py +30 -0
- sqlalchemy/testing/fixtures/base.py +384 -0
- sqlalchemy/testing/fixtures/mypy.py +247 -0
- sqlalchemy/testing/fixtures/orm.py +227 -0
- sqlalchemy/testing/fixtures/sql.py +538 -0
- sqlalchemy/testing/pickleable.py +155 -0
- sqlalchemy/testing/plugin/__init__.py +6 -0
- sqlalchemy/testing/plugin/bootstrap.py +51 -0
- sqlalchemy/testing/plugin/plugin_base.py +828 -0
- sqlalchemy/testing/plugin/pytestplugin.py +892 -0
- sqlalchemy/testing/profiling.py +329 -0
- sqlalchemy/testing/provision.py +613 -0
- sqlalchemy/testing/requirements.py +1978 -0
- sqlalchemy/testing/schema.py +198 -0
- sqlalchemy/testing/suite/__init__.py +19 -0
- sqlalchemy/testing/suite/test_cte.py +237 -0
- sqlalchemy/testing/suite/test_ddl.py +420 -0
- sqlalchemy/testing/suite/test_dialect.py +776 -0
- sqlalchemy/testing/suite/test_insert.py +630 -0
- sqlalchemy/testing/suite/test_reflection.py +3557 -0
- sqlalchemy/testing/suite/test_results.py +660 -0
- sqlalchemy/testing/suite/test_rowcount.py +258 -0
- sqlalchemy/testing/suite/test_select.py +2112 -0
- sqlalchemy/testing/suite/test_sequence.py +317 -0
- sqlalchemy/testing/suite/test_table_via_select.py +686 -0
- sqlalchemy/testing/suite/test_types.py +2271 -0
- sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
- sqlalchemy/testing/suite/test_update_delete.py +139 -0
- sqlalchemy/testing/util.py +535 -0
- sqlalchemy/testing/warnings.py +52 -0
- sqlalchemy/types.py +76 -0
- sqlalchemy/util/__init__.py +158 -0
- sqlalchemy/util/_collections.py +688 -0
- sqlalchemy/util/_collections_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/util/_collections_cy.pxd +8 -0
- sqlalchemy/util/_collections_cy.py +516 -0
- sqlalchemy/util/_has_cython.py +46 -0
- sqlalchemy/util/_immutabledict_cy.cp313t-win_arm64.pyd +0 -0
- sqlalchemy/util/_immutabledict_cy.py +240 -0
- sqlalchemy/util/compat.py +299 -0
- sqlalchemy/util/concurrency.py +322 -0
- sqlalchemy/util/cython.py +79 -0
- sqlalchemy/util/deprecations.py +401 -0
- sqlalchemy/util/langhelpers.py +2320 -0
- sqlalchemy/util/preloaded.py +152 -0
- sqlalchemy/util/queue.py +304 -0
- sqlalchemy/util/tool_support.py +201 -0
- sqlalchemy/util/topological.py +120 -0
- sqlalchemy/util/typing.py +711 -0
- sqlalchemy-2.1.0b2.dist-info/METADATA +269 -0
- sqlalchemy-2.1.0b2.dist-info/RECORD +270 -0
- sqlalchemy-2.1.0b2.dist-info/WHEEL +5 -0
- sqlalchemy-2.1.0b2.dist-info/licenses/LICENSE +19 -0
- sqlalchemy-2.1.0b2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# dialects/mysql/__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
|
+
|
|
10
|
+
from . import aiomysql # noqa
|
|
11
|
+
from . import asyncmy # noqa
|
|
12
|
+
from . import base # noqa
|
|
13
|
+
from . import cymysql # noqa
|
|
14
|
+
from . import mariadbconnector # noqa
|
|
15
|
+
from . import mysqlconnector # noqa
|
|
16
|
+
from . import mysqldb # noqa
|
|
17
|
+
from . import pymysql # noqa
|
|
18
|
+
from . import pyodbc # noqa
|
|
19
|
+
from .base import BIGINT
|
|
20
|
+
from .base import BINARY
|
|
21
|
+
from .base import BIT
|
|
22
|
+
from .base import BLOB
|
|
23
|
+
from .base import BOOLEAN
|
|
24
|
+
from .base import CHAR
|
|
25
|
+
from .base import DATE
|
|
26
|
+
from .base import DATETIME
|
|
27
|
+
from .base import DECIMAL
|
|
28
|
+
from .base import DOUBLE
|
|
29
|
+
from .base import ENUM
|
|
30
|
+
from .base import FLOAT
|
|
31
|
+
from .base import INTEGER
|
|
32
|
+
from .base import JSON
|
|
33
|
+
from .base import LONGBLOB
|
|
34
|
+
from .base import LONGTEXT
|
|
35
|
+
from .base import MEDIUMBLOB
|
|
36
|
+
from .base import MEDIUMINT
|
|
37
|
+
from .base import MEDIUMTEXT
|
|
38
|
+
from .base import NCHAR
|
|
39
|
+
from .base import NUMERIC
|
|
40
|
+
from .base import NVARCHAR
|
|
41
|
+
from .base import REAL
|
|
42
|
+
from .base import SET
|
|
43
|
+
from .base import SMALLINT
|
|
44
|
+
from .base import TEXT
|
|
45
|
+
from .base import TIME
|
|
46
|
+
from .base import TIMESTAMP
|
|
47
|
+
from .base import TINYBLOB
|
|
48
|
+
from .base import TINYINT
|
|
49
|
+
from .base import TINYTEXT
|
|
50
|
+
from .base import VARBINARY
|
|
51
|
+
from .base import VARCHAR
|
|
52
|
+
from .base import YEAR
|
|
53
|
+
from .dml import Insert
|
|
54
|
+
from .dml import insert
|
|
55
|
+
from .dml import limit
|
|
56
|
+
from .expression import match
|
|
57
|
+
from .mariadb import INET4
|
|
58
|
+
from .mariadb import INET6
|
|
59
|
+
|
|
60
|
+
# default dialect
|
|
61
|
+
base.dialect = dialect = mysqldb.dialect
|
|
62
|
+
|
|
63
|
+
__all__ = (
|
|
64
|
+
"BIGINT",
|
|
65
|
+
"BINARY",
|
|
66
|
+
"BIT",
|
|
67
|
+
"BLOB",
|
|
68
|
+
"BOOLEAN",
|
|
69
|
+
"CHAR",
|
|
70
|
+
"DATE",
|
|
71
|
+
"DATETIME",
|
|
72
|
+
"DECIMAL",
|
|
73
|
+
"DOUBLE",
|
|
74
|
+
"ENUM",
|
|
75
|
+
"FLOAT",
|
|
76
|
+
"INET4",
|
|
77
|
+
"INET6",
|
|
78
|
+
"INTEGER",
|
|
79
|
+
"INTEGER",
|
|
80
|
+
"JSON",
|
|
81
|
+
"LONGBLOB",
|
|
82
|
+
"LONGTEXT",
|
|
83
|
+
"MEDIUMBLOB",
|
|
84
|
+
"MEDIUMINT",
|
|
85
|
+
"MEDIUMTEXT",
|
|
86
|
+
"NCHAR",
|
|
87
|
+
"NVARCHAR",
|
|
88
|
+
"NUMERIC",
|
|
89
|
+
"SET",
|
|
90
|
+
"SMALLINT",
|
|
91
|
+
"REAL",
|
|
92
|
+
"TEXT",
|
|
93
|
+
"TIME",
|
|
94
|
+
"TIMESTAMP",
|
|
95
|
+
"TINYBLOB",
|
|
96
|
+
"TINYINT",
|
|
97
|
+
"TINYTEXT",
|
|
98
|
+
"VARBINARY",
|
|
99
|
+
"VARCHAR",
|
|
100
|
+
"YEAR",
|
|
101
|
+
"dialect",
|
|
102
|
+
"insert",
|
|
103
|
+
"Insert",
|
|
104
|
+
"match",
|
|
105
|
+
"limit",
|
|
106
|
+
)
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# dialects/mysql/_mariadb_shim.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 cast
|
|
12
|
+
from typing import Optional
|
|
13
|
+
from typing import Type
|
|
14
|
+
from typing import TYPE_CHECKING
|
|
15
|
+
|
|
16
|
+
from .reserved_words import RESERVED_WORDS_MARIADB
|
|
17
|
+
from ... import exc
|
|
18
|
+
from ... import schema as sa_schema
|
|
19
|
+
from ... import util
|
|
20
|
+
from ...engine import cursor as _cursor
|
|
21
|
+
from ...engine import default
|
|
22
|
+
from ...engine.default import DefaultDialect
|
|
23
|
+
from ...engine.interfaces import TypeCompiler
|
|
24
|
+
from ...sql import elements
|
|
25
|
+
from ...sql import sqltypes
|
|
26
|
+
from ...sql.compiler import DDLCompiler
|
|
27
|
+
from ...sql.compiler import IdentifierPreparer
|
|
28
|
+
from ...sql.compiler import SQLCompiler
|
|
29
|
+
from ...sql.schema import SchemaConst
|
|
30
|
+
from ...sql.sqltypes import _UUID_RETURN
|
|
31
|
+
from ...sql.sqltypes import UUID
|
|
32
|
+
from ...sql.sqltypes import Uuid
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
from .base import MySQLIdentifierPreparer
|
|
36
|
+
from .mariadb import INET4
|
|
37
|
+
from .mariadb import INET6
|
|
38
|
+
from ...engine import URL
|
|
39
|
+
from ...engine.base import Connection
|
|
40
|
+
from ...sql import ddl
|
|
41
|
+
from ...sql.schema import IdentityOptions
|
|
42
|
+
from ...sql.schema import Sequence as Sequence_SchemaItem
|
|
43
|
+
from ...sql.type_api import _BindProcessorType
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class _MariaDBUUID(UUID[_UUID_RETURN]):
|
|
47
|
+
def __init__(self, as_uuid: bool = True, native_uuid: bool = True):
|
|
48
|
+
self.as_uuid = as_uuid
|
|
49
|
+
|
|
50
|
+
# the _MariaDBUUID internal type is only invoked for a Uuid() with
|
|
51
|
+
# native_uuid=True. for non-native uuid type, the plain Uuid
|
|
52
|
+
# returns itself due to the workings of the Emulated superclass.
|
|
53
|
+
assert native_uuid
|
|
54
|
+
|
|
55
|
+
# for internal type, force string conversion for result_processor() as
|
|
56
|
+
# current drivers are returning a string, not a Python UUID object
|
|
57
|
+
self.native_uuid = False
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def native(self) -> bool: # type: ignore[override]
|
|
61
|
+
# override to return True, this is a native type, just turning
|
|
62
|
+
# off native_uuid for internal data handling
|
|
63
|
+
return True
|
|
64
|
+
|
|
65
|
+
def bind_processor(self, dialect: MariaDBShim) -> Optional[_BindProcessorType[_UUID_RETURN]]: # type: ignore[override] # noqa: E501
|
|
66
|
+
if not dialect.supports_native_uuid or not dialect._allows_uuid_binds:
|
|
67
|
+
return super().bind_processor(dialect) # type: ignore[return-value] # noqa: E501
|
|
68
|
+
else:
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class MariaDBTypeCompilerShim(TypeCompiler):
|
|
73
|
+
def visit_INET4(self, type_: INET4, **kwargs: Any) -> str:
|
|
74
|
+
return "INET4"
|
|
75
|
+
|
|
76
|
+
def visit_INET6(self, type_: INET6, **kwargs: Any) -> str:
|
|
77
|
+
return "INET6"
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class MariadbExecutionContextShim(default.DefaultExecutionContext):
|
|
81
|
+
def post_exec(self) -> None:
|
|
82
|
+
if (
|
|
83
|
+
self.isdelete
|
|
84
|
+
and cast(SQLCompiler, self.compiled).effective_returning
|
|
85
|
+
and not self.cursor.description
|
|
86
|
+
):
|
|
87
|
+
# All MySQL/mariadb drivers appear to not include
|
|
88
|
+
# cursor.description for DELETE..RETURNING with no rows if the
|
|
89
|
+
# WHERE criteria is a straight "false" condition such as our EMPTY
|
|
90
|
+
# IN condition. manufacture an empty result in this case (issue
|
|
91
|
+
# #10505)
|
|
92
|
+
#
|
|
93
|
+
# taken from cx_Oracle implementation
|
|
94
|
+
self.cursor_fetch_strategy = (
|
|
95
|
+
_cursor.FullyBufferedCursorFetchStrategy(
|
|
96
|
+
self.cursor,
|
|
97
|
+
[
|
|
98
|
+
(entry.keyname, None) # type: ignore[misc]
|
|
99
|
+
for entry in cast(
|
|
100
|
+
SQLCompiler, self.compiled
|
|
101
|
+
)._result_columns
|
|
102
|
+
],
|
|
103
|
+
[],
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
def fire_sequence(
|
|
108
|
+
self, seq: Sequence_SchemaItem, type_: sqltypes.Integer
|
|
109
|
+
) -> int:
|
|
110
|
+
return self._execute_scalar( # type: ignore[no-any-return]
|
|
111
|
+
(
|
|
112
|
+
"select nextval(%s)"
|
|
113
|
+
% self.identifier_preparer.format_sequence(seq)
|
|
114
|
+
),
|
|
115
|
+
type_,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class MariaDBIdentifierPreparerShim(IdentifierPreparer):
|
|
120
|
+
def _set_mariadb(self) -> None:
|
|
121
|
+
self.reserved_words = RESERVED_WORDS_MARIADB
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class MariaDBSQLCompilerShim(SQLCompiler):
|
|
125
|
+
def visit_sequence(self, sequence: sa_schema.Sequence, **kw: Any) -> str:
|
|
126
|
+
return "nextval(%s)" % self.preparer.format_sequence(sequence)
|
|
127
|
+
|
|
128
|
+
def _mariadb_regexp_flags(
|
|
129
|
+
self, flags: str, pattern: elements.ColumnElement[Any], **kw: Any
|
|
130
|
+
) -> str:
|
|
131
|
+
return "CONCAT('(?', %s, ')', %s)" % (
|
|
132
|
+
self.render_literal_value(flags, sqltypes.STRINGTYPE),
|
|
133
|
+
self.process(pattern, **kw),
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
def _mariadb_regexp_match(
|
|
137
|
+
self,
|
|
138
|
+
op_string: str,
|
|
139
|
+
binary: elements.BinaryExpression[Any],
|
|
140
|
+
operator: Any,
|
|
141
|
+
**kw: Any,
|
|
142
|
+
) -> str:
|
|
143
|
+
flags = binary.modifiers["flags"]
|
|
144
|
+
return "%s%s%s" % (
|
|
145
|
+
self.process(binary.left, **kw),
|
|
146
|
+
op_string,
|
|
147
|
+
self._mariadb_regexp_flags(flags, binary.right),
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
def _mariadb_regexp_replace_op_binary(
|
|
151
|
+
self, binary: elements.BinaryExpression[Any], operator: Any, **kw: Any
|
|
152
|
+
) -> str:
|
|
153
|
+
flags = binary.modifiers["flags"]
|
|
154
|
+
return "REGEXP_REPLACE(%s, %s, %s)" % (
|
|
155
|
+
self.process(binary.left, **kw),
|
|
156
|
+
self._mariadb_regexp_flags(flags, binary.right.clauses[0]),
|
|
157
|
+
self.process(binary.right.clauses[1], **kw),
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
def _mariadb_visit_drop_check_constraint(
|
|
161
|
+
self, drop: ddl.DropConstraint, **kw: Any
|
|
162
|
+
) -> str:
|
|
163
|
+
constraint = drop.element
|
|
164
|
+
qual = "CONSTRAINT "
|
|
165
|
+
const = self.preparer.format_constraint(constraint)
|
|
166
|
+
return "ALTER TABLE %s DROP %s%s" % (
|
|
167
|
+
self.preparer.format_table(constraint.table),
|
|
168
|
+
qual,
|
|
169
|
+
const,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class MariaDBDDLCompilerShim(DDLCompiler):
|
|
174
|
+
dialect: MariaDBShim
|
|
175
|
+
|
|
176
|
+
def _mariadb_get_column_specification(
|
|
177
|
+
self, column: sa_schema.Column[Any], **kw: Any
|
|
178
|
+
) -> str:
|
|
179
|
+
|
|
180
|
+
if (
|
|
181
|
+
column.computed is not None
|
|
182
|
+
and column._user_defined_nullable is SchemaConst.NULL_UNSPECIFIED
|
|
183
|
+
):
|
|
184
|
+
kw["_force_column_to_nullable"] = True
|
|
185
|
+
|
|
186
|
+
return self._mysql_get_column_specification(column, **kw)
|
|
187
|
+
|
|
188
|
+
def _mysql_get_column_specification(
|
|
189
|
+
self,
|
|
190
|
+
column: sa_schema.Column[Any],
|
|
191
|
+
*,
|
|
192
|
+
_force_column_to_nullable: bool = False,
|
|
193
|
+
**kw: Any,
|
|
194
|
+
) -> str:
|
|
195
|
+
raise NotImplementedError()
|
|
196
|
+
|
|
197
|
+
def get_identity_options(self, identity_options: IdentityOptions) -> str:
|
|
198
|
+
text = super().get_identity_options(identity_options)
|
|
199
|
+
text = text.replace("NO CYCLE", "NOCYCLE")
|
|
200
|
+
return text
|
|
201
|
+
|
|
202
|
+
def _mariadb_visit_drop_check_constraint(
|
|
203
|
+
self, drop: ddl.DropConstraint, **kw: Any
|
|
204
|
+
) -> str:
|
|
205
|
+
constraint = drop.element
|
|
206
|
+
qual = "CONSTRAINT "
|
|
207
|
+
const = self.preparer.format_constraint(constraint)
|
|
208
|
+
return "ALTER TABLE %s DROP %s%s" % (
|
|
209
|
+
self.preparer.format_table(constraint.table),
|
|
210
|
+
qual,
|
|
211
|
+
const,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class MariaDBShim(DefaultDialect):
|
|
216
|
+
server_version_info: tuple[int, ...]
|
|
217
|
+
is_mariadb: bool
|
|
218
|
+
_allows_uuid_binds = False
|
|
219
|
+
|
|
220
|
+
identifier_preparer: MySQLIdentifierPreparer
|
|
221
|
+
preparer: Type[MySQLIdentifierPreparer]
|
|
222
|
+
|
|
223
|
+
def _set_mariadb(
|
|
224
|
+
self, is_mariadb: Optional[bool], server_version_info: tuple[int, ...]
|
|
225
|
+
) -> None:
|
|
226
|
+
if is_mariadb is None:
|
|
227
|
+
return
|
|
228
|
+
|
|
229
|
+
if not is_mariadb and self.is_mariadb:
|
|
230
|
+
raise exc.InvalidRequestError(
|
|
231
|
+
"MySQL version %s is not a MariaDB variant."
|
|
232
|
+
% (".".join(map(str, server_version_info)),)
|
|
233
|
+
)
|
|
234
|
+
if is_mariadb:
|
|
235
|
+
assert isinstance(self.colspecs, dict)
|
|
236
|
+
self.colspecs = util.update_copy(
|
|
237
|
+
self.colspecs, {Uuid: _MariaDBUUID}
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
self.identifier_preparer = self.preparer(self)
|
|
241
|
+
self.identifier_preparer._set_mariadb()
|
|
242
|
+
|
|
243
|
+
# this will be updated on first connect in initialize()
|
|
244
|
+
# if using older mariadb version
|
|
245
|
+
self.delete_returning = True
|
|
246
|
+
self.insert_returning = True
|
|
247
|
+
|
|
248
|
+
self.is_mariadb = is_mariadb
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def _mariadb_normalized_version_info(self) -> tuple[int, ...]:
|
|
252
|
+
return self.server_version_info
|
|
253
|
+
|
|
254
|
+
@property
|
|
255
|
+
def _is_mariadb(self) -> bool:
|
|
256
|
+
return self.is_mariadb
|
|
257
|
+
|
|
258
|
+
@classmethod
|
|
259
|
+
def _is_mariadb_from_url(cls, url: URL) -> bool:
|
|
260
|
+
dbapi = cls.import_dbapi()
|
|
261
|
+
dialect = cls(dbapi=dbapi)
|
|
262
|
+
|
|
263
|
+
cargs, cparams = dialect.create_connect_args(url)
|
|
264
|
+
conn = dialect.connect(*cargs, **cparams)
|
|
265
|
+
try:
|
|
266
|
+
cursor = conn.cursor()
|
|
267
|
+
cursor.execute("SELECT VERSION() LIKE '%MariaDB%'")
|
|
268
|
+
val = cursor.fetchone()[0] # type: ignore[index]
|
|
269
|
+
except:
|
|
270
|
+
raise
|
|
271
|
+
else:
|
|
272
|
+
return bool(val)
|
|
273
|
+
finally:
|
|
274
|
+
conn.close()
|
|
275
|
+
|
|
276
|
+
def _initialize_mariadb(self, connection: Connection) -> None:
|
|
277
|
+
assert self.is_mariadb
|
|
278
|
+
|
|
279
|
+
self.supports_sequences = self.server_version_info >= (10, 3)
|
|
280
|
+
|
|
281
|
+
self.delete_returning = self.server_version_info >= (10, 0, 5)
|
|
282
|
+
|
|
283
|
+
self.insert_returning = self.server_version_info >= (10, 5)
|
|
284
|
+
|
|
285
|
+
self._warn_for_known_db_issues()
|
|
286
|
+
|
|
287
|
+
self.supports_native_uuid = (
|
|
288
|
+
self.server_version_info is not None
|
|
289
|
+
and self.server_version_info >= (10, 7)
|
|
290
|
+
)
|
|
291
|
+
self._allows_uuid_binds = True
|
|
292
|
+
|
|
293
|
+
# ref https://mariadb.com/kb/en/mariadb-1021-release-notes/
|
|
294
|
+
self._support_default_function = self.server_version_info >= (10, 2, 1)
|
|
295
|
+
|
|
296
|
+
# ref https://mariadb.com/kb/en/mariadb-1045-release-notes/
|
|
297
|
+
self._support_float_cast = self.server_version_info >= (10, 4, 5)
|
|
298
|
+
|
|
299
|
+
def _warn_for_known_db_issues(self) -> None:
|
|
300
|
+
if self.is_mariadb:
|
|
301
|
+
mdb_version = self.server_version_info
|
|
302
|
+
assert mdb_version is not None
|
|
303
|
+
if mdb_version > (10, 2) and mdb_version < (10, 2, 9):
|
|
304
|
+
util.warn(
|
|
305
|
+
"MariaDB %r before 10.2.9 has known issues regarding "
|
|
306
|
+
"CHECK constraints, which impact handling of NULL values "
|
|
307
|
+
"with SQLAlchemy's boolean datatype (MDEV-13596). An "
|
|
308
|
+
"additional issue prevents proper migrations of columns "
|
|
309
|
+
"with CHECK constraints (MDEV-11114). Please upgrade to "
|
|
310
|
+
"MariaDB 10.2.9 or greater, or use the MariaDB 10.1 "
|
|
311
|
+
"series, to avoid these issues." % (mdb_version,)
|
|
312
|
+
)
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# dialects/mysql/aiomysql.py
|
|
2
|
+
# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors <see AUTHORS
|
|
3
|
+
# 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
|
+
r"""
|
|
9
|
+
.. dialect:: mysql+aiomysql
|
|
10
|
+
:name: aiomysql
|
|
11
|
+
:dbapi: aiomysql
|
|
12
|
+
:connectstring: mysql+aiomysql://user:password@host:port/dbname[?key=value&key=value...]
|
|
13
|
+
:url: https://github.com/aio-libs/aiomysql
|
|
14
|
+
|
|
15
|
+
The aiomysql dialect is SQLAlchemy's second Python asyncio dialect.
|
|
16
|
+
|
|
17
|
+
Using a special asyncio mediation layer, the aiomysql dialect is usable
|
|
18
|
+
as the backend for the :ref:`SQLAlchemy asyncio <asyncio_toplevel>`
|
|
19
|
+
extension package.
|
|
20
|
+
|
|
21
|
+
This dialect should normally be used only with the
|
|
22
|
+
:func:`_asyncio.create_async_engine` engine creation function::
|
|
23
|
+
|
|
24
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
25
|
+
|
|
26
|
+
engine = create_async_engine(
|
|
27
|
+
"mysql+aiomysql://user:pass@hostname/dbname?charset=utf8mb4"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
""" # noqa
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
from types import ModuleType
|
|
34
|
+
from typing import Any
|
|
35
|
+
from typing import Optional
|
|
36
|
+
from typing import TYPE_CHECKING
|
|
37
|
+
from typing import Union
|
|
38
|
+
|
|
39
|
+
from .pymysql import MySQLDialect_pymysql
|
|
40
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_connection
|
|
41
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_cursor
|
|
42
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_module
|
|
43
|
+
from ...connectors.asyncio import AsyncAdapt_dbapi_ss_cursor
|
|
44
|
+
from ...connectors.asyncio import AsyncAdapt_terminate
|
|
45
|
+
from ...util.concurrency import await_
|
|
46
|
+
|
|
47
|
+
if TYPE_CHECKING:
|
|
48
|
+
|
|
49
|
+
from ...connectors.asyncio import AsyncIODBAPIConnection
|
|
50
|
+
from ...connectors.asyncio import AsyncIODBAPICursor
|
|
51
|
+
from ...engine.interfaces import ConnectArgsType
|
|
52
|
+
from ...engine.interfaces import DBAPIConnection
|
|
53
|
+
from ...engine.interfaces import DBAPICursor
|
|
54
|
+
from ...engine.interfaces import DBAPIModule
|
|
55
|
+
from ...engine.interfaces import PoolProxiedConnection
|
|
56
|
+
from ...engine.url import URL
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class AsyncAdapt_aiomysql_cursor(AsyncAdapt_dbapi_cursor):
|
|
60
|
+
__slots__ = ()
|
|
61
|
+
|
|
62
|
+
def _make_new_cursor(
|
|
63
|
+
self, connection: AsyncIODBAPIConnection
|
|
64
|
+
) -> AsyncIODBAPICursor:
|
|
65
|
+
return connection.cursor(self._adapt_connection.dbapi.Cursor)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class AsyncAdapt_aiomysql_ss_cursor(
|
|
69
|
+
AsyncAdapt_dbapi_ss_cursor, AsyncAdapt_aiomysql_cursor
|
|
70
|
+
):
|
|
71
|
+
__slots__ = ()
|
|
72
|
+
|
|
73
|
+
def _make_new_cursor(
|
|
74
|
+
self, connection: AsyncIODBAPIConnection
|
|
75
|
+
) -> AsyncIODBAPICursor:
|
|
76
|
+
return connection.cursor(
|
|
77
|
+
self._adapt_connection.dbapi.aiomysql.cursors.SSCursor
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class AsyncAdapt_aiomysql_connection(
|
|
82
|
+
AsyncAdapt_terminate, AsyncAdapt_dbapi_connection
|
|
83
|
+
):
|
|
84
|
+
__slots__ = ()
|
|
85
|
+
|
|
86
|
+
_cursor_cls = AsyncAdapt_aiomysql_cursor
|
|
87
|
+
_ss_cursor_cls = AsyncAdapt_aiomysql_ss_cursor
|
|
88
|
+
|
|
89
|
+
def ping(self, reconnect: bool) -> None:
|
|
90
|
+
assert not reconnect
|
|
91
|
+
await_(self._connection.ping(reconnect))
|
|
92
|
+
|
|
93
|
+
def character_set_name(self) -> Optional[str]:
|
|
94
|
+
return self._connection.character_set_name() # type: ignore[no-any-return] # noqa: E501
|
|
95
|
+
|
|
96
|
+
def autocommit(self, value: Any) -> None:
|
|
97
|
+
await_(self._connection.autocommit(value))
|
|
98
|
+
|
|
99
|
+
def get_autocommit(self) -> bool:
|
|
100
|
+
return self._connection.get_autocommit() # type: ignore
|
|
101
|
+
|
|
102
|
+
def close(self) -> None:
|
|
103
|
+
await_(self._connection.ensure_closed())
|
|
104
|
+
|
|
105
|
+
async def _terminate_graceful_close(self) -> None:
|
|
106
|
+
await self._connection.ensure_closed()
|
|
107
|
+
|
|
108
|
+
def _terminate_force_close(self) -> None:
|
|
109
|
+
# it's not awaitable.
|
|
110
|
+
self._connection.close()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class AsyncAdapt_aiomysql_dbapi(AsyncAdapt_dbapi_module):
|
|
114
|
+
def __init__(self, aiomysql: ModuleType, pymysql: ModuleType):
|
|
115
|
+
super().__init__(aiomysql, dbapi_module=pymysql)
|
|
116
|
+
self.aiomysql = aiomysql
|
|
117
|
+
self.pymysql = pymysql
|
|
118
|
+
self.paramstyle = "format"
|
|
119
|
+
self._init_dbapi_attributes()
|
|
120
|
+
self.Cursor, self.SSCursor = self._init_cursors_subclasses()
|
|
121
|
+
|
|
122
|
+
def _init_dbapi_attributes(self) -> None:
|
|
123
|
+
for name in (
|
|
124
|
+
"Warning",
|
|
125
|
+
"Error",
|
|
126
|
+
"InterfaceError",
|
|
127
|
+
"DataError",
|
|
128
|
+
"DatabaseError",
|
|
129
|
+
"OperationalError",
|
|
130
|
+
"InterfaceError",
|
|
131
|
+
"IntegrityError",
|
|
132
|
+
"ProgrammingError",
|
|
133
|
+
"InternalError",
|
|
134
|
+
"NotSupportedError",
|
|
135
|
+
):
|
|
136
|
+
setattr(self, name, getattr(self.aiomysql, name))
|
|
137
|
+
|
|
138
|
+
for name in (
|
|
139
|
+
"NUMBER",
|
|
140
|
+
"STRING",
|
|
141
|
+
"DATETIME",
|
|
142
|
+
"BINARY",
|
|
143
|
+
"TIMESTAMP",
|
|
144
|
+
"Binary",
|
|
145
|
+
):
|
|
146
|
+
setattr(self, name, getattr(self.pymysql, name))
|
|
147
|
+
|
|
148
|
+
def connect(self, *arg: Any, **kw: Any) -> AsyncAdapt_aiomysql_connection:
|
|
149
|
+
creator_fn = kw.pop("async_creator_fn", self.aiomysql.connect)
|
|
150
|
+
|
|
151
|
+
return await_(
|
|
152
|
+
AsyncAdapt_aiomysql_connection.create(
|
|
153
|
+
self,
|
|
154
|
+
creator_fn(*arg, **kw),
|
|
155
|
+
)
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
def _init_cursors_subclasses(
|
|
159
|
+
self,
|
|
160
|
+
) -> tuple[AsyncIODBAPICursor, AsyncIODBAPICursor]:
|
|
161
|
+
# suppress unconditional warning emitted by aiomysql
|
|
162
|
+
class Cursor(self.aiomysql.Cursor): # type: ignore[misc, name-defined]
|
|
163
|
+
async def _show_warnings(
|
|
164
|
+
self, conn: AsyncIODBAPIConnection
|
|
165
|
+
) -> None:
|
|
166
|
+
pass
|
|
167
|
+
|
|
168
|
+
class SSCursor(self.aiomysql.SSCursor): # type: ignore[misc, name-defined] # noqa: E501
|
|
169
|
+
async def _show_warnings(
|
|
170
|
+
self, conn: AsyncIODBAPIConnection
|
|
171
|
+
) -> None:
|
|
172
|
+
pass
|
|
173
|
+
|
|
174
|
+
return Cursor, SSCursor # type: ignore[return-value]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class MySQLDialect_aiomysql(MySQLDialect_pymysql):
|
|
178
|
+
driver = "aiomysql"
|
|
179
|
+
supports_statement_cache = True
|
|
180
|
+
|
|
181
|
+
supports_server_side_cursors = True
|
|
182
|
+
_sscursor = AsyncAdapt_aiomysql_ss_cursor
|
|
183
|
+
|
|
184
|
+
is_async = True
|
|
185
|
+
has_terminate = True
|
|
186
|
+
|
|
187
|
+
@classmethod
|
|
188
|
+
def import_dbapi(cls) -> AsyncAdapt_aiomysql_dbapi:
|
|
189
|
+
return AsyncAdapt_aiomysql_dbapi(
|
|
190
|
+
__import__("aiomysql"), __import__("pymysql")
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
def do_terminate(self, dbapi_connection: DBAPIConnection) -> None:
|
|
194
|
+
dbapi_connection.terminate()
|
|
195
|
+
|
|
196
|
+
def create_connect_args(
|
|
197
|
+
self, url: URL, _translate_args: Optional[dict[str, Any]] = None
|
|
198
|
+
) -> ConnectArgsType:
|
|
199
|
+
return super().create_connect_args(
|
|
200
|
+
url, _translate_args=dict(username="user", database="db")
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
def is_disconnect(
|
|
204
|
+
self,
|
|
205
|
+
e: DBAPIModule.Error,
|
|
206
|
+
connection: Optional[Union[PoolProxiedConnection, DBAPIConnection]],
|
|
207
|
+
cursor: Optional[DBAPICursor],
|
|
208
|
+
) -> bool:
|
|
209
|
+
if super().is_disconnect(e, connection, cursor):
|
|
210
|
+
return True
|
|
211
|
+
else:
|
|
212
|
+
str_e = str(e).lower()
|
|
213
|
+
return "not connected" in str_e
|
|
214
|
+
|
|
215
|
+
def _found_rows_client_flag(self) -> int:
|
|
216
|
+
from pymysql.constants import CLIENT # type: ignore
|
|
217
|
+
|
|
218
|
+
return CLIENT.FOUND_ROWS # type: ignore[no-any-return]
|
|
219
|
+
|
|
220
|
+
def get_driver_connection(
|
|
221
|
+
self, connection: DBAPIConnection
|
|
222
|
+
) -> AsyncIODBAPIConnection:
|
|
223
|
+
return connection._connection # type: ignore[no-any-return]
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
dialect = MySQLDialect_aiomysql
|