fastmssql 0.2.2__cp313-cp313-win_amd64.whl → 0.3.2__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.

Potentially problematic release.


This version of fastmssql might be problematic. Click here for more details.

@@ -1,819 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: fastmssql
3
- Version: 0.2.2
4
- Classifier: Development Status :: 4 - Beta
5
- Classifier: Intended Audience :: Developers
6
- Classifier: License :: Other/Proprietary License
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: Programming Language :: Python :: 3.8
9
- Classifier: Programming Language :: Python :: 3.9
10
- Classifier: Programming Language :: Python :: 3.10
11
- Classifier: Programming Language :: Python :: 3.11
12
- Classifier: Programming Language :: Python :: 3.12
13
- Classifier: Programming Language :: Python :: 3.13
14
- Classifier: Programming Language :: Rust
15
- Classifier: Topic :: Database
16
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
- Requires-Dist: pytest>=7.0 ; extra == 'dev'
18
- Requires-Dist: pytest-asyncio>=0.21 ; extra == 'dev'
19
- Requires-Dist: psutil>=5.9.0 ; extra == 'dev'
20
- Provides-Extra: dev
21
- License-File: LICENSE
22
- Summary: A high-performance Python library for Microsoft SQL Server using Rust and Tiberius
23
- Author-email: Riveranda <riverb514@gmail.com>
24
- License: PolyForm Noncommercial License 1.0.0
25
- Requires-Python: >=3.8
26
- Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
27
- Project-URL: Homepage, https://github.com/Rivendael/pymssql-rs
28
-
29
-
30
- # Fastmssql ⚡
31
-
32
- A **blazingly fast** Python library for Microsoft SQL Server that delivers **significant performance improvements** over standard libraries. Built with Rust using the [Tiberius](https://github.com/prisma/tiberius) driver, [PyO3](https://github.com/PyO3/pyo3), and [bb8](https://github.com/djc/bb8) connection pooling.
33
-
34
- > **🚀 Performance Highlight**: Achieves **3,493 requests/second** and **0.08 KB memory per query** in our benchmarks
35
-
36
- [![Performance](https://img.shields.io/badge/Performance-3493_RPS-brightgreen)](https://github.com/Rivendael/pymssql-rs)
37
- [![Memory](https://img.shields.io/badge/Memory-0.08_KB/query-blue)](https://github.com/Rivendael/pymssql-rs)
38
- [![Speed](https://img.shields.io/badge/Speed-High_Performance-orange)](https://github.com/Rivendael/pymssql-rs)
39
- [![Language](https://img.shields.io/badge/Language-Rust_Backend-red)](https://github.com/Rivendael/pymssql-rs)
40
- [![Async](https://img.shields.io/badge/Async-Native_Tokio-blue)](https://github.com/Rivendael/pymssql-rs)
41
-
42
- ## Features
43
-
44
- - **High Performance**: Built with Rust for memory safety and speed
45
- - **No ODBC Required**: Direct native SQL Server connection without ODBC drivers
46
- - **Connection Pooling**: Advanced bb8-based connection pool for optimal performance
47
- - **Async-Only Design**: Built on Tokio for excellent concurrency with clean async/await API
48
- - **Context Managers**: Automatic resource management with `async with`
49
- - **Type Safety**: Strong typing with automatic Python type conversion
50
- - **Thread Safety**: Full support for concurrent operations
51
- - **Cross-Platform**: Works on Windows, macOS, and Linux
52
- - **Simple API**: Clean, intuitive async-only interface
53
-
54
- ## ⚡ Performance
55
-
56
- Fastmssql delivers **excellent performance** that outperforms standard Python SQL Server libraries in our testing:
57
-
58
- ### 🚀 Benchmark Results
59
-
60
- | Library | RPS (Requests/Second) | Performance vs fastmssql |
61
- |---------|----------------------|--------------------------|
62
- | **fastmssql** | **3,493** | **Baseline** |
63
- | Other Python libraries | ~300-600* | **5-11x slower** |
64
-
65
- *Benchmarks performed with 20 concurrent workers executing `SELECT @@VERSION` queries on our test environment. Performance of other libraries may vary based on configuration, environment, and specific use cases. We recommend conducting your own benchmarks for your specific requirements.*
66
-
67
- ### 🧠 Memory Efficiency
68
-
69
- Fastmssql delivers **exceptional memory efficiency** with minimal overhead:
70
-
71
- | Metric | Value | Description |
72
- |--------|-------|-------------|
73
- | **Per Query Overhead** | **0.08 KB** | Memory used per database query |
74
- | **Concurrent Overhead** | **3.52 KB** | Memory per concurrent operation |
75
- | **Connection Pool** | **5.26 MB** | One-time pool initialization |
76
- | **Memory Leaks** | **None** | Actually reduces memory over time |
77
-
78
- **Memory Efficiency Highlights:**
79
- - **12,800 queries per MB** of memory overhead
80
- - **Zero memory leaks** - memory usage decreases over time
81
- - **100-1000x more efficient** than libraries without connection pooling
82
- - **Stable memory usage** under high concurrent load
83
-
84
- *Traditional Python SQL Server libraries typically use 50-200 KB per operation due to connection overhead and lack of efficient pooling.*
85
-
86
- ## Installation
87
-
88
- ### From PyPI (Recommended)
89
-
90
- Install fastmssql using pip:
91
-
92
- ```bash
93
- pip install fastmssql
94
- ```
95
-
96
- ### Prerequisites
97
-
98
- - Python 3.8 to 3.13
99
- - Microsoft SQL Server (any recent version)
100
-
101
- ### From Source (Development)
102
- Ensure you have Docker, Rust, and Python installed.
103
- If you want to build from source or contribute to development:
104
-
105
- 1. Clone the repository:
106
- ```bash
107
- git clone <your-repo-url>
108
- cd mssql-python-rust
109
- ```
110
-
111
- 2. Run the setup script
112
- ```
113
- ./setup.sh
114
- ```
115
-
116
- ## Quick Start
117
-
118
- > **💡 Performance Tip**: Always reuse `Connection` objects! Each `Connection` manages a connection pool, so creating multiple `Connection` instances defeats the purpose of pooling and hurts performance. Create one `Connection` per database and reuse it throughout your application.
119
-
120
- ### Basic Async Usage (Recommended)
121
-
122
- ```python
123
- import asyncio
124
- from fastmssql import Connection
125
-
126
- async def main():
127
- # Connect to SQL Server using async context manager
128
- connection_string = "Server=localhost;Database=master;User Id=myuser;Password=mypass"
129
-
130
- # Automatic connection pool management
131
- async with Connection(connection_string) as conn:
132
- rows = await conn.execute("SELECT @@VERSION as version")
133
- for row in rows:
134
- print(row['version'])
135
-
136
- # Pool statistics
137
- stats = conn.pool_stats()
138
- print(f"Pool: {stats['active_connections']}/{stats['connections']} connections active")
139
-
140
- asyncio.run(main())
141
- ```
142
-
143
- ### Connection Methods
144
-
145
- The library supports two ways to connect to SQL Server:
146
-
147
- #### 1. Connection String (Traditional)
148
-
149
- ```python
150
- import asyncio
151
- from fastmssql import Connection
152
-
153
- async def main():
154
- # Traditional connection string approach
155
- connection_string = "Server=localhost;Database=master;User Id=myuser;Password=mypass"
156
-
157
- async with Connection(connection_string=connection_string) as conn:
158
- result = await conn.execute("SELECT @@VERSION as version")
159
- for row in result.rows():
160
- print(row['version'])
161
-
162
- asyncio.run(main())
163
- ```
164
-
165
- #### 2. Individual Parameters
166
-
167
- ```python
168
- import asyncio
169
- from fastmssql import Connection
170
-
171
- async def main():
172
- # Using individual connection parameters
173
-
174
- # SQL Server Authentication
175
- async with Connection(
176
- server="localhost",
177
- database="master",
178
- username="myuser",
179
- password="mypassword"
180
- ) as conn:
181
- result = await conn.execute("SELECT SUSER_NAME() as login")
182
- for row in result.rows():
183
- print(f"Logged in as: {row['login']}")
184
-
185
- asyncio.run(main())
186
- ```
187
-
188
- ### Connection Pool Configuration
189
-
190
- Configure the connection pool for your specific needs:
191
-
192
- ```python
193
- import asyncio
194
- from fastmssql import Connection, PoolConfig
195
-
196
- async def main():
197
- # Custom pool configuration
198
- pool_config = PoolConfig(
199
- max_size=20, # Maximum connections in pool
200
- min_idle=5, # Minimum idle connections
201
- max_lifetime_secs=3600, # Connection max lifetime (1 hour)
202
- idle_timeout_secs=600, # Idle connection timeout (10 min)
203
- connection_timeout_secs=30 # Max wait time for connection
204
- )
205
-
206
- async with Connection(connection_string, pool_config) as conn:
207
- result = await conn.execute("SELECT * FROM users")
208
-
209
- # Predefined configurations for common scenarios
210
- high_throughput_config = PoolConfig.high_throughput() # 20 connections, optimized for load
211
- low_resource_config = PoolConfig.low_resource() # 3 connections, minimal resources
212
- dev_config = PoolConfig.development() # 5 connections, shorter timeouts
213
-
214
- asyncio.run(main())
215
- ```
216
-
217
- ### 🔥 Maximum Performance Configuration
218
-
219
- For applications requiring **extreme performance**, use the high-throughput configuration:
220
-
221
- ```python
222
- import asyncio
223
- from fastmssql import Connection, PoolConfig
224
-
225
- async def main():
226
- # Maximum performance setup
227
- extreme_config = PoolConfig.high_throughput() # Optimized for 3000+ RPS
228
-
229
- async with Connection(connection_string, extreme_config) as conn:
230
- # This setup achieves 3,493 RPS in benchmarks
231
-
232
- # Concurrent workers for maximum throughput
233
- async def worker():
234
- result = await conn.execute("SELECT @@VERSION")
235
- return result.rows()
236
-
237
- # Run 20 concurrent workers
238
- tasks = [worker() for _ in range(20)]
239
- results = await asyncio.gather(*tasks)
240
-
241
- # Pool monitoring
242
- stats = await conn.pool_stats()
243
- print(f"Pool utilization: {stats['active_connections']}/{stats['max_size']}")
244
-
245
- asyncio.run(main())
246
- ```
247
-
248
- **Performance Tips:**
249
- - **Reuse Connection objects**: Create one `Connection` per database and reuse it across your application
250
- - Use `PoolConfig.high_throughput()` for maximum RPS
251
- - Leverage `asyncio.gather()` for concurrent operations
252
- - Monitor pool stats to optimize connection count
253
- - Consider connection lifetime for long-running applications
254
-
255
- **⚠️ Performance Anti-Pattern:**
256
- ```python
257
- # DON'T DO THIS - Creates new pool for each operation
258
- async def bad_example():
259
- async with Connection(conn_str) as conn: # New pool created
260
- return await conn.execute("SELECT 1")
261
-
262
- async with Connection(conn_str) as conn: # Another new pool created
263
- return await conn.execute("SELECT 2")
264
- ```
265
-
266
- **✅ Correct Pattern:**
267
- ```python
268
- # DO THIS - Reuse the same connection pool
269
- async def good_example():
270
- async with Connection(conn_str) as conn: # Single pool created
271
- result1 = await conn.execute("SELECT 1")
272
- result2 = await conn.execute("SELECT 2") # Reuses same pool
273
- return result1, result2
274
- ```
275
-
276
- ### Connection Pool Benefits
277
-
278
- The bb8 connection pool provides significant performance improvements over traditional Python libraries:
279
-
280
- | Metric | Traditional Python | fastmssql | Improvement |
281
- |--------|-------------------|-----------|-------------|
282
- | **Connection Setup** | 50ms | 0.1ms | **500x faster** |
283
- | **Memory per Query** | 50-200 KB | 0.08 KB | **625-2500x less** |
284
- | **10 Concurrent Queries** | 500ms | 150ms | **3.3x faster** |
285
- | **100 Concurrent Queries** | 5000ms | 400ms | **12.5x faster** |
286
- | **1000 Concurrent Queries** | Timeouts/Errors | 2.9s | **Stable** |
287
- | **Memory Leaks** | Common | None | **Zero leaks** |
288
-
289
- **Key Benefits:**
290
- - **Connection Reuse**: Eliminates connection establishment overhead (500x improvement)
291
- - **Memory Efficiency**: Uses 625-2500x less memory per operation (0.08 KB vs 50-200 KB)
292
- - **Zero Memory Leaks**: Automatic cleanup with decreasing memory usage over time
293
- - **Concurrency**: Safe multi-threaded access with automatic pooling
294
- - **Resource Management**: Intelligent memory and connection lifecycle management
295
- - **Load Balancing**: Intelligent connection distribution across threads
296
- - **Fault Tolerance**: Built-in retry logic and connection health checks
297
- - **Timeouts**: Configurable timeouts prevent hanging connections
298
-
299
- ### Connection Strings
300
-
301
- The library supports standard SQL Server connection string formats:
302
-
303
- ```python
304
- # SQL Server Authentication
305
- conn_str = "Server=localhost;Database=MyDB;User Id=sa;Password=MyPassword"
306
-
307
- # With specific port
308
- conn_str = "Server=localhost,1433;Database=MyDB;User Id=myuser;Password=mypass"
309
-
310
- # Azure SQL Database
311
- conn_str = "Server=tcp:myserver.database.windows.net,1433;Database=MyDB;User Id=myuser;Password=mypass;Encrypt=true"
312
- ```
313
-
314
- ### Working with Data
315
-
316
- ```python
317
- import asyncio
318
- from fastmssql import Connection
319
-
320
- async def main():
321
- async with Connection(connection_string) as conn:
322
- # Execute queries
323
- users = await conn.execute("SELECT id, name, email FROM users WHERE active = 1")
324
-
325
- # Iterate through results
326
- for user in users:
327
- print(f"User {user['id']}: {user['name']} ({user['email']})")
328
-
329
- # Execute non-query operations
330
- rows_affected = await conn.execute_non_query(
331
- "UPDATE users SET last_login = GETDATE() WHERE id = 123"
332
- )
333
- print(f"Updated {rows_affected} rows")
334
-
335
- # Work with different data types
336
- data = await conn.execute("""
337
- SELECT
338
- 42 as int_value,
339
- 3.14159 as float_value,
340
- 'Hello World' as string_value,
341
- GETDATE() as datetime_value,
342
- CAST(1 as BIT) as bool_value,
343
- NULL as null_value
344
- """)
345
-
346
- row = data[0]
347
- for column_name, value in row.items():
348
- print(f"{column_name}: {value} (type: {type(value).__name__})")
349
-
350
- asyncio.run(main())
351
- ```
352
-
353
- ## Usage
354
-
355
- ### Asynchronous Usage with Connection Pooling
356
-
357
- Full async/await support with automatic connection pool management:
358
-
359
- ```python
360
- import asyncio
361
- from fastmssql import Connection
362
-
363
- async def main():
364
- connection_string = "Server=localhost;Database=test;Integrated Security=true"
365
-
366
- # Async context manager with automatic pool management
367
- async with Connection(connection_string) as conn:
368
- rows = await conn.execute("SELECT name FROM sys.databases")
369
- for row in rows:
370
- print(row['name'])
371
-
372
- # Pool statistics
373
- stats = conn.pool_stats()
374
- print(f"Pool: {stats['active_connections']}/{stats['connections']} connections active")
375
-
376
- # High-performance concurrent operations
377
- async def fetch_user_data(user_id):
378
- async with Connection(connection_string) as conn:
379
- return await conn.execute(f"SELECT * FROM users WHERE id = {user_id}")
380
-
381
- # Execute multiple queries concurrently using the connection pool
382
- user_ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
383
- tasks = [fetch_user_data(uid) for uid in user_ids]
384
- results = await asyncio.gather(*tasks) # bb8 pool handles concurrent connections efficiently
385
-
386
- for user_data in results:
387
- if user_data:
388
- print(f"User: {user_data[0]['name']}")
389
-
390
- asyncio.run(main())
391
- ```
392
-
393
- ### Performance Comparison: bb8 Connection Pool
394
-
395
- The bb8 connection pool dramatically improves performance, especially under load:
396
-
397
- ```python
398
- import asyncio
399
- import time
400
- from fastmssql import Connection
401
-
402
- async def performance_comparison():
403
- connection_string = "Server=localhost;Database=test;User Id=myuser;Password=mypass"
404
-
405
- # Sequential async operations (still efficient with pool reuse)
406
- start = time.time()
407
- async with Connection(connection_string) as conn:
408
- for i in range(10):
409
- result = await conn.execute("SELECT COUNT(*) FROM users")
410
- sequential_time = time.time() - start
411
-
412
- # Concurrent async operations (much faster with bb8 pool)
413
- start = time.time()
414
- async def concurrent_queries():
415
- tasks = []
416
- for i in range(10):
417
- async def query():
418
- async with Connection(connection_string) as conn: # Pool reuse
419
- return await conn.execute("SELECT COUNT(*) FROM users")
420
- tasks.append(query())
421
- return await asyncio.gather(*tasks)
422
-
423
- await concurrent_queries()
424
- concurrent_time = time.time() - start
425
-
426
- print(f"Sequential: {sequential_time:.3f}s")
427
- print(f"Concurrent: {concurrent_time:.3f}s")
428
- print(f"Improvement: {sequential_time/concurrent_time:.1f}x faster")
429
-
430
- asyncio.run(performance_comparison())
431
- ```
432
-
433
- **Real-world Performance Benefits:**
434
- - **Web Applications**: Handle 100+ concurrent requests without connection exhaustion
435
- - **Batch Processing**: Process large datasets with optimal resource usage
436
- - **Microservices**: Reliable database connections across service boundaries
437
- - **Data Analytics**: Concurrent query execution for faster insights
438
-
439
- ## Examples
440
-
441
- Run the provided examples to see async patterns and features:
442
-
443
- ```bash
444
- # Basic asynchronous usage
445
- python examples/basic_usage.py
446
-
447
- # Advanced asynchronous features
448
- python examples/advanced_usage.py
449
-
450
- # Asynchronous usage patterns
451
- python examples/async_usage.py
452
-
453
- # Advanced pool configuration
454
- python examples/advanced_pool_config.py
455
-
456
- # Connection parameters demonstration
457
- python examples/connection_parameters_demo.py
458
- ```
459
-
460
- ### Key API Improvements
461
-
462
- Our async-only design provides a clean, intuitive interface:
463
-
464
- ```python
465
- # ✅ Clean async API (New Design)
466
- async with Connection(connection_string) as conn:
467
- result = await conn.execute(sql) # Intuitive!
468
- rows_affected = await conn.execute_non_query(sql)
469
-
470
- # ❌ Old confusing API (Removed)
471
- # async with Connection(connection_string) as conn:
472
- # result = await conn.execute_async(sql) # Confusing suffixes
473
- # rows_affected = await conn.execute_non_query_async(sql)
474
- ```
475
-
476
- ## Development
477
-
478
- ### Building from Source
479
-
480
- ```bash
481
- # Install development dependencies
482
- pip install maturin pytest pytest-asyncio black ruff
483
-
484
- # Build in development mode
485
- maturin develop
486
-
487
- # Run tests
488
- python -m pytest tests/
489
-
490
- # Format code
491
- black python/
492
- ruff check python/
493
- ```
494
-
495
- ### Project Structure
496
-
497
- ```
498
- mssql-python-rust/
499
- ├── src/ # Rust source code
500
- │ ├── lib.rs # Main library entry point
501
- │ ├── connection.rs # Connection handling
502
- │ ├── query.rs # Query execution
503
- │ └── types.rs # Type definitions
504
- ├── python/ # Python source code
505
- │ ├── __init__.py # Main Python module
506
- │ ├── mssql.py # High-level API
507
- │ └── types.py # Python type definitions
508
- ├── examples/ # Usage examples
509
- ├── tests/ # Test files
510
- ├── Cargo.toml # Rust dependencies
511
- ├── pyproject.toml # Python project configuration
512
- └── README.md # This file
513
- ```
514
-
515
- ### Testing
516
-
517
- Run the examples to test your installation:
518
-
519
- ```bash
520
- # Basic functionality
521
- python examples/basic_usage.py
522
-
523
- # Advanced features
524
- python examples/advanced_usage.py
525
- ```
526
-
527
- ## API Reference
528
-
529
- ### Core Classes
530
-
531
- #### `Connection`
532
- Main connection class with bb8 connection pool management.
533
-
534
- **Constructor:**
535
- ```python
536
- Connection(connection_string: str, pool_config: Optional[PoolConfig] = None)
537
- ```
538
-
539
- **Context Manager Support:**
540
- ```python
541
- # Synchronous
542
- with Connection(conn_str) as conn:
543
- result = conn.execute("SELECT * FROM table")
544
-
545
- # Asynchronous
546
- async with Connection(conn_str) as conn:
547
- result = await conn.execute_async("SELECT * FROM table")
548
- ```
549
-
550
- **Methods:**
551
- - `execute(sql: str) -> List[Row]` - Execute a query synchronously
552
- - `pool_stats() -> dict` - Get connection pool statistics
553
- - `disconnect()` - Close the connection pool
554
- - `is_connected() -> bool` - Check if pool is active
555
-
556
- **Pool Statistics:**
557
- ```python
558
- stats = conn.pool_stats()
559
- # Returns: {
560
- # 'connections': 10, # Total connections in pool
561
- # 'active_connections': 3, # Currently active connections
562
- # 'idle_connections': 7 # Available idle connections
563
- # }
564
- ```
565
-
566
- #### `PoolConfig`
567
- Configuration class for bb8 connection pool settings.
568
-
569
- **Constructor:**
570
- ```python
571
- PoolConfig(
572
- max_size: int = 10, # Maximum connections in pool
573
- min_idle: int = 0, # Minimum idle connections
574
- max_lifetime_secs: Optional[int] = None, # Connection max lifetime
575
- idle_timeout_secs: Optional[int] = None, # Idle connection timeout
576
- connection_timeout_secs: int = 30 # Max wait time for connection
577
- )
578
- ```
579
-
580
- **Predefined Configurations:**
581
- ```python
582
- # High throughput applications (web servers, APIs)
583
- config = PoolConfig.high_throughput() # 20 connections, optimized settings
584
-
585
- # Low resource environments (embedded, containers)
586
- config = PoolConfig.low_resource() # 3 connections, minimal overhead
587
-
588
- # Development environments
589
- config = PoolConfig.development() # 5 connections, shorter timeouts
590
- ```
591
-
592
- #### `Row`
593
- Represents a database row with column access.
594
-
595
- **Methods:**
596
- - `get(column: str) -> Value` - Get value by column name
597
- - `get_by_index(index: int) -> Value` - Get value by column index
598
- - `columns() -> List[str]` - Get column names
599
- - `values() -> List[Value]` - Get all values
600
- - `to_dict() -> dict` - Convert to dictionary
601
-
602
- ### Module Functions
603
-
604
- #### Connection Management
605
- ```python
606
- # Create connection with default pool settings
607
- connect(connection_string: str) -> Connection
608
-
609
- # Create async connection with default pool settings
610
- connect_async(connection_string: str) -> Connection
611
-
612
- # One-liner query execution
613
- execute(connection_string: str, sql: str) -> List[dict]
614
- execute_async(connection_string: str, sql: str) -> List[dict]
615
- ```
616
-
617
- #### Utility Functions
618
- ```python
619
- version() -> str # Get library version
620
- ```
621
-
622
- ### Connection Pool Architecture
623
-
624
- The library uses the bb8 connection pool for efficient resource management:
625
-
626
- 1. **Pool Initialization**: Creates a pool of reusable connections on first use
627
- 2. **Connection Reuse**: Automatically reuses idle connections for new requests
628
- 3. **Load Balancing**: Distributes connections across concurrent operations
629
- 4. **Automatic Cleanup**: Closes idle connections based on timeout settings
630
- 5. **Thread Safety**: Safe for use across multiple threads and async tasks
631
-
632
- ### Error Handling
633
-
634
- ```python
635
- try:
636
- async with mssql.connect_async(connection_string) as conn:
637
- result = await conn.execute("SELECT * FROM invalid_table")
638
- except Exception as e:
639
- print(f"Database error: {e}")
640
- # Connection automatically returned to pool even on error
641
- ```
642
-
643
- ## Migration to Async-Only Architecture
644
-
645
- This library has been upgraded to use async-only operations with the bb8 connection pool for improved performance and reliability.
646
-
647
- **Async-Only API:**
648
- ```python
649
- # Async-only with automatic connection pooling
650
- async with mssql.connect_async(conn_str) as conn:
651
- result = await conn.execute("SELECT * FROM table")
652
-
653
- # Pool statistics
654
- stats = conn.pool_stats()
655
- print(f"Pool utilization: {stats['active_connections']}/{stats['connections']}")
656
- ```
657
-
658
- **Features:**
659
- - Async-only operations for maximum performance
660
- - Automatic connection pooling with bb8
661
- - Configurable pool settings via `PoolConfig`
662
- - Pool statistics and monitoring
663
- - Improved concurrent performance
664
- - Better resource management
665
-
666
- **Breaking Changes:**
667
- - None - the API is fully backward compatible
668
- - All existing code continues to work without modification
669
- - Performance improvements are automatic
670
-
671
- ## Advanced Usage Patterns
672
-
673
- ### Custom Pool Configuration for Different Scenarios
674
-
675
- ```python
676
- from fastmssql import Connection, PoolConfig
677
-
678
- # High-load web application
679
- web_config = PoolConfig(
680
- max_size=50, # Handle many concurrent requests
681
- min_idle=10, # Keep connections ready
682
- max_lifetime_secs=1800, # 30 min connection lifetime
683
- idle_timeout_secs=300, # 5 min idle timeout
684
- connection_timeout_secs=10 # Fast timeout for web responses
685
- )
686
-
687
- # Batch processing application
688
- batch_config = PoolConfig(
689
- max_size=5, # Fewer connections
690
- min_idle=2, # Always keep some ready
691
- max_lifetime_secs=7200, # 2 hour lifetime for long operations
692
- idle_timeout_secs=1800, # 30 min idle timeout
693
- connection_timeout_secs=60 # Longer timeout for batch work
694
- )
695
-
696
- # Microservice with limited resources
697
- micro_config = PoolConfig(
698
- max_size=3, # Minimal connections
699
- min_idle=1, # One always ready
700
- max_lifetime_secs=3600, # 1 hour lifetime
701
- idle_timeout_secs=600, # 10 min idle timeout
702
- connection_timeout_secs=15 # Quick timeout
703
- )
704
- ```
705
-
706
- ### Monitoring Pool Health
707
-
708
- ```python
709
- async def monitor_database_pool():
710
- """Monitor connection pool health and performance"""
711
-
712
- async with mssql.connect_async(connection_string) as conn:
713
- while True:
714
- stats = conn.pool_stats()
715
- utilization = stats['active_connections'] / stats['connections'] * 100
716
-
717
- print(f"Pool Utilization: {utilization:.1f}%")
718
- print(f"Active: {stats['active_connections']}, Idle: {stats['idle_connections']}")
719
-
720
- # Alert if pool utilization is too high
721
- if utilization > 90:
722
- print("WARNING: High pool utilization detected!")
723
-
724
- await asyncio.sleep(30) # Check every 30 seconds
725
- ```
726
-
727
- ### Optimizing for Different Database Workloads
728
-
729
- ```python
730
- # OLTP (Online Transaction Processing) - Many small, fast queries
731
- oltp_config = PoolConfig.high_throughput()
732
- async def oltp_operations():
733
- async with mssql.connect_async(conn_str, oltp_config) as conn:
734
- # Fast, concurrent transactions
735
- tasks = [
736
- conn.execute_async("SELECT * FROM users WHERE id = $1", [user_id])
737
- for user_id in range(1, 101)
738
- ]
739
- results = await asyncio.gather(*tasks)
740
-
741
- # OLAP (Online Analytical Processing) - Fewer, longer-running queries
742
- olap_config = PoolConfig.low_resource()
743
- async def olap_operations():
744
- async with mssql.connect_async(conn_str, olap_config) as conn:
745
- # Long-running analytical queries
746
- quarterly_report = await conn.execute_async("""
747
- SELECT
748
- DATE_TRUNC('quarter', order_date) as quarter,
749
- SUM(total_amount) as total_revenue,
750
- COUNT(*) as order_count
751
- FROM orders
752
- WHERE order_date >= '2024-01-01'
753
- GROUP BY DATE_TRUNC('quarter', order_date)
754
- ORDER BY quarter
755
- """)
756
- return quarterly_report
757
- ```
758
-
759
- ## Troubleshooting
760
-
761
- ### Common Issues
762
-
763
- 1. **Import Error**: Make sure you've built the extension with `maturin develop`
764
- 2. **Connection Fails**: Check your connection string and SQL Server configuration. Note that Windows authentication is not supported - use SQL Server authentication with username and password.
765
- 3. **Build Errors**: Ensure you have the Rust toolchain installed
766
- 4. **Build Issues**: Make sure you have the Microsoft Visual C++ Build Tools on Windows
767
-
768
-
769
- ## Contributing
770
-
771
- Contributions are welcome! Please open an issue or submit a pull request for any enhancements or bug fixes.
772
-
773
-
774
- ## License
775
-
776
- This project is licensed under the PolyForm Noncommercial License 1.0.0. See the LICENSE file for details.
777
-
778
- ## Third-Party Attributions
779
-
780
- This project includes and depends on third-party libraries licensed under the Apache License 2.0 and MIT License, as well as other open source licenses.
781
-
782
- **Note:** Additional third-party libraries and their license information are listed in `licenses/NOTICE.txt`.
783
-
784
- - [Tiberius](https://github.com/prisma/tiberius) (Apache License 2.0)
785
- - [PyO3](https://github.com/PyO3/pyo3) (Apache License 2.0)
786
- - [pyo3-asyncio](https://github.com/PyO3/pyo3-asyncio) (Apache License 2.0)
787
- - [bb8](https://github.com/djc/bb8) (MIT or Apache License 2.0)
788
- - [bb8-tiberius](https://github.com/prisma/tiberius) (Apache License 2.0)
789
- - [tokio](https://github.com/tokio-rs/tokio) (MIT or Apache License 2.0)
790
- - [tokio-util](https://github.com/tokio-rs/tokio) (MIT or Apache License 2.0)
791
- - [futures](https://github.com/rust-lang/futures-rs) (MIT or Apache License 2.0)
792
- - [serde](https://github.com/serde-rs/serde) (MIT or Apache License 2.0)
793
- - [serde_json](https://github.com/serde-rs/json) (MIT or Apache License 2.0)
794
- - [anyhow](https://github.com/dtolnay/anyhow) (MIT or Apache License 2.0)
795
- - [chrono](https://github.com/chronotope/chrono) (MIT or Apache License 2.0)
796
- - [uuid](https://github.com/uuid-rs/uuid) (MIT or Apache License 2.0)
797
- - [tempfile](https://github.com/Stebalien/tempfile) (MIT or Apache License 2.0)
798
- - [pytest](https://github.com/pytest-dev/pytest) (MIT License)
799
- - [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) (MIT License)
800
- - [black](https://github.com/psf/black) (MIT License)
801
- - [ruff](https://github.com/astral-sh/ruff) (MIT License)
802
- - [maturin](https://github.com/PyO3/maturin) (Apache License 2.0 or MIT License)
803
- - [Python](https://www.python.org/) and [asyncio](https://docs.python.org/3/library/asyncio.html) (Python Software Foundation License)
804
-
805
- See the `licenses/NOTICE.txt` file for full attribution and copyright information.
806
- The full text of the Apache License 2.0 is provided in the `licenses/APACHE_LICENSE_2.0.txt` file.
807
- The full text of the MIT License is provided in the `licenses/MIT_LICENSE.txt` file.
808
-
809
- ## Acknowledgments
810
-
811
- - [Tiberius](https://github.com/prisma/tiberius) - Rust SQL Server driver (Apache License 2.0)
812
- - [PyO3](https://github.com/PyO3/pyo3) - Python bindings for Rust (Apache License 2.0)
813
- - [pyo3-asyncio](https://github.com/PyO3/pyo3-asyncio) - Async bridge for PyO3 (Apache License 2.0)
814
- - [pytest](https://github.com/pytest-dev/pytest) - Python testing framework (MIT License)
815
- - [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) - Async test support for pytest (MIT License)
816
- - [black](https://github.com/psf/black) - Python code formatter (MIT License)
817
- - [ruff](https://github.com/astral-sh/ruff) - Python linter (MIT License)
818
- - [Python](https://www.python.org/) and [asyncio](https://docs.python.org/3/library/asyncio.html) - Python standard library (Python Software Foundation License)
819
- - [Maturin](https://github.com/PyO3/maturin) - Build tool for Python extensions in Rust