fastmssql 0.5.0__cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.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.
fastmssql/__init__.py ADDED
@@ -0,0 +1,66 @@
1
+ """FastMSSQL - High-Performance Microsoft SQL Server Driver for Python
2
+
3
+ High-performance Rust-backed Python driver for SQL Server with async/await support,
4
+ connection pooling, SSL/TLS encryption, and parameterized queries.
5
+ """
6
+
7
+ # Import from the compiled Rust module
8
+ from .fastmssql import (
9
+ Connection as _RustConnection,
10
+ PoolConfig,
11
+ SslConfig,
12
+ FastExecutionResult,
13
+ FastRow,
14
+ Parameter,
15
+ Parameters,
16
+ EncryptionLevel,
17
+ version,
18
+ )
19
+
20
+
21
+ class Connection:
22
+ """Thin wrapper to fix async context manager behavior."""
23
+
24
+ def __init__(self, *args, **kwargs):
25
+ self._conn = _RustConnection(*args, **kwargs)
26
+
27
+ def __getattr__(self, name):
28
+ return getattr(self._conn, name)
29
+
30
+ async def __aenter__(self):
31
+ await self._conn.__aenter__()
32
+ return self
33
+
34
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
35
+ return await self._conn.__aexit__(exc_type, exc_val, exc_tb)
36
+
37
+ async def pool_stats(self):
38
+ """Get connection pool statistics and convert tuple to dict."""
39
+ result_tuple = await self._conn.pool_stats()
40
+
41
+ # Convert tuple to dictionary
42
+ connected, connections, idle_connections, max_size, min_idle = result_tuple
43
+
44
+ if connected:
45
+ return {
46
+ 'connections': connections,
47
+ 'idle_connections': idle_connections,
48
+ 'max_size': max_size,
49
+ 'min_idle': min_idle,
50
+ 'active_connections': connections - idle_connections,
51
+ }
52
+ else:
53
+ return {'connected': False}
54
+
55
+
56
+ __all__ = [
57
+ "Connection",
58
+ "PoolConfig",
59
+ "SslConfig",
60
+ "FastExecutionResult",
61
+ "FastRow",
62
+ "Parameter",
63
+ "Parameters",
64
+ "EncryptionLevel",
65
+ "version",
66
+ ]
Binary file
@@ -0,0 +1,415 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastmssql
3
+ Version: 0.5.0
4
+ Classifier: Development Status :: 5 - Production/Stable
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: Operating System :: OS Independent
8
+ Classifier: Operating System :: Microsoft :: Windows
9
+ Classifier: Operating System :: POSIX :: Linux
10
+ Classifier: Operating System :: MacOS
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Programming Language :: Rust
18
+ Classifier: Topic :: Database
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Dist: pytest>=8.4.2 ; extra == 'dev'
21
+ Requires-Dist: pytest-asyncio>=1.2.0 ; extra == 'dev'
22
+ Requires-Dist: psutil>=7.1.1 ; extra == 'dev'
23
+ Provides-Extra: dev
24
+ License-File: LICENSE
25
+ Summary: A high-performance async Python library for Microsoft SQL Server built on Rust for heavy workloads and low latency.
26
+ Keywords: mssql,sqlserver,sql-server,database,async,asynchronous,rust,python,driver,client,pooling,high-performance,bulk-insert,batch,tokio,bb8,pyO3,cross-platform,windows,linux,macos,ssl,tls,connection-pool,data-ingestion,low-latency
27
+ Author-email: Rivendael <riverb514@gmail.com>
28
+ Requires-Python: >=3.10
29
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
30
+ Project-URL: Homepage, https://github.com/Rivendael/FastMssql
31
+ Project-URL: Repository, https://github.com/Rivendael/FastMssql
32
+ Project-URL: Bug Tracker, https://github.com/Rivendael/FastMssql/issues
33
+ Project-URL: Documentation, https://github.com/Rivendael/FastMssql#readme
34
+
35
+ # FastMSSQL ⚡
36
+
37
+ FastMSSQL is an async Python library for Microsoft SQL Server (MSSQL), built in Rust.
38
+ Unlike standard libaries, it uses a native SQL Server client—no ODBC required—simplifying installation on Windows, macOS, and Linux.
39
+ Great for data ingestion, bulk inserts, and large-scale query workloads.
40
+
41
+ [![Python Versions](https://img.shields.io/pypi/pyversions/fastmssql)](https://pypi.org/project/fastmssql/)
42
+
43
+ [![License](https://img.shields.io/badge/license-MIT%20-green)](LICENSE)
44
+
45
+ [![Unit Tests](https://github.com/Rivendael/fastmssql/actions/workflows/unittests.yml/badge.svg)](https://github.com/Rivendael/fastmssql/actions/workflows/build.yml)
46
+
47
+ [![Latest Release](https://img.shields.io/github/v/release/Rivendael/fastmssql)](https://github.com/Rivendael/fastmssql/releases)
48
+
49
+ [![Platform](https://img.shields.io/badge/platform-Windows%20|%20Linux%20|%20macOS-lightgrey)](https://github.com/Rivendael/fastmssql)
50
+
51
+ [![Rust Backend](https://img.shields.io/badge/backend-rust-orange)](https://github.com/Rivendael/pymssql-rs)
52
+
53
+ ## Features
54
+
55
+ - High performance: optimized for very high RPS and low overhead
56
+ - Rust core: memory‑safe and reliable, tuned Tokio runtime
57
+ - No ODBC: native SQL Server client, no external drivers needed
58
+ - Connection pooling: bb8‑based, smart defaults (default max_size=10, min_idle=2)
59
+ - Async first: clean async/await API with `async with` context managers
60
+ - Strong typing: fast conversions for common SQL Server types
61
+ - Thread‑safe: safe to use in concurrent apps
62
+ - Cross‑platform: Windows, macOS, Linux
63
+ - Batch operations: high-performance bulk inserts and batch query execution
64
+
65
+
66
+ ## Key API methods
67
+
68
+ Core methods for individual operations:
69
+
70
+ - `query()` — SELECT statements that return rows
71
+ - `execute()` — INSERT/UPDATE/DELETE/DDL that return affected row count
72
+
73
+ ```python
74
+ # Use query() for SELECT statements
75
+ result = await conn.query("SELECT * FROM users WHERE age > @P1", [25])
76
+ rows = result.rows()
77
+
78
+ # Use execute() for data modification
79
+ affected = await conn.execute("INSERT INTO users (name) VALUES (@P1)", ["John"])
80
+ ```
81
+
82
+
83
+ ## Installation
84
+
85
+ ### From PyPI (recommended)
86
+
87
+ ```bash
88
+ pip install fastmssql
89
+ ```
90
+
91
+ ### Prerequisites
92
+
93
+ - Python 3.10 to 3.14
94
+ - Microsoft SQL Server (any recent version)
95
+
96
+ ## Quick start
97
+
98
+ ### Basic async usage
99
+
100
+ ```python
101
+ import asyncio
102
+ from fastmssql import Connection
103
+
104
+ async def main():
105
+ conn_str = "Server=localhost;Database=master;User Id=myuser;Password=mypass"
106
+ async with Connection(conn_str) as conn:
107
+ # SELECT: use query() -> rows()
108
+ result = await conn.query("SELECT @@VERSION as version")
109
+ for row in result.rows():
110
+ print(row['version'])
111
+
112
+ # Pool statistics (tuple: connected, connections, idle, max_size, min_idle)
113
+ connected, connections, idle, max_size, min_idle = await conn.pool_stats()
114
+ print(f"Pool: connected={connected}, size={connections}/{max_size}, idle={idle}, min_idle={min_idle}")
115
+
116
+ asyncio.run(main())
117
+ ```
118
+
119
+ ## Explicit Connection Management
120
+
121
+ When not utilizing Python's context manager (async with), **FastMssql** uses *lazy connection initialization*:
122
+ if you call `query()` or `execute()` on a new `Connection`, the underlying pool is created if not already present.
123
+
124
+ For more control, you can explicitly connect and disconnect:
125
+
126
+ ```python
127
+ import asyncio
128
+ from fastmssql import Connection
129
+
130
+ async def main():
131
+ conn_str = "Server=localhost;Database=master;User Id=myuser;Password=mypass"
132
+ conn = Connection(conn_str)
133
+
134
+ # Explicitly connect
135
+ await conn.connect()
136
+ assert await conn.is_connected()
137
+
138
+ # Run queries
139
+ result = await conn.query("SELECT 42 as answer")
140
+ print(result.rows()[0]["answer"]) # -> 42
141
+
142
+ # Explicitly disconnect
143
+ await conn.disconnect()
144
+ assert not await conn.is_connected()
145
+
146
+ asyncio.run(main())
147
+ ```
148
+ ## Usage
149
+
150
+ ### Connection options
151
+
152
+ You can connect either with a connection string or individual parameters.
153
+
154
+ 1) Connection string
155
+
156
+ ```python
157
+ import asyncio
158
+ from fastmssql import Connection
159
+
160
+ async def main():
161
+ conn_str = "Server=localhost;Database=master;User Id=myuser;Password=mypass"
162
+ async with Connection(connection_string=conn_str) as conn:
163
+ rows = (await conn.query("SELECT DB_NAME() as db")).rows()
164
+ print(rows[0]['db'])
165
+
166
+ asyncio.run(main())
167
+ ```
168
+
169
+ 2) Individual parameters
170
+
171
+ ```python
172
+ import asyncio
173
+ from fastmssql import Connection
174
+
175
+ async def main():
176
+ async with Connection(
177
+ server="localhost",
178
+ database="master",
179
+ username="myuser",
180
+ password="mypassword"
181
+ ) as conn:
182
+ rows = (await conn.query("SELECT SUSER_SID() as sid")).rows()
183
+ print(rows[0]['sid'])
184
+
185
+ asyncio.run(main())
186
+ ```
187
+
188
+ Note: Windows authentication (Trusted Connection) is currently not supported. Use SQL authentication (username/password).
189
+
190
+
191
+ ### Working with data
192
+
193
+ ```python
194
+ import asyncio
195
+ from fastmssql import Connection
196
+
197
+ async def main():
198
+ async with Connection("Server=.;Database=MyDB;User Id=sa;Password=StrongPwd;") as conn:
199
+ # SELECT (returns rows)
200
+ users = (await conn.query(
201
+ "SELECT id, name, email FROM users WHERE active = 1"
202
+ )).rows()
203
+ for u in users:
204
+ print(f"User {u['id']}: {u['name']} ({u['email']})")
205
+
206
+ # INSERT / UPDATE / DELETE (returns affected row count)
207
+ inserted = await conn.execute(
208
+ "INSERT INTO users (name, email) VALUES (@P1, @P2)",
209
+ ["Jane", "jane@example.com"],
210
+ )
211
+ print(f"Inserted {inserted} row(s)")
212
+
213
+ updated = await conn.execute(
214
+ "UPDATE users SET last_login = GETDATE() WHERE id = @P1",
215
+ [123],
216
+ )
217
+ print(f"Updated {updated} row(s)")
218
+
219
+ asyncio.run(main())
220
+ ```
221
+
222
+ Parameters use positional placeholders: `@P1`, `@P2`, ... Provide values as a list in the same order.
223
+
224
+
225
+ ### Batch operations
226
+
227
+ For high-throughput scenarios, use batch methods to reduce network round-trips:
228
+
229
+ ```python
230
+ import asyncio
231
+ from fastmssql import Connection
232
+
233
+ async def main_fetching():
234
+ # Replace with your actual connection string
235
+ async with Connection("Server=.;Database=MyDB;User Id=sa;Password=StrongPwd;") as conn:
236
+
237
+ # --- 1. Prepare Data for Demonstration ---
238
+ columns = ["name", "email", "age"]
239
+ data_rows = [
240
+ ["Alice Johnson", "alice@example.com", 28],
241
+ ["Bob Smith", "bob@example.com", 32],
242
+ ["Carol Davis", "carol@example.com", 25],
243
+ ["David Lee", "david@example.com", 35],
244
+ ["Eva Green", "eva@example.com", 29]
245
+ ]
246
+ await conn.bulk_insert("users", columns, data_rows)
247
+
248
+ # --- 2. Execute Query and Retrieve the Result Object ---
249
+ print("\n--- Result Object Fetching (fetchone, fetchmany, fetchall) ---")
250
+
251
+ # The Result object is returned after the awaitable query executes.
252
+ result = await conn.query("SELECT name, age FROM users ORDER BY age DESC")
253
+
254
+ # fetchone(): Retrieves the next single row synchronously.
255
+ oldest_user = result.fetchone()
256
+ if oldest_user:
257
+ print(f"1. fetchone: Oldest user is {oldest_user['name']} (Age: {oldest_user['age']})")
258
+
259
+ # fetchmany(2): Retrieves the next set of rows synchronously.
260
+ next_two_users = result.fetchmany(2)
261
+ print(f"2. fetchmany: Retrieved {len(next_two_users)} users: {[r['name'] for r in next_two_users]}.")
262
+
263
+ # fetchall(): Retrieves all remaining rows synchronously.
264
+ remaining_users = result.fetchall()
265
+ print(f"3. fetchall: Retrieved all {len(remaining_users)} remaining users: {[r['name'] for r in remaining_users]}.")
266
+
267
+ # Exhaustion Check: Subsequent calls return None/[]
268
+ print(f"4. Exhaustion Check (fetchone): {result.fetchone()}")
269
+ print(f"5. Exhaustion Check (fetchmany): {result.fetchmany(1)}")
270
+
271
+ # --- 3. Batch Commands for multiple operations ---
272
+ print("\n--- Batch Commands (execute_batch) ---")
273
+ commands = [
274
+ ("UPDATE users SET last_login = GETDATE() WHERE name = @P1", ["Alice Johnson"]),
275
+ ("INSERT INTO user_logs (action, user_name) VALUES (@P1, @P2)", ["login", "Alice Johnson"])
276
+ ]
277
+
278
+ affected_counts = await conn.execute_batch(commands)
279
+ print(f"Updated {affected_counts[0]} users, inserted {affected_counts[1]} logs")
280
+
281
+ asyncio.run(main_fetching())
282
+ ```
283
+
284
+ ### Connection pooling
285
+
286
+ Tune the pool to fit your workload. Constructor signature:
287
+
288
+ ```python
289
+ from fastmssql import PoolConfig
290
+
291
+ # PoolConfig(max_size=10, min_idle=2, max_lifetime_secs=None, idle_timeout_secs=None, connection_timeout_secs=30)
292
+ config = PoolConfig(
293
+ max_size=20, # max connections in pool
294
+ min_idle=5, # keep at least this many idle
295
+ max_lifetime_secs=3600, # recycle connections after 1h
296
+ idle_timeout_secs=600, # close idle connections after 10m
297
+ connection_timeout_secs=30
298
+ )
299
+ ```
300
+
301
+ Presets:
302
+
303
+ ```python
304
+ one. = PoolConfig.one() # ~ max_size=1, min_idle=1
305
+ low = PoolConfig.low_resource() # ~ max_size=3, min_idle=1
306
+ dev = PoolConfig.development() # ~ max_size=5, min_idle=1
307
+ high = PoolConfig.high_throughput() # ~ max_size=50, min_idle=15
308
+ maxp = PoolConfig.performance() # ~ max_size=100, min_idle=30
309
+ ```
310
+
311
+ Apply to a connection:
312
+
313
+ ```python
314
+ async with Connection(conn_str, pool_config=high) as conn:
315
+ rows = (await conn.query("SELECT 1 AS ok")).rows()
316
+ ```
317
+
318
+ Default pool (if omitted): `max_size=10`, `min_idle=2`.
319
+
320
+
321
+ ### SSL/TLS
322
+
323
+ For `Required` and `LoginOnly` encryption, you must specify how to validate the server certificate:
324
+
325
+ **Option 1: Trust Server Certificate** (development/self-signed certs):
326
+ ```python
327
+ from fastmssql import SslConfig, EncryptionLevel, Connection
328
+
329
+ ssl = SslConfig(
330
+ encryption_level=EncryptionLevel.Required,
331
+ trust_server_certificate=True
332
+ )
333
+
334
+ async with Connection(conn_str, ssl_config=ssl) as conn:
335
+ ...
336
+ ```
337
+
338
+ **Option 2: Custom CA Certificate** (production):
339
+ ```python
340
+ from fastmssql import SslConfig, EncryptionLevel, Connection
341
+
342
+ ssl = SslConfig(
343
+ encryption_level=EncryptionLevel.Required,
344
+ ca_certificate_path="/path/to/ca-cert.pem"
345
+ )
346
+
347
+ async with Connection(conn_str, ssl_config=ssl) as conn:
348
+ ...
349
+ ```
350
+
351
+ **Note**: `trust_server_certificate` and `ca_certificate_path` are mutually exclusive.
352
+
353
+ Helpers:
354
+
355
+ - `SslConfig.development()` – encrypt, trust all (dev only)
356
+ - `SslConfig.with_ca_certificate(path)` – use custom CA
357
+ - `SslConfig.login_only()` / `SslConfig.disabled()` – legacy modes
358
+ - `SslConfig.disabled()` – no encryption (not recommended)
359
+
360
+
361
+ ## Performance tips
362
+
363
+ For maximum throughput in highly concurrent scenarios, use multiple `Connection` instances (each with its own pool) and batch your work:
364
+
365
+ ```python
366
+ import asyncio
367
+ from fastmssql import Connection, PoolConfig
368
+
369
+ async def worker(conn_str, cfg):
370
+ async with Connection(conn_str, pool_config=cfg) as conn:
371
+ for _ in range(1000):
372
+ _ = (await conn.query("SELECT 1 as v")).rows()
373
+
374
+ async def main():
375
+ conn_str = "Server=.;Database=master;User Id=sa;Password=StrongPwd;"
376
+ cfg = PoolConfig.high_throughput()
377
+ await asyncio.gather(*[asyncio.create_task(worker(conn_str, cfg)) for _ in range(32)])
378
+
379
+ asyncio.run(main())
380
+ ```
381
+
382
+
383
+ ## Examples & benchmarks
384
+
385
+ - Examples: `examples/comprehensive_example.py`
386
+ - Benchmarks: `benchmarks/`
387
+
388
+
389
+ ## Troubleshooting
390
+
391
+ - Import/build: ensure Rust toolchain and `maturin` are installed if building from source
392
+ - Connection: verify connection string; Windows auth not supported
393
+ - Timeouts: increase pool size or tune `connection_timeout_secs`
394
+ - Parameters: use `@P1, @P2, ...` and pass a list of values
395
+
396
+
397
+ ## Contributing
398
+
399
+ Contributions are welcome. Please open an issue or PR.
400
+
401
+
402
+ ## License
403
+
404
+ FastMSSQL is licensed under MIT:
405
+
406
+ See the [LICENSE](LICENSE) file for details.
407
+
408
+ ## Third‑party attributions
409
+
410
+ Built on excellent open source projects: Tiberius, PyO3, pyo3‑asyncio, bb8, tokio, serde, pytest, maturin, and more. See `licenses/NOTICE.txt` for the full list. The full texts of Apache‑2.0 and MIT are in `licenses/`.
411
+
412
+
413
+ ## Acknowledgments
414
+
415
+ Thanks to the maintainers of Tiberius, PyO3, pyo3‑asyncio, Tokio, pytest, maturin, and the broader open source community.
@@ -0,0 +1,6 @@
1
+ fastmssql-0.5.0.dist-info/METADATA,sha256=4KxzPnFJ_hIlepKELDUdT9QrapmgeaSTcrSQrB7BQtE,14059
2
+ fastmssql-0.5.0.dist-info/WHEEL,sha256=X_Cce7mIV5wGTHIl0EkW0q8IpVi433Ij5ILty3Nzqfk,145
3
+ fastmssql-0.5.0.dist-info/licenses/LICENSE,sha256=CWJTVQpPm5xURNm1EgddZQllDC7KDdgMfE_lY4n5Ows,1065
4
+ fastmssql/__init__.py,sha256=8J1RvUa8coOP7Rkhdk-DkWQwrmE6xDMzmOSnAf6MohQ,1792
5
+ fastmssql/fastmssql.abi3.so,sha256=OgVWx2ABXvn3QZVPnH4chHYVOw0XIFRwuh7j8E5phOM,2607040
6
+ fastmssql-0.5.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.10.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp310-abi3-manylinux_2_17_x86_64
5
+ Tag: cp310-abi3-manylinux2014_x86_64
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Rivendael
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 all
13
+ 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 THE
21
+ SOFTWARE.