SQLAlchemy 2.0.36__cp313-cp313-win_amd64.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-2.0.36.dist-info/LICENSE +19 -0
- SQLAlchemy-2.0.36.dist-info/METADATA +243 -0
- SQLAlchemy-2.0.36.dist-info/RECORD +273 -0
- SQLAlchemy-2.0.36.dist-info/WHEEL +5 -0
- SQLAlchemy-2.0.36.dist-info/top_level.txt +1 -0
- sqlalchemy/__init__.py +294 -0
- sqlalchemy/connectors/__init__.py +18 -0
- sqlalchemy/connectors/aioodbc.py +174 -0
- sqlalchemy/connectors/asyncio.py +213 -0
- sqlalchemy/connectors/pyodbc.py +249 -0
- sqlalchemy/cyextension/__init__.py +6 -0
- sqlalchemy/cyextension/collections.cp313-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/collections.pyx +409 -0
- sqlalchemy/cyextension/immutabledict.cp313-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/immutabledict.pxd +8 -0
- sqlalchemy/cyextension/immutabledict.pyx +133 -0
- sqlalchemy/cyextension/processors.cp313-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/processors.pyx +68 -0
- sqlalchemy/cyextension/resultproxy.cp313-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/resultproxy.pyx +102 -0
- sqlalchemy/cyextension/util.cp313-win_amd64.pyd +0 -0
- sqlalchemy/cyextension/util.pyx +91 -0
- sqlalchemy/dialects/__init__.py +61 -0
- sqlalchemy/dialects/_typing.py +25 -0
- sqlalchemy/dialects/mssql/__init__.py +88 -0
- sqlalchemy/dialects/mssql/aioodbc.py +64 -0
- sqlalchemy/dialects/mssql/base.py +4010 -0
- sqlalchemy/dialects/mssql/information_schema.py +254 -0
- sqlalchemy/dialects/mssql/json.py +133 -0
- sqlalchemy/dialects/mssql/provision.py +162 -0
- sqlalchemy/dialects/mssql/pymssql.py +126 -0
- sqlalchemy/dialects/mssql/pyodbc.py +745 -0
- sqlalchemy/dialects/mysql/__init__.py +101 -0
- sqlalchemy/dialects/mysql/aiomysql.py +333 -0
- sqlalchemy/dialects/mysql/asyncmy.py +337 -0
- sqlalchemy/dialects/mysql/base.py +3494 -0
- sqlalchemy/dialects/mysql/cymysql.py +84 -0
- sqlalchemy/dialects/mysql/dml.py +219 -0
- sqlalchemy/dialects/mysql/enumerated.py +244 -0
- sqlalchemy/dialects/mysql/expression.py +141 -0
- sqlalchemy/dialects/mysql/json.py +81 -0
- sqlalchemy/dialects/mysql/mariadb.py +32 -0
- sqlalchemy/dialects/mysql/mariadbconnector.py +277 -0
- sqlalchemy/dialects/mysql/mysqlconnector.py +180 -0
- sqlalchemy/dialects/mysql/mysqldb.py +303 -0
- sqlalchemy/dialects/mysql/provision.py +110 -0
- sqlalchemy/dialects/mysql/pymysql.py +137 -0
- sqlalchemy/dialects/mysql/pyodbc.py +138 -0
- sqlalchemy/dialects/mysql/reflection.py +677 -0
- sqlalchemy/dialects/mysql/reserved_words.py +571 -0
- sqlalchemy/dialects/mysql/types.py +774 -0
- sqlalchemy/dialects/oracle/__init__.py +67 -0
- sqlalchemy/dialects/oracle/base.py +3271 -0
- sqlalchemy/dialects/oracle/cx_oracle.py +1483 -0
- sqlalchemy/dialects/oracle/dictionary.py +507 -0
- sqlalchemy/dialects/oracle/oracledb.py +431 -0
- sqlalchemy/dialects/oracle/provision.py +220 -0
- sqlalchemy/dialects/oracle/types.py +287 -0
- sqlalchemy/dialects/postgresql/__init__.py +167 -0
- sqlalchemy/dialects/postgresql/_psycopg_common.py +187 -0
- sqlalchemy/dialects/postgresql/array.py +425 -0
- sqlalchemy/dialects/postgresql/asyncpg.py +1274 -0
- sqlalchemy/dialects/postgresql/base.py +5008 -0
- sqlalchemy/dialects/postgresql/dml.py +310 -0
- sqlalchemy/dialects/postgresql/ext.py +496 -0
- sqlalchemy/dialects/postgresql/hstore.py +397 -0
- sqlalchemy/dialects/postgresql/json.py +333 -0
- sqlalchemy/dialects/postgresql/named_types.py +509 -0
- sqlalchemy/dialects/postgresql/operators.py +129 -0
- sqlalchemy/dialects/postgresql/pg8000.py +662 -0
- sqlalchemy/dialects/postgresql/pg_catalog.py +300 -0
- sqlalchemy/dialects/postgresql/provision.py +175 -0
- sqlalchemy/dialects/postgresql/psycopg.py +772 -0
- sqlalchemy/dialects/postgresql/psycopg2.py +886 -0
- sqlalchemy/dialects/postgresql/psycopg2cffi.py +61 -0
- sqlalchemy/dialects/postgresql/ranges.py +1029 -0
- sqlalchemy/dialects/postgresql/types.py +303 -0
- sqlalchemy/dialects/sqlite/__init__.py +57 -0
- sqlalchemy/dialects/sqlite/aiosqlite.py +396 -0
- sqlalchemy/dialects/sqlite/base.py +2805 -0
- sqlalchemy/dialects/sqlite/dml.py +240 -0
- sqlalchemy/dialects/sqlite/json.py +92 -0
- sqlalchemy/dialects/sqlite/provision.py +198 -0
- sqlalchemy/dialects/sqlite/pysqlcipher.py +155 -0
- sqlalchemy/dialects/sqlite/pysqlite.py +756 -0
- sqlalchemy/dialects/type_migration_guidelines.txt +145 -0
- sqlalchemy/engine/__init__.py +62 -0
- sqlalchemy/engine/_py_processors.py +136 -0
- sqlalchemy/engine/_py_row.py +128 -0
- sqlalchemy/engine/_py_util.py +74 -0
- sqlalchemy/engine/base.py +3375 -0
- sqlalchemy/engine/characteristics.py +155 -0
- sqlalchemy/engine/create.py +875 -0
- sqlalchemy/engine/cursor.py +2181 -0
- sqlalchemy/engine/default.py +2365 -0
- sqlalchemy/engine/events.py +951 -0
- sqlalchemy/engine/interfaces.py +3403 -0
- sqlalchemy/engine/mock.py +131 -0
- sqlalchemy/engine/processors.py +61 -0
- sqlalchemy/engine/reflection.py +2098 -0
- sqlalchemy/engine/result.py +2382 -0
- sqlalchemy/engine/row.py +401 -0
- sqlalchemy/engine/strategies.py +19 -0
- sqlalchemy/engine/url.py +910 -0
- sqlalchemy/engine/util.py +167 -0
- sqlalchemy/event/__init__.py +25 -0
- sqlalchemy/event/api.py +225 -0
- sqlalchemy/event/attr.py +655 -0
- sqlalchemy/event/base.py +470 -0
- sqlalchemy/event/legacy.py +246 -0
- sqlalchemy/event/registry.py +386 -0
- sqlalchemy/events.py +17 -0
- sqlalchemy/exc.py +830 -0
- sqlalchemy/ext/__init__.py +11 -0
- sqlalchemy/ext/associationproxy.py +2013 -0
- sqlalchemy/ext/asyncio/__init__.py +25 -0
- sqlalchemy/ext/asyncio/base.py +279 -0
- sqlalchemy/ext/asyncio/engine.py +1466 -0
- sqlalchemy/ext/asyncio/exc.py +21 -0
- sqlalchemy/ext/asyncio/result.py +961 -0
- sqlalchemy/ext/asyncio/scoping.py +1614 -0
- sqlalchemy/ext/asyncio/session.py +1936 -0
- sqlalchemy/ext/automap.py +1691 -0
- sqlalchemy/ext/baked.py +574 -0
- sqlalchemy/ext/compiler.py +570 -0
- sqlalchemy/ext/declarative/__init__.py +65 -0
- sqlalchemy/ext/declarative/extensions.py +548 -0
- sqlalchemy/ext/horizontal_shard.py +481 -0
- sqlalchemy/ext/hybrid.py +1514 -0
- sqlalchemy/ext/indexable.py +341 -0
- sqlalchemy/ext/instrumentation.py +450 -0
- sqlalchemy/ext/mutable.py +1073 -0
- sqlalchemy/ext/mypy/__init__.py +6 -0
- sqlalchemy/ext/mypy/apply.py +320 -0
- sqlalchemy/ext/mypy/decl_class.py +515 -0
- sqlalchemy/ext/mypy/infer.py +590 -0
- sqlalchemy/ext/mypy/names.py +335 -0
- sqlalchemy/ext/mypy/plugin.py +303 -0
- sqlalchemy/ext/mypy/util.py +357 -0
- sqlalchemy/ext/orderinglist.py +416 -0
- sqlalchemy/ext/serializer.py +181 -0
- sqlalchemy/future/__init__.py +16 -0
- sqlalchemy/future/engine.py +15 -0
- sqlalchemy/inspection.py +174 -0
- sqlalchemy/log.py +288 -0
- sqlalchemy/orm/__init__.py +170 -0
- sqlalchemy/orm/_orm_constructors.py +2571 -0
- sqlalchemy/orm/_typing.py +179 -0
- sqlalchemy/orm/attributes.py +2835 -0
- sqlalchemy/orm/base.py +973 -0
- sqlalchemy/orm/bulk_persistence.py +2123 -0
- sqlalchemy/orm/clsregistry.py +571 -0
- sqlalchemy/orm/collections.py +1620 -0
- sqlalchemy/orm/context.py +3268 -0
- sqlalchemy/orm/decl_api.py +1883 -0
- sqlalchemy/orm/decl_base.py +2190 -0
- sqlalchemy/orm/dependency.py +1304 -0
- sqlalchemy/orm/descriptor_props.py +1076 -0
- sqlalchemy/orm/dynamic.py +300 -0
- sqlalchemy/orm/evaluator.py +379 -0
- sqlalchemy/orm/events.py +3261 -0
- sqlalchemy/orm/exc.py +228 -0
- sqlalchemy/orm/identity.py +302 -0
- sqlalchemy/orm/instrumentation.py +754 -0
- sqlalchemy/orm/interfaces.py +1474 -0
- sqlalchemy/orm/loading.py +1682 -0
- sqlalchemy/orm/mapped_collection.py +557 -0
- sqlalchemy/orm/mapper.py +4432 -0
- sqlalchemy/orm/path_registry.py +811 -0
- sqlalchemy/orm/persistence.py +1782 -0
- sqlalchemy/orm/properties.py +886 -0
- sqlalchemy/orm/query.py +3396 -0
- sqlalchemy/orm/relationships.py +3500 -0
- sqlalchemy/orm/scoping.py +2165 -0
- sqlalchemy/orm/session.py +5301 -0
- sqlalchemy/orm/state.py +1143 -0
- sqlalchemy/orm/state_changes.py +198 -0
- sqlalchemy/orm/strategies.py +3473 -0
- sqlalchemy/orm/strategy_options.py +2569 -0
- sqlalchemy/orm/sync.py +164 -0
- sqlalchemy/orm/unitofwork.py +796 -0
- sqlalchemy/orm/util.py +2424 -0
- sqlalchemy/orm/writeonly.py +678 -0
- sqlalchemy/pool/__init__.py +44 -0
- sqlalchemy/pool/base.py +1515 -0
- sqlalchemy/pool/events.py +370 -0
- sqlalchemy/pool/impl.py +581 -0
- sqlalchemy/py.typed +0 -0
- sqlalchemy/schema.py +70 -0
- sqlalchemy/sql/__init__.py +145 -0
- sqlalchemy/sql/_dml_constructors.py +140 -0
- sqlalchemy/sql/_elements_constructors.py +1850 -0
- sqlalchemy/sql/_orm_types.py +20 -0
- sqlalchemy/sql/_py_util.py +75 -0
- sqlalchemy/sql/_selectable_constructors.py +635 -0
- sqlalchemy/sql/_typing.py +460 -0
- sqlalchemy/sql/annotation.py +585 -0
- sqlalchemy/sql/base.py +2185 -0
- sqlalchemy/sql/cache_key.py +1057 -0
- sqlalchemy/sql/coercions.py +1405 -0
- sqlalchemy/sql/compiler.py +7818 -0
- sqlalchemy/sql/crud.py +1669 -0
- sqlalchemy/sql/ddl.py +1378 -0
- sqlalchemy/sql/default_comparator.py +552 -0
- sqlalchemy/sql/dml.py +1817 -0
- sqlalchemy/sql/elements.py +5499 -0
- sqlalchemy/sql/events.py +455 -0
- sqlalchemy/sql/expression.py +162 -0
- sqlalchemy/sql/functions.py +2055 -0
- sqlalchemy/sql/lambdas.py +1449 -0
- sqlalchemy/sql/naming.py +212 -0
- sqlalchemy/sql/operators.py +2579 -0
- sqlalchemy/sql/roles.py +323 -0
- sqlalchemy/sql/schema.py +6158 -0
- sqlalchemy/sql/selectable.py +7004 -0
- sqlalchemy/sql/sqltypes.py +3827 -0
- sqlalchemy/sql/traversals.py +1024 -0
- sqlalchemy/sql/type_api.py +2339 -0
- sqlalchemy/sql/util.py +1486 -0
- sqlalchemy/sql/visitors.py +1165 -0
- sqlalchemy/testing/__init__.py +96 -0
- sqlalchemy/testing/assertions.py +989 -0
- sqlalchemy/testing/assertsql.py +516 -0
- sqlalchemy/testing/asyncio.py +135 -0
- sqlalchemy/testing/config.py +427 -0
- sqlalchemy/testing/engines.py +472 -0
- sqlalchemy/testing/entities.py +117 -0
- sqlalchemy/testing/exclusions.py +435 -0
- sqlalchemy/testing/fixtures/__init__.py +28 -0
- sqlalchemy/testing/fixtures/base.py +366 -0
- sqlalchemy/testing/fixtures/mypy.py +312 -0
- sqlalchemy/testing/fixtures/orm.py +227 -0
- sqlalchemy/testing/fixtures/sql.py +503 -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 +779 -0
- sqlalchemy/testing/plugin/pytestplugin.py +868 -0
- sqlalchemy/testing/profiling.py +324 -0
- sqlalchemy/testing/provision.py +496 -0
- sqlalchemy/testing/requirements.py +1818 -0
- sqlalchemy/testing/schema.py +224 -0
- sqlalchemy/testing/suite/__init__.py +19 -0
- sqlalchemy/testing/suite/test_cte.py +211 -0
- sqlalchemy/testing/suite/test_ddl.py +389 -0
- sqlalchemy/testing/suite/test_deprecations.py +153 -0
- sqlalchemy/testing/suite/test_dialect.py +740 -0
- sqlalchemy/testing/suite/test_insert.py +630 -0
- sqlalchemy/testing/suite/test_reflection.py +3225 -0
- sqlalchemy/testing/suite/test_results.py +502 -0
- sqlalchemy/testing/suite/test_rowcount.py +258 -0
- sqlalchemy/testing/suite/test_select.py +1999 -0
- sqlalchemy/testing/suite/test_sequence.py +317 -0
- sqlalchemy/testing/suite/test_types.py +2141 -0
- sqlalchemy/testing/suite/test_unicode_ddl.py +189 -0
- sqlalchemy/testing/suite/test_update_delete.py +139 -0
- sqlalchemy/testing/util.py +537 -0
- sqlalchemy/testing/warnings.py +52 -0
- sqlalchemy/types.py +76 -0
- sqlalchemy/util/__init__.py +160 -0
- sqlalchemy/util/_collections.py +715 -0
- sqlalchemy/util/_concurrency_py3k.py +288 -0
- sqlalchemy/util/_has_cy.py +40 -0
- sqlalchemy/util/_py_collections.py +541 -0
- sqlalchemy/util/compat.py +301 -0
- sqlalchemy/util/concurrency.py +108 -0
- sqlalchemy/util/deprecations.py +401 -0
- sqlalchemy/util/langhelpers.py +2218 -0
- sqlalchemy/util/preloaded.py +150 -0
- sqlalchemy/util/queue.py +322 -0
- sqlalchemy/util/tool_support.py +201 -0
- sqlalchemy/util/topological.py +120 -0
- sqlalchemy/util/typing.py +629 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# dialects/mysql/__init__.py
|
|
2
|
+
# Copyright (C) 2005-2024 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 .expression import match
|
|
56
|
+
from ...util import compat
|
|
57
|
+
|
|
58
|
+
# default dialect
|
|
59
|
+
base.dialect = dialect = mysqldb.dialect
|
|
60
|
+
|
|
61
|
+
__all__ = (
|
|
62
|
+
"BIGINT",
|
|
63
|
+
"BINARY",
|
|
64
|
+
"BIT",
|
|
65
|
+
"BLOB",
|
|
66
|
+
"BOOLEAN",
|
|
67
|
+
"CHAR",
|
|
68
|
+
"DATE",
|
|
69
|
+
"DATETIME",
|
|
70
|
+
"DECIMAL",
|
|
71
|
+
"DOUBLE",
|
|
72
|
+
"ENUM",
|
|
73
|
+
"FLOAT",
|
|
74
|
+
"INTEGER",
|
|
75
|
+
"INTEGER",
|
|
76
|
+
"JSON",
|
|
77
|
+
"LONGBLOB",
|
|
78
|
+
"LONGTEXT",
|
|
79
|
+
"MEDIUMBLOB",
|
|
80
|
+
"MEDIUMINT",
|
|
81
|
+
"MEDIUMTEXT",
|
|
82
|
+
"NCHAR",
|
|
83
|
+
"NVARCHAR",
|
|
84
|
+
"NUMERIC",
|
|
85
|
+
"SET",
|
|
86
|
+
"SMALLINT",
|
|
87
|
+
"REAL",
|
|
88
|
+
"TEXT",
|
|
89
|
+
"TIME",
|
|
90
|
+
"TIMESTAMP",
|
|
91
|
+
"TINYBLOB",
|
|
92
|
+
"TINYINT",
|
|
93
|
+
"TINYTEXT",
|
|
94
|
+
"VARBINARY",
|
|
95
|
+
"VARCHAR",
|
|
96
|
+
"YEAR",
|
|
97
|
+
"dialect",
|
|
98
|
+
"insert",
|
|
99
|
+
"Insert",
|
|
100
|
+
"match",
|
|
101
|
+
)
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
# dialects/mysql/aiomysql.py
|
|
2
|
+
# Copyright (C) 2005-2024 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
|
+
# mypy: ignore-errors
|
|
8
|
+
|
|
9
|
+
r"""
|
|
10
|
+
.. dialect:: mysql+aiomysql
|
|
11
|
+
:name: aiomysql
|
|
12
|
+
:dbapi: aiomysql
|
|
13
|
+
:connectstring: mysql+aiomysql://user:password@host:port/dbname[?key=value&key=value...]
|
|
14
|
+
:url: https://github.com/aio-libs/aiomysql
|
|
15
|
+
|
|
16
|
+
The aiomysql dialect is SQLAlchemy's second Python asyncio dialect.
|
|
17
|
+
|
|
18
|
+
Using a special asyncio mediation layer, the aiomysql dialect is usable
|
|
19
|
+
as the backend for the :ref:`SQLAlchemy asyncio <asyncio_toplevel>`
|
|
20
|
+
extension package.
|
|
21
|
+
|
|
22
|
+
This dialect should normally be used only with the
|
|
23
|
+
:func:`_asyncio.create_async_engine` engine creation function::
|
|
24
|
+
|
|
25
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
26
|
+
engine = create_async_engine("mysql+aiomysql://user:pass@hostname/dbname?charset=utf8mb4")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
""" # noqa
|
|
30
|
+
from collections import deque
|
|
31
|
+
|
|
32
|
+
from .pymysql import MySQLDialect_pymysql
|
|
33
|
+
from ... import pool
|
|
34
|
+
from ... import util
|
|
35
|
+
from ...engine import AdaptedConnection
|
|
36
|
+
from ...util.concurrency import asyncio
|
|
37
|
+
from ...util.concurrency import await_fallback
|
|
38
|
+
from ...util.concurrency import await_only
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AsyncAdapt_aiomysql_cursor:
|
|
42
|
+
# TODO: base on connectors/asyncio.py
|
|
43
|
+
# see #10415
|
|
44
|
+
server_side = False
|
|
45
|
+
__slots__ = (
|
|
46
|
+
"_adapt_connection",
|
|
47
|
+
"_connection",
|
|
48
|
+
"await_",
|
|
49
|
+
"_cursor",
|
|
50
|
+
"_rows",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def __init__(self, adapt_connection):
|
|
54
|
+
self._adapt_connection = adapt_connection
|
|
55
|
+
self._connection = adapt_connection._connection
|
|
56
|
+
self.await_ = adapt_connection.await_
|
|
57
|
+
|
|
58
|
+
cursor = self._connection.cursor(adapt_connection.dbapi.Cursor)
|
|
59
|
+
|
|
60
|
+
# see https://github.com/aio-libs/aiomysql/issues/543
|
|
61
|
+
self._cursor = self.await_(cursor.__aenter__())
|
|
62
|
+
self._rows = deque()
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def description(self):
|
|
66
|
+
return self._cursor.description
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def rowcount(self):
|
|
70
|
+
return self._cursor.rowcount
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def arraysize(self):
|
|
74
|
+
return self._cursor.arraysize
|
|
75
|
+
|
|
76
|
+
@arraysize.setter
|
|
77
|
+
def arraysize(self, value):
|
|
78
|
+
self._cursor.arraysize = value
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def lastrowid(self):
|
|
82
|
+
return self._cursor.lastrowid
|
|
83
|
+
|
|
84
|
+
def close(self):
|
|
85
|
+
# note we aren't actually closing the cursor here,
|
|
86
|
+
# we are just letting GC do it. to allow this to be async
|
|
87
|
+
# we would need the Result to change how it does "Safe close cursor".
|
|
88
|
+
# MySQL "cursors" don't actually have state to be "closed" besides
|
|
89
|
+
# exhausting rows, which we already have done for sync cursor.
|
|
90
|
+
# another option would be to emulate aiosqlite dialect and assign
|
|
91
|
+
# cursor only if we are doing server side cursor operation.
|
|
92
|
+
self._rows.clear()
|
|
93
|
+
|
|
94
|
+
def execute(self, operation, parameters=None):
|
|
95
|
+
return self.await_(self._execute_async(operation, parameters))
|
|
96
|
+
|
|
97
|
+
def executemany(self, operation, seq_of_parameters):
|
|
98
|
+
return self.await_(
|
|
99
|
+
self._executemany_async(operation, seq_of_parameters)
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
async def _execute_async(self, operation, parameters):
|
|
103
|
+
async with self._adapt_connection._execute_mutex:
|
|
104
|
+
result = await self._cursor.execute(operation, parameters)
|
|
105
|
+
|
|
106
|
+
if not self.server_side:
|
|
107
|
+
# aiomysql has a "fake" async result, so we have to pull it out
|
|
108
|
+
# of that here since our default result is not async.
|
|
109
|
+
# we could just as easily grab "_rows" here and be done with it
|
|
110
|
+
# but this is safer.
|
|
111
|
+
self._rows = deque(await self._cursor.fetchall())
|
|
112
|
+
return result
|
|
113
|
+
|
|
114
|
+
async def _executemany_async(self, operation, seq_of_parameters):
|
|
115
|
+
async with self._adapt_connection._execute_mutex:
|
|
116
|
+
return await self._cursor.executemany(operation, seq_of_parameters)
|
|
117
|
+
|
|
118
|
+
def setinputsizes(self, *inputsizes):
|
|
119
|
+
pass
|
|
120
|
+
|
|
121
|
+
def __iter__(self):
|
|
122
|
+
while self._rows:
|
|
123
|
+
yield self._rows.popleft()
|
|
124
|
+
|
|
125
|
+
def fetchone(self):
|
|
126
|
+
if self._rows:
|
|
127
|
+
return self._rows.popleft()
|
|
128
|
+
else:
|
|
129
|
+
return None
|
|
130
|
+
|
|
131
|
+
def fetchmany(self, size=None):
|
|
132
|
+
if size is None:
|
|
133
|
+
size = self.arraysize
|
|
134
|
+
|
|
135
|
+
rr = self._rows
|
|
136
|
+
return [rr.popleft() for _ in range(min(size, len(rr)))]
|
|
137
|
+
|
|
138
|
+
def fetchall(self):
|
|
139
|
+
retval = list(self._rows)
|
|
140
|
+
self._rows.clear()
|
|
141
|
+
return retval
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class AsyncAdapt_aiomysql_ss_cursor(AsyncAdapt_aiomysql_cursor):
|
|
145
|
+
# TODO: base on connectors/asyncio.py
|
|
146
|
+
# see #10415
|
|
147
|
+
__slots__ = ()
|
|
148
|
+
server_side = True
|
|
149
|
+
|
|
150
|
+
def __init__(self, adapt_connection):
|
|
151
|
+
self._adapt_connection = adapt_connection
|
|
152
|
+
self._connection = adapt_connection._connection
|
|
153
|
+
self.await_ = adapt_connection.await_
|
|
154
|
+
|
|
155
|
+
cursor = self._connection.cursor(adapt_connection.dbapi.SSCursor)
|
|
156
|
+
|
|
157
|
+
self._cursor = self.await_(cursor.__aenter__())
|
|
158
|
+
|
|
159
|
+
def close(self):
|
|
160
|
+
if self._cursor is not None:
|
|
161
|
+
self.await_(self._cursor.close())
|
|
162
|
+
self._cursor = None
|
|
163
|
+
|
|
164
|
+
def fetchone(self):
|
|
165
|
+
return self.await_(self._cursor.fetchone())
|
|
166
|
+
|
|
167
|
+
def fetchmany(self, size=None):
|
|
168
|
+
return self.await_(self._cursor.fetchmany(size=size))
|
|
169
|
+
|
|
170
|
+
def fetchall(self):
|
|
171
|
+
return self.await_(self._cursor.fetchall())
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class AsyncAdapt_aiomysql_connection(AdaptedConnection):
|
|
175
|
+
# TODO: base on connectors/asyncio.py
|
|
176
|
+
# see #10415
|
|
177
|
+
await_ = staticmethod(await_only)
|
|
178
|
+
__slots__ = ("dbapi", "_execute_mutex")
|
|
179
|
+
|
|
180
|
+
def __init__(self, dbapi, connection):
|
|
181
|
+
self.dbapi = dbapi
|
|
182
|
+
self._connection = connection
|
|
183
|
+
self._execute_mutex = asyncio.Lock()
|
|
184
|
+
|
|
185
|
+
def ping(self, reconnect):
|
|
186
|
+
return self.await_(self._connection.ping(reconnect))
|
|
187
|
+
|
|
188
|
+
def character_set_name(self):
|
|
189
|
+
return self._connection.character_set_name()
|
|
190
|
+
|
|
191
|
+
def autocommit(self, value):
|
|
192
|
+
self.await_(self._connection.autocommit(value))
|
|
193
|
+
|
|
194
|
+
def cursor(self, server_side=False):
|
|
195
|
+
if server_side:
|
|
196
|
+
return AsyncAdapt_aiomysql_ss_cursor(self)
|
|
197
|
+
else:
|
|
198
|
+
return AsyncAdapt_aiomysql_cursor(self)
|
|
199
|
+
|
|
200
|
+
def rollback(self):
|
|
201
|
+
self.await_(self._connection.rollback())
|
|
202
|
+
|
|
203
|
+
def commit(self):
|
|
204
|
+
self.await_(self._connection.commit())
|
|
205
|
+
|
|
206
|
+
def terminate(self):
|
|
207
|
+
# it's not awaitable.
|
|
208
|
+
self._connection.close()
|
|
209
|
+
|
|
210
|
+
def close(self) -> None:
|
|
211
|
+
self.await_(self._connection.ensure_closed())
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class AsyncAdaptFallback_aiomysql_connection(AsyncAdapt_aiomysql_connection):
|
|
215
|
+
# TODO: base on connectors/asyncio.py
|
|
216
|
+
# see #10415
|
|
217
|
+
__slots__ = ()
|
|
218
|
+
|
|
219
|
+
await_ = staticmethod(await_fallback)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class AsyncAdapt_aiomysql_dbapi:
|
|
223
|
+
def __init__(self, aiomysql, pymysql):
|
|
224
|
+
self.aiomysql = aiomysql
|
|
225
|
+
self.pymysql = pymysql
|
|
226
|
+
self.paramstyle = "format"
|
|
227
|
+
self._init_dbapi_attributes()
|
|
228
|
+
self.Cursor, self.SSCursor = self._init_cursors_subclasses()
|
|
229
|
+
|
|
230
|
+
def _init_dbapi_attributes(self):
|
|
231
|
+
for name in (
|
|
232
|
+
"Warning",
|
|
233
|
+
"Error",
|
|
234
|
+
"InterfaceError",
|
|
235
|
+
"DataError",
|
|
236
|
+
"DatabaseError",
|
|
237
|
+
"OperationalError",
|
|
238
|
+
"InterfaceError",
|
|
239
|
+
"IntegrityError",
|
|
240
|
+
"ProgrammingError",
|
|
241
|
+
"InternalError",
|
|
242
|
+
"NotSupportedError",
|
|
243
|
+
):
|
|
244
|
+
setattr(self, name, getattr(self.aiomysql, name))
|
|
245
|
+
|
|
246
|
+
for name in (
|
|
247
|
+
"NUMBER",
|
|
248
|
+
"STRING",
|
|
249
|
+
"DATETIME",
|
|
250
|
+
"BINARY",
|
|
251
|
+
"TIMESTAMP",
|
|
252
|
+
"Binary",
|
|
253
|
+
):
|
|
254
|
+
setattr(self, name, getattr(self.pymysql, name))
|
|
255
|
+
|
|
256
|
+
def connect(self, *arg, **kw):
|
|
257
|
+
async_fallback = kw.pop("async_fallback", False)
|
|
258
|
+
creator_fn = kw.pop("async_creator_fn", self.aiomysql.connect)
|
|
259
|
+
|
|
260
|
+
if util.asbool(async_fallback):
|
|
261
|
+
return AsyncAdaptFallback_aiomysql_connection(
|
|
262
|
+
self,
|
|
263
|
+
await_fallback(creator_fn(*arg, **kw)),
|
|
264
|
+
)
|
|
265
|
+
else:
|
|
266
|
+
return AsyncAdapt_aiomysql_connection(
|
|
267
|
+
self,
|
|
268
|
+
await_only(creator_fn(*arg, **kw)),
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
def _init_cursors_subclasses(self):
|
|
272
|
+
# suppress unconditional warning emitted by aiomysql
|
|
273
|
+
class Cursor(self.aiomysql.Cursor):
|
|
274
|
+
async def _show_warnings(self, conn):
|
|
275
|
+
pass
|
|
276
|
+
|
|
277
|
+
class SSCursor(self.aiomysql.SSCursor):
|
|
278
|
+
async def _show_warnings(self, conn):
|
|
279
|
+
pass
|
|
280
|
+
|
|
281
|
+
return Cursor, SSCursor
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
class MySQLDialect_aiomysql(MySQLDialect_pymysql):
|
|
285
|
+
driver = "aiomysql"
|
|
286
|
+
supports_statement_cache = True
|
|
287
|
+
|
|
288
|
+
supports_server_side_cursors = True
|
|
289
|
+
_sscursor = AsyncAdapt_aiomysql_ss_cursor
|
|
290
|
+
|
|
291
|
+
is_async = True
|
|
292
|
+
has_terminate = True
|
|
293
|
+
|
|
294
|
+
@classmethod
|
|
295
|
+
def import_dbapi(cls):
|
|
296
|
+
return AsyncAdapt_aiomysql_dbapi(
|
|
297
|
+
__import__("aiomysql"), __import__("pymysql")
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
@classmethod
|
|
301
|
+
def get_pool_class(cls, url):
|
|
302
|
+
async_fallback = url.query.get("async_fallback", False)
|
|
303
|
+
|
|
304
|
+
if util.asbool(async_fallback):
|
|
305
|
+
return pool.FallbackAsyncAdaptedQueuePool
|
|
306
|
+
else:
|
|
307
|
+
return pool.AsyncAdaptedQueuePool
|
|
308
|
+
|
|
309
|
+
def do_terminate(self, dbapi_connection) -> None:
|
|
310
|
+
dbapi_connection.terminate()
|
|
311
|
+
|
|
312
|
+
def create_connect_args(self, url):
|
|
313
|
+
return super().create_connect_args(
|
|
314
|
+
url, _translate_args=dict(username="user", database="db")
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
def is_disconnect(self, e, connection, cursor):
|
|
318
|
+
if super().is_disconnect(e, connection, cursor):
|
|
319
|
+
return True
|
|
320
|
+
else:
|
|
321
|
+
str_e = str(e).lower()
|
|
322
|
+
return "not connected" in str_e
|
|
323
|
+
|
|
324
|
+
def _found_rows_client_flag(self):
|
|
325
|
+
from pymysql.constants import CLIENT
|
|
326
|
+
|
|
327
|
+
return CLIENT.FOUND_ROWS
|
|
328
|
+
|
|
329
|
+
def get_driver_connection(self, connection):
|
|
330
|
+
return connection._connection
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
dialect = MySQLDialect_aiomysql
|