fastmssql 0.2.6__cp310-cp310-macosx_11_0_arm64.whl → 0.3.2__cp310-cp310-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

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