sqlcycli 1.0.1__tar.gz
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.
- sqlcycli-1.0.1/LICENSE +42 -0
- sqlcycli-1.0.1/MANIFEST.in +12 -0
- sqlcycli-1.0.1/PKG-INFO +174 -0
- sqlcycli-1.0.1/README.md +152 -0
- sqlcycli-1.0.1/pyproject.toml +8 -0
- sqlcycli-1.0.1/setup.cfg +41 -0
- sqlcycli-1.0.1/setup.py +107 -0
- sqlcycli-1.0.1/src/sqlcycli/__init__.pxd +0 -0
- sqlcycli-1.0.1/src/sqlcycli/__init__.py +46 -0
- sqlcycli-1.0.1/src/sqlcycli/_auth.c +31124 -0
- sqlcycli-1.0.1/src/sqlcycli/_auth.pxd +23 -0
- sqlcycli-1.0.1/src/sqlcycli/_auth.py +343 -0
- sqlcycli-1.0.1/src/sqlcycli/_connect.c +22401 -0
- sqlcycli-1.0.1/src/sqlcycli/_connect.pxd +88 -0
- sqlcycli-1.0.1/src/sqlcycli/_connect.py +458 -0
- sqlcycli-1.0.1/src/sqlcycli/_optionfile.c +17035 -0
- sqlcycli-1.0.1/src/sqlcycli/_optionfile.pxd +15 -0
- sqlcycli-1.0.1/src/sqlcycli/_optionfile.py +257 -0
- sqlcycli-1.0.1/src/sqlcycli/_ssl.c +15297 -0
- sqlcycli-1.0.1/src/sqlcycli/_ssl.pxd +21 -0
- sqlcycli-1.0.1/src/sqlcycli/_ssl.py +233 -0
- sqlcycli-1.0.1/src/sqlcycli/aio/__init__.pxd +0 -0
- sqlcycli-1.0.1/src/sqlcycli/aio/__init__.py +24 -0
- sqlcycli-1.0.1/src/sqlcycli/aio/connection.c +126075 -0
- sqlcycli-1.0.1/src/sqlcycli/aio/connection.pxd +158 -0
- sqlcycli-1.0.1/src/sqlcycli/aio/connection.py +3611 -0
- sqlcycli-1.0.1/src/sqlcycli/aio/pool.c +55631 -0
- sqlcycli-1.0.1/src/sqlcycli/aio/pool.pxd +85 -0
- sqlcycli-1.0.1/src/sqlcycli/aio/pool.py +1301 -0
- sqlcycli-1.0.1/src/sqlcycli/charset.c +25647 -0
- sqlcycli-1.0.1/src/sqlcycli/charset.pxd +35 -0
- sqlcycli-1.0.1/src/sqlcycli/charset.py +499 -0
- sqlcycli-1.0.1/src/sqlcycli/connection.c +88260 -0
- sqlcycli-1.0.1/src/sqlcycli/connection.pxd +227 -0
- sqlcycli-1.0.1/src/sqlcycli/connection.py +3701 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/CLIENT.py +38 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/COMMAND.py +32 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/CR.py +79 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/ER.py +477 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/FIELD_TYPE.py +31 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/FLAG.py +15 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/SERVER_STATUS.py +10 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_CLIENT.c +5153 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_CLIENT.pxd +9 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_CLIENT.py +31 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_COMMAND.c +5330 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_COMMAND.pxd +10 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_COMMAND.py +36 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_FIELD_TYPE.c +5282 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_FIELD_TYPE.pxd +8 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_FIELD_TYPE.py +34 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_SERVER_STATUS.c +4804 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_SERVER_STATUS.pxd +8 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/_SERVER_STATUS.py +16 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/__init__.pxd +0 -0
- sqlcycli-1.0.1/src/sqlcycli/constants/__init__.py +0 -0
- sqlcycli-1.0.1/src/sqlcycli/errors.c +26419 -0
- sqlcycli-1.0.1/src/sqlcycli/errors.pxd +7 -0
- sqlcycli-1.0.1/src/sqlcycli/errors.py +402 -0
- sqlcycli-1.0.1/src/sqlcycli/protocol.c +33623 -0
- sqlcycli-1.0.1/src/sqlcycli/protocol.pxd +65 -0
- sqlcycli-1.0.1/src/sqlcycli/protocol.py +626 -0
- sqlcycli-1.0.1/src/sqlcycli/transcode.c +37092 -0
- sqlcycli-1.0.1/src/sqlcycli/transcode.pxd +301 -0
- sqlcycli-1.0.1/src/sqlcycli/transcode.py +2118 -0
- sqlcycli-1.0.1/src/sqlcycli/typeref.c +5691 -0
- sqlcycli-1.0.1/src/sqlcycli/typeref.pxd +20 -0
- sqlcycli-1.0.1/src/sqlcycli/typeref.py +46 -0
- sqlcycli-1.0.1/src/sqlcycli/utils.c +18107 -0
- sqlcycli-1.0.1/src/sqlcycli/utils.pxd +509 -0
- sqlcycli-1.0.1/src/sqlcycli/utils.py +3 -0
- sqlcycli-1.0.1/src/sqlcycli.egg-info/PKG-INFO +174 -0
- sqlcycli-1.0.1/src/sqlcycli.egg-info/SOURCES.txt +76 -0
- sqlcycli-1.0.1/src/sqlcycli.egg-info/dependency_links.txt +1 -0
- sqlcycli-1.0.1/src/sqlcycli.egg-info/not-zip-safe +1 -0
- sqlcycli-1.0.1/src/sqlcycli.egg-info/requires.txt +5 -0
- sqlcycli-1.0.1/src/sqlcycli.egg-info/top_level.txt +1 -0
sqlcycli-1.0.1/LICENSE
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
sqlcycli - Copyright (c) 2023 Jifu Chen.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
--------------------------------------------------------------------------------
|
|
24
|
+
Copyright (c) 2010, 2013 PyMySQL contributors
|
|
25
|
+
|
|
26
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
27
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
28
|
+
in the Software without restriction, including without limitation the rights
|
|
29
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
30
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
31
|
+
furnished to do so, subject to the following conditions:
|
|
32
|
+
|
|
33
|
+
The above copyright notice and this permission notice shall be included in
|
|
34
|
+
all copies or substantial portions of the Software.
|
|
35
|
+
|
|
36
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
37
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
38
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
39
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
40
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
41
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
42
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
include LICENSE
|
|
2
|
+
include README.md
|
|
3
|
+
|
|
4
|
+
include src/sqlcycli/aio/*.pxd
|
|
5
|
+
include src/sqlcycli/aio/*.py
|
|
6
|
+
include src/sqlcycli/aio/*.pyx
|
|
7
|
+
include src/sqlcycli/constants/*.pxd
|
|
8
|
+
include src/sqlcycli/constants/*.py
|
|
9
|
+
include src/sqlcycli/constants/*.pyx
|
|
10
|
+
include src/sqlcycli/*.pxd
|
|
11
|
+
include src/sqlcycli/*.py
|
|
12
|
+
include src/sqlcycli/*.pyx
|
sqlcycli-1.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: sqlcycli
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Fast MySQL driver build in Cython (Sync and Async).
|
|
5
|
+
Home-page: https://github.com/AresJef/SQLCyCli
|
|
6
|
+
Author: Jiefu Chen
|
|
7
|
+
Author-email: keppa1991@163.com
|
|
8
|
+
License: MIT license
|
|
9
|
+
Keywords: mysql,mariadb,pymysql,aiomysql,cython,asyncio
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Operating System :: Unix
|
|
12
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: cytimes>=1.0.3
|
|
18
|
+
Requires-Dist: numpy>=1.25.2
|
|
19
|
+
Requires-Dist: orjson>=3.10.2
|
|
20
|
+
Requires-Dist: pandas>=2.1.0
|
|
21
|
+
Requires-Dist: mysqlclient>=2.2.0
|
|
22
|
+
|
|
23
|
+
## Fast MySQL driver build in Cython (Sync and Async).
|
|
24
|
+
|
|
25
|
+
Created to be used in a project, this package is published to github for ease of management and installation across different modules.
|
|
26
|
+
|
|
27
|
+
### Installation
|
|
28
|
+
Install from `PyPi`
|
|
29
|
+
``` bash
|
|
30
|
+
pip install sqlcycli
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Install from `github`
|
|
34
|
+
``` bash
|
|
35
|
+
pip install git+https://github.com/AresJef/SQLCyCli.git
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Requirements
|
|
39
|
+
- Python 3.10 or higher.
|
|
40
|
+
- MySQL 5.5 or higher.
|
|
41
|
+
|
|
42
|
+
### Features
|
|
43
|
+
- Written in [Cython](https://cython.org/) for optimal performance (especially for SELECT/INSERT query).
|
|
44
|
+
- All classes and methods are well documented and static typed.
|
|
45
|
+
- Supports both `Sync` and `Async` connection to the server.
|
|
46
|
+
- API Compatiable with [PyMySQL](https://github.com/PyMySQL/PyMySQL) and [aiomysql](https://github.com/aio-libs/aiomysql).
|
|
47
|
+
- Support conversion (escape) for most of the native python types, and objects from libaray [numpy](https://github.com/numpy/numpy) and [pandas](https://github.com/pandas-dev/pandas). Does `NOT` support custom conversion (escape).
|
|
48
|
+
|
|
49
|
+
### Benchmark
|
|
50
|
+
The following result comes from [benchmark](./src/benchmark.py):
|
|
51
|
+
- Device: MacbookPro M1Pro(2E8P) 32GB
|
|
52
|
+
- Python: 3.12.4
|
|
53
|
+
- MySQL: 8.3.0
|
|
54
|
+
- mysqlclient: 2.2.4
|
|
55
|
+
- PyMySQL: 1.1.1
|
|
56
|
+
- aiomysql: 0.2.0
|
|
57
|
+
- asyncmy: 0.2.9
|
|
58
|
+
```
|
|
59
|
+
# Unit: second | Lower is better
|
|
60
|
+
name type rows insert-per-row insert-bulk select-per-row select-all update-per-row update-all delete-per-row delete-all
|
|
61
|
+
mysqlclient sync 50000 1.734200 0.427027 1.756226 0.117552 1.901870 0.365056 1.651022 0.131151
|
|
62
|
+
SQLCyCli sync 50000 2.203967 0.293410 2.331576 0.062152 2.279076 0.352106 2.115025 0.107902
|
|
63
|
+
PyMySQL sync 50000 2.607349 0.412063 4.219286 0.321089 2.572826 0.345419 2.304015 0.104720
|
|
64
|
+
SQLCyCli async 50000 3.342991 0.270254 4.297667 0.141201 3.466729 0.346168 3.343880 0.105293
|
|
65
|
+
aiomysql async 50000 3.464662 0.384193 5.115068 0.322858 3.582689 0.345661 3.444377 0.104894
|
|
66
|
+
asyncmy async 50000 3.851011 0.416715 5.604330 0.314939 3.824736 0.346903 3.580444 0.104748
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Usage
|
|
70
|
+
#### Use `connect()` to create one connection (`Sync` or `Async`) to the server.
|
|
71
|
+
```python
|
|
72
|
+
import asyncio
|
|
73
|
+
import sqlcycli
|
|
74
|
+
|
|
75
|
+
HOST = "localhost"
|
|
76
|
+
PORT = 3306
|
|
77
|
+
USER = "root"
|
|
78
|
+
PSWD = "password"
|
|
79
|
+
|
|
80
|
+
# Synchronous Connection
|
|
81
|
+
def test_sync_connection() -> None:
|
|
82
|
+
with sqlcycli.connect(HOST, PORT, USER, PSWD) as conn:
|
|
83
|
+
with conn.cursor() as cur:
|
|
84
|
+
cur.execute("SELECT 1")
|
|
85
|
+
res = cur.fetchone()
|
|
86
|
+
assert res == (1,)
|
|
87
|
+
# Connection closed
|
|
88
|
+
assert conn.closed()
|
|
89
|
+
|
|
90
|
+
# Asynchronous Connection
|
|
91
|
+
async def test_async_connection() -> None:
|
|
92
|
+
async with sqlcycli.connect(HOST, PORT, USER, PSWD) as conn:
|
|
93
|
+
async with conn.cursor() as cur:
|
|
94
|
+
await cur.execute("SELECT 1")
|
|
95
|
+
res = await cur.fetchone()
|
|
96
|
+
assert res == (1,)
|
|
97
|
+
# Connection closed
|
|
98
|
+
assert conn.closed()
|
|
99
|
+
|
|
100
|
+
if __name__ == "__main__":
|
|
101
|
+
test_sync_connection()
|
|
102
|
+
asyncio.run(test_async_connection())
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### Use `create_pool()` to create a Pool for managing and maintaining `Async` connections to the server.
|
|
106
|
+
```python
|
|
107
|
+
import asyncio
|
|
108
|
+
import sqlcycli
|
|
109
|
+
|
|
110
|
+
HOST = "localhost"
|
|
111
|
+
PORT = 3306
|
|
112
|
+
USER = "root"
|
|
113
|
+
PSWD = "password"
|
|
114
|
+
|
|
115
|
+
# Pool (Context Manager: Connected)
|
|
116
|
+
async def test_pool_context_connected() -> None:
|
|
117
|
+
async with sqlcycli.create_pool(HOST, PORT, USER, PSWD, min_size=1) as pool:
|
|
118
|
+
# Pool is connected: 1 free connection (min_size=1)
|
|
119
|
+
assert not pool.closed() and pool.free == 1
|
|
120
|
+
async with pool.acquire() as conn:
|
|
121
|
+
async with conn.cursor() as cur:
|
|
122
|
+
await cur.execute("SELECT 1")
|
|
123
|
+
res = await cur.fetchone()
|
|
124
|
+
assert res == (1,)
|
|
125
|
+
# Pool closed
|
|
126
|
+
assert pool.closed() and pool.total == 0
|
|
127
|
+
|
|
128
|
+
# Pool (Context Manager: Disconnected)
|
|
129
|
+
async def test_pool_context_disconnected() -> None:
|
|
130
|
+
with sqlcycli.create_pool(HOST, PORT, USER, PSWD, min_size=1) as pool:
|
|
131
|
+
# Pool is not connected: 0 free connection (min_size=1)
|
|
132
|
+
assert pool.closed() and pool.free == 0
|
|
133
|
+
# Connect automatically
|
|
134
|
+
async with pool.acquire() as conn:
|
|
135
|
+
async with conn.cursor() as cur:
|
|
136
|
+
await cur.execute("SELECT 1")
|
|
137
|
+
res = await cur.fetchone()
|
|
138
|
+
assert res == (1,)
|
|
139
|
+
# 1 free connection
|
|
140
|
+
assert pool.free == 1
|
|
141
|
+
# Pool closed
|
|
142
|
+
assert pool.closed() and pool.total == 0
|
|
143
|
+
|
|
144
|
+
# Pool (Create Directly: Connected)
|
|
145
|
+
async def test_pool_direct_connected() -> None:
|
|
146
|
+
pool = await sqlcycli.create_pool(HOST, PORT, USER, PSWD, min_size=1)
|
|
147
|
+
# Pool is connected: 1 free connection (min_size=1)
|
|
148
|
+
assert not pool.closed() and pool.free == 1
|
|
149
|
+
async with pool.acquire() as conn:
|
|
150
|
+
async with conn.cursor() as cur:
|
|
151
|
+
await cur.execute("SELECT 1")
|
|
152
|
+
res = await cur.fetchone()
|
|
153
|
+
assert res == (1,)
|
|
154
|
+
# Close pool manually
|
|
155
|
+
await pool.close()
|
|
156
|
+
assert pool.closed() and pool.total == 0
|
|
157
|
+
|
|
158
|
+
if __name__ == "__main__":
|
|
159
|
+
asyncio.run(test_pool_context_connected())
|
|
160
|
+
asyncio.run(test_pool_context_disconnected())
|
|
161
|
+
asyncio.run(test_pool_direct_connected())
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Acknowledgements
|
|
165
|
+
SQLCyCli is build on top of the following open-source repositories:
|
|
166
|
+
- [aiomysql](https://github.com/aio-libs/aiomysql)
|
|
167
|
+
- [PyMySQL](https://github.com/PyMySQL/PyMySQL)
|
|
168
|
+
|
|
169
|
+
SQLCyCli is based on the following open-source repositories:
|
|
170
|
+
- [cytimes](https://github.com/AresJef/cyTimes)
|
|
171
|
+
- [numpy](https://github.com/numpy/numpy)
|
|
172
|
+
- [orjson](https://github.com/ijl/orjson)
|
|
173
|
+
- [pandas](https://github.com/pandas-dev/pandas)
|
|
174
|
+
- [mysqlclient](https://github.com/PyMySQL/mysqlclient)
|
sqlcycli-1.0.1/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
## Fast MySQL driver build in Cython (Sync and Async).
|
|
2
|
+
|
|
3
|
+
Created to be used in a project, this package is published to github for ease of management and installation across different modules.
|
|
4
|
+
|
|
5
|
+
### Installation
|
|
6
|
+
Install from `PyPi`
|
|
7
|
+
``` bash
|
|
8
|
+
pip install sqlcycli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Install from `github`
|
|
12
|
+
``` bash
|
|
13
|
+
pip install git+https://github.com/AresJef/SQLCyCli.git
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Requirements
|
|
17
|
+
- Python 3.10 or higher.
|
|
18
|
+
- MySQL 5.5 or higher.
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
- Written in [Cython](https://cython.org/) for optimal performance (especially for SELECT/INSERT query).
|
|
22
|
+
- All classes and methods are well documented and static typed.
|
|
23
|
+
- Supports both `Sync` and `Async` connection to the server.
|
|
24
|
+
- API Compatiable with [PyMySQL](https://github.com/PyMySQL/PyMySQL) and [aiomysql](https://github.com/aio-libs/aiomysql).
|
|
25
|
+
- Support conversion (escape) for most of the native python types, and objects from libaray [numpy](https://github.com/numpy/numpy) and [pandas](https://github.com/pandas-dev/pandas). Does `NOT` support custom conversion (escape).
|
|
26
|
+
|
|
27
|
+
### Benchmark
|
|
28
|
+
The following result comes from [benchmark](./src/benchmark.py):
|
|
29
|
+
- Device: MacbookPro M1Pro(2E8P) 32GB
|
|
30
|
+
- Python: 3.12.4
|
|
31
|
+
- MySQL: 8.3.0
|
|
32
|
+
- mysqlclient: 2.2.4
|
|
33
|
+
- PyMySQL: 1.1.1
|
|
34
|
+
- aiomysql: 0.2.0
|
|
35
|
+
- asyncmy: 0.2.9
|
|
36
|
+
```
|
|
37
|
+
# Unit: second | Lower is better
|
|
38
|
+
name type rows insert-per-row insert-bulk select-per-row select-all update-per-row update-all delete-per-row delete-all
|
|
39
|
+
mysqlclient sync 50000 1.734200 0.427027 1.756226 0.117552 1.901870 0.365056 1.651022 0.131151
|
|
40
|
+
SQLCyCli sync 50000 2.203967 0.293410 2.331576 0.062152 2.279076 0.352106 2.115025 0.107902
|
|
41
|
+
PyMySQL sync 50000 2.607349 0.412063 4.219286 0.321089 2.572826 0.345419 2.304015 0.104720
|
|
42
|
+
SQLCyCli async 50000 3.342991 0.270254 4.297667 0.141201 3.466729 0.346168 3.343880 0.105293
|
|
43
|
+
aiomysql async 50000 3.464662 0.384193 5.115068 0.322858 3.582689 0.345661 3.444377 0.104894
|
|
44
|
+
asyncmy async 50000 3.851011 0.416715 5.604330 0.314939 3.824736 0.346903 3.580444 0.104748
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Usage
|
|
48
|
+
#### Use `connect()` to create one connection (`Sync` or `Async`) to the server.
|
|
49
|
+
```python
|
|
50
|
+
import asyncio
|
|
51
|
+
import sqlcycli
|
|
52
|
+
|
|
53
|
+
HOST = "localhost"
|
|
54
|
+
PORT = 3306
|
|
55
|
+
USER = "root"
|
|
56
|
+
PSWD = "password"
|
|
57
|
+
|
|
58
|
+
# Synchronous Connection
|
|
59
|
+
def test_sync_connection() -> None:
|
|
60
|
+
with sqlcycli.connect(HOST, PORT, USER, PSWD) as conn:
|
|
61
|
+
with conn.cursor() as cur:
|
|
62
|
+
cur.execute("SELECT 1")
|
|
63
|
+
res = cur.fetchone()
|
|
64
|
+
assert res == (1,)
|
|
65
|
+
# Connection closed
|
|
66
|
+
assert conn.closed()
|
|
67
|
+
|
|
68
|
+
# Asynchronous Connection
|
|
69
|
+
async def test_async_connection() -> None:
|
|
70
|
+
async with sqlcycli.connect(HOST, PORT, USER, PSWD) as conn:
|
|
71
|
+
async with conn.cursor() as cur:
|
|
72
|
+
await cur.execute("SELECT 1")
|
|
73
|
+
res = await cur.fetchone()
|
|
74
|
+
assert res == (1,)
|
|
75
|
+
# Connection closed
|
|
76
|
+
assert conn.closed()
|
|
77
|
+
|
|
78
|
+
if __name__ == "__main__":
|
|
79
|
+
test_sync_connection()
|
|
80
|
+
asyncio.run(test_async_connection())
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### Use `create_pool()` to create a Pool for managing and maintaining `Async` connections to the server.
|
|
84
|
+
```python
|
|
85
|
+
import asyncio
|
|
86
|
+
import sqlcycli
|
|
87
|
+
|
|
88
|
+
HOST = "localhost"
|
|
89
|
+
PORT = 3306
|
|
90
|
+
USER = "root"
|
|
91
|
+
PSWD = "password"
|
|
92
|
+
|
|
93
|
+
# Pool (Context Manager: Connected)
|
|
94
|
+
async def test_pool_context_connected() -> None:
|
|
95
|
+
async with sqlcycli.create_pool(HOST, PORT, USER, PSWD, min_size=1) as pool:
|
|
96
|
+
# Pool is connected: 1 free connection (min_size=1)
|
|
97
|
+
assert not pool.closed() and pool.free == 1
|
|
98
|
+
async with pool.acquire() as conn:
|
|
99
|
+
async with conn.cursor() as cur:
|
|
100
|
+
await cur.execute("SELECT 1")
|
|
101
|
+
res = await cur.fetchone()
|
|
102
|
+
assert res == (1,)
|
|
103
|
+
# Pool closed
|
|
104
|
+
assert pool.closed() and pool.total == 0
|
|
105
|
+
|
|
106
|
+
# Pool (Context Manager: Disconnected)
|
|
107
|
+
async def test_pool_context_disconnected() -> None:
|
|
108
|
+
with sqlcycli.create_pool(HOST, PORT, USER, PSWD, min_size=1) as pool:
|
|
109
|
+
# Pool is not connected: 0 free connection (min_size=1)
|
|
110
|
+
assert pool.closed() and pool.free == 0
|
|
111
|
+
# Connect automatically
|
|
112
|
+
async with pool.acquire() as conn:
|
|
113
|
+
async with conn.cursor() as cur:
|
|
114
|
+
await cur.execute("SELECT 1")
|
|
115
|
+
res = await cur.fetchone()
|
|
116
|
+
assert res == (1,)
|
|
117
|
+
# 1 free connection
|
|
118
|
+
assert pool.free == 1
|
|
119
|
+
# Pool closed
|
|
120
|
+
assert pool.closed() and pool.total == 0
|
|
121
|
+
|
|
122
|
+
# Pool (Create Directly: Connected)
|
|
123
|
+
async def test_pool_direct_connected() -> None:
|
|
124
|
+
pool = await sqlcycli.create_pool(HOST, PORT, USER, PSWD, min_size=1)
|
|
125
|
+
# Pool is connected: 1 free connection (min_size=1)
|
|
126
|
+
assert not pool.closed() and pool.free == 1
|
|
127
|
+
async with pool.acquire() as conn:
|
|
128
|
+
async with conn.cursor() as cur:
|
|
129
|
+
await cur.execute("SELECT 1")
|
|
130
|
+
res = await cur.fetchone()
|
|
131
|
+
assert res == (1,)
|
|
132
|
+
# Close pool manually
|
|
133
|
+
await pool.close()
|
|
134
|
+
assert pool.closed() and pool.total == 0
|
|
135
|
+
|
|
136
|
+
if __name__ == "__main__":
|
|
137
|
+
asyncio.run(test_pool_context_connected())
|
|
138
|
+
asyncio.run(test_pool_context_disconnected())
|
|
139
|
+
asyncio.run(test_pool_direct_connected())
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Acknowledgements
|
|
143
|
+
SQLCyCli is build on top of the following open-source repositories:
|
|
144
|
+
- [aiomysql](https://github.com/aio-libs/aiomysql)
|
|
145
|
+
- [PyMySQL](https://github.com/PyMySQL/PyMySQL)
|
|
146
|
+
|
|
147
|
+
SQLCyCli is based on the following open-source repositories:
|
|
148
|
+
- [cytimes](https://github.com/AresJef/cyTimes)
|
|
149
|
+
- [numpy](https://github.com/numpy/numpy)
|
|
150
|
+
- [orjson](https://github.com/ijl/orjson)
|
|
151
|
+
- [pandas](https://github.com/pandas-dev/pandas)
|
|
152
|
+
- [mysqlclient](https://github.com/PyMySQL/mysqlclient)
|
sqlcycli-1.0.1/setup.cfg
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = sqlcycli
|
|
3
|
+
version = 1.0.1
|
|
4
|
+
author = Jiefu Chen
|
|
5
|
+
author_email = keppa1991@163.com
|
|
6
|
+
description = Fast MySQL driver build in Cython (Sync and Async).
|
|
7
|
+
url = https://github.com/AresJef/SQLCyCli
|
|
8
|
+
long_description = file: README.md
|
|
9
|
+
long_description_content_type = text/markdown
|
|
10
|
+
keywords = mysql, mariadb, pymysql, aiomysql, cython, asyncio
|
|
11
|
+
license = MIT license
|
|
12
|
+
classifiers =
|
|
13
|
+
Programming Language :: Python :: 3
|
|
14
|
+
Operating System :: Unix
|
|
15
|
+
Operating System :: MacOS :: MacOS X
|
|
16
|
+
Operating System :: Microsoft :: Windows
|
|
17
|
+
|
|
18
|
+
[options]
|
|
19
|
+
zip_safe = False
|
|
20
|
+
include_package_data = True
|
|
21
|
+
package_dir =
|
|
22
|
+
= src
|
|
23
|
+
packages = find:
|
|
24
|
+
python_requires = >=3.10
|
|
25
|
+
install_requires =
|
|
26
|
+
cytimes>=1.0.3
|
|
27
|
+
numpy>=1.25.2
|
|
28
|
+
orjson>=3.10.2
|
|
29
|
+
pandas>=2.1.0
|
|
30
|
+
mysqlclient>=2.2.0
|
|
31
|
+
|
|
32
|
+
[options.packages.find]
|
|
33
|
+
where = src
|
|
34
|
+
|
|
35
|
+
[build_ext]
|
|
36
|
+
inplace = 1
|
|
37
|
+
|
|
38
|
+
[egg_info]
|
|
39
|
+
tag_build =
|
|
40
|
+
tag_date = 0
|
|
41
|
+
|
sqlcycli-1.0.1/setup.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import os, numpy as np, platform
|
|
2
|
+
from setuptools import setup, Extension
|
|
3
|
+
from Cython.Build import cythonize
|
|
4
|
+
|
|
5
|
+
# Package name
|
|
6
|
+
__package__ = "sqlcycli"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Create Extension
|
|
10
|
+
def extension(filename: str, include_np: bool, *extra_compile_args: str) -> Extension:
|
|
11
|
+
# Extra arguments
|
|
12
|
+
extra_args = list(extra_compile_args) if extra_compile_args else None
|
|
13
|
+
# Name
|
|
14
|
+
name: str = "%s.%s" % (__package__, filename.split(".")[0])
|
|
15
|
+
source: str = os.path.join("src", __package__, filename)
|
|
16
|
+
# Create extension
|
|
17
|
+
if include_np:
|
|
18
|
+
return Extension(
|
|
19
|
+
name,
|
|
20
|
+
sources=[source],
|
|
21
|
+
extra_compile_args=extra_args,
|
|
22
|
+
include_dirs=[np.get_include()],
|
|
23
|
+
define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
|
|
24
|
+
)
|
|
25
|
+
else:
|
|
26
|
+
return Extension(name, sources=[source], extra_compile_args=extra_args)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Create Constant Extension
|
|
30
|
+
def folder_extension(
|
|
31
|
+
folder: str,
|
|
32
|
+
filename: str,
|
|
33
|
+
include_np: bool,
|
|
34
|
+
*extra_compile_args: str,
|
|
35
|
+
) -> Extension:
|
|
36
|
+
# Extra arguments
|
|
37
|
+
extra_args = list(extra_compile_args) if extra_compile_args else None
|
|
38
|
+
# Name
|
|
39
|
+
name: str = "%s.%s.%s" % (__package__, folder, filename.split(".")[0])
|
|
40
|
+
source: str = os.path.join("src", __package__, folder, filename)
|
|
41
|
+
# Create extension
|
|
42
|
+
if include_np:
|
|
43
|
+
return Extension(
|
|
44
|
+
name,
|
|
45
|
+
sources=[source],
|
|
46
|
+
extra_compile_args=extra_args,
|
|
47
|
+
include_dirs=[np.get_include()],
|
|
48
|
+
define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
|
|
49
|
+
)
|
|
50
|
+
else:
|
|
51
|
+
return Extension(name, sources=[source], extra_compile_args=extra_args)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# Build Extensions
|
|
55
|
+
if platform.system() == "Windows":
|
|
56
|
+
extensions = [
|
|
57
|
+
# fmt: off
|
|
58
|
+
folder_extension("aio", "connection.py", True),
|
|
59
|
+
folder_extension("aio", "pool.py", True),
|
|
60
|
+
# fmt: on
|
|
61
|
+
folder_extension("constants", "_CLIENT.py", False),
|
|
62
|
+
folder_extension("constants", "_COMMAND.py", False),
|
|
63
|
+
folder_extension("constants", "_FIELD_TYPE.py", False),
|
|
64
|
+
folder_extension("constants", "_SERVER_STATUS.py", False),
|
|
65
|
+
extension("_auth.py", True),
|
|
66
|
+
extension("_connect.py", False),
|
|
67
|
+
extension("_optionfile.py", False),
|
|
68
|
+
extension("_ssl.py", False),
|
|
69
|
+
extension("charset.py", False),
|
|
70
|
+
extension("connection.py", True),
|
|
71
|
+
extension("errors.py", True),
|
|
72
|
+
extension("protocol.py", True),
|
|
73
|
+
extension("transcode.py", True),
|
|
74
|
+
extension("typeref.py", False),
|
|
75
|
+
extension("utils.py", True),
|
|
76
|
+
]
|
|
77
|
+
else:
|
|
78
|
+
extensions = [
|
|
79
|
+
# fmt: off
|
|
80
|
+
folder_extension("aio", "connection.py", True, "-Wno-unreachable-code", "-Wno-incompatible-pointer-types"),
|
|
81
|
+
folder_extension("aio", "pool.py", True, "-Wno-unreachable-code", "-Wno-incompatible-pointer-types"),
|
|
82
|
+
# fmt: on
|
|
83
|
+
folder_extension("constants", "_CLIENT.py", False),
|
|
84
|
+
folder_extension("constants", "_COMMAND.py", False),
|
|
85
|
+
folder_extension("constants", "_FIELD_TYPE.py", False),
|
|
86
|
+
folder_extension("constants", "_SERVER_STATUS.py", False),
|
|
87
|
+
extension("_auth.py", True, "-Wno-unreachable-code"),
|
|
88
|
+
extension("_connect.py", False, "-Wno-unreachable-code"),
|
|
89
|
+
extension("_optionfile.py", False, "-Wno-unreachable-code"),
|
|
90
|
+
extension("_ssl.py", False, "-Wno-unreachable-code"),
|
|
91
|
+
extension("charset.py", False, "-Wno-unreachable-code"),
|
|
92
|
+
extension("connection.py", True, "-Wno-unreachable-code"),
|
|
93
|
+
extension("errors.py", True, "-Wno-unreachable-code"),
|
|
94
|
+
extension("protocol.py", True, "-Wno-unreachable-code"),
|
|
95
|
+
extension("transcode.py", True, "-Wno-unreachable-code"),
|
|
96
|
+
extension("typeref.py", False),
|
|
97
|
+
extension("utils.py", True, "-Wno-unreachable-code"),
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
# Build
|
|
101
|
+
setup(
|
|
102
|
+
ext_modules=cythonize(
|
|
103
|
+
extensions,
|
|
104
|
+
compiler_directives={"language_level": "3"},
|
|
105
|
+
annotate=True,
|
|
106
|
+
),
|
|
107
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from sqlcycli import constants, errors
|
|
2
|
+
from sqlcycli._auth import AuthPlugin
|
|
3
|
+
from sqlcycli._optionfile import OptionFile
|
|
4
|
+
from sqlcycli._ssl import SSL, SSL_ENABLED
|
|
5
|
+
from sqlcycli.charset import Charset, all_charsets
|
|
6
|
+
from sqlcycli.protocol import MysqlPacket, FieldDescriptorPacket
|
|
7
|
+
from sqlcycli.connection import (
|
|
8
|
+
Cursor,
|
|
9
|
+
DictCursor,
|
|
10
|
+
DfCursor,
|
|
11
|
+
SSCursor,
|
|
12
|
+
SSDictCursor,
|
|
13
|
+
SSDfCursor,
|
|
14
|
+
BaseConnection,
|
|
15
|
+
Connection,
|
|
16
|
+
)
|
|
17
|
+
from sqlcycli import aio
|
|
18
|
+
from sqlcycli.aio.pool import Pool, PoolConnection
|
|
19
|
+
from sqlcycli._connect import connect, create_pool
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"constants",
|
|
24
|
+
"errors",
|
|
25
|
+
"AuthPlugin",
|
|
26
|
+
"OptionFile",
|
|
27
|
+
"SSL",
|
|
28
|
+
"SSL_ENABLED",
|
|
29
|
+
"Charset",
|
|
30
|
+
"all_charsets",
|
|
31
|
+
"MysqlPacket",
|
|
32
|
+
"FieldDescriptorPacket",
|
|
33
|
+
"Cursor",
|
|
34
|
+
"DictCursor",
|
|
35
|
+
"DfCursor",
|
|
36
|
+
"SSCursor",
|
|
37
|
+
"SSDictCursor",
|
|
38
|
+
"SSDfCursor",
|
|
39
|
+
"BaseConnection",
|
|
40
|
+
"Connection",
|
|
41
|
+
"aio",
|
|
42
|
+
"Pool",
|
|
43
|
+
"PoolConnection",
|
|
44
|
+
"connect",
|
|
45
|
+
"create_pool",
|
|
46
|
+
]
|