fastmssql 0.2.8__cp39-cp39-macosx_11_0_arm64.whl → 0.2.9__cp39-cp39-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.

fastmssql/__init__.py CHANGED
@@ -23,18 +23,25 @@ Basic Usage (Async):
23
23
  >>>
24
24
  >>> async def main():
25
25
  ... async with Connection("Server=localhost;Database=test;Trusted_Connection=yes") as conn:
26
- ... # Simple query
27
- ... result = await conn.execute("SELECT * FROM users")
26
+ ... # SELECT queries - use query() method
27
+ ... result = await conn.query("SELECT * FROM users")
28
28
  ... async for row in result:
29
29
  ... print(f"User: {row['name']}, Age: {row['age']}")
30
30
  ...
31
- ... # Parameterized query
32
- ... result = await conn.execute(
31
+ ... # Parameterized SELECT query
32
+ ... result = await conn.query(
33
33
  ... "SELECT * FROM users WHERE age > @P1 AND city = @P2",
34
34
  ... [18, "New York"]
35
35
  ... )
36
36
  ... rows = await result.fetchall()
37
37
  ... print(f"Found {len(rows)} users")
38
+ ...
39
+ ... # INSERT/UPDATE/DELETE - use execute() method
40
+ ... affected = await conn.execute(
41
+ ... "INSERT INTO users (name, email, age) VALUES (@P1, @P2, @P3)",
42
+ ... ["John Doe", "john@example.com", 30]
43
+ ... )
44
+ ... print(f"Inserted {affected} rows")
38
45
  >>>
39
46
  >>> asyncio.run(main())
40
47
 
@@ -42,11 +49,9 @@ Basic Usage (Sync):
42
49
  >>> from fastmssql import Connection
43
50
  >>>
44
51
  >>> with Connection("Server=localhost;Database=test;Trusted_Connection=yes") as conn:
45
- ... result = conn.execute_with_python_params(
46
- ... "SELECT COUNT(*) as count FROM users WHERE active = ?",
47
- ... [True]
48
- ... )
49
- ... print(f"Active users: {result[0]['count']}")
52
+ ... # For SELECT queries, you would typically use the async API
53
+ ... # Sync usage is primarily for simple operations
54
+ ... pass # Connection established and will be closed on exit
50
55
 
51
56
  Advanced Configuration:
52
57
  >>> from fastmssql import Connection, PoolConfig, SslConfig, EncryptionLevel
@@ -232,13 +237,19 @@ class Connection:
232
237
  trusted_connection=trusted_connection
233
238
  )
234
239
 
235
- async def execute(self, query, parameters=None):
240
+ async def query(self, query, parameters=None):
236
241
  """
237
- Execute a SQL query asynchronously and return a FastExecutionResult.
242
+ Execute a SQL query that returns rows (SELECT statements) asynchronously.
243
+
244
+ This method is specifically designed for SELECT queries and other statements
245
+ that return result sets. It uses the optimized query() method internally
246
+ for maximum performance when fetching data.
238
247
 
239
- This method executes SQL queries with optional parameterization for security
240
- and performance. It supports all types of SQL statements including SELECT,
241
- INSERT, UPDATE, DELETE, and stored procedure calls.
248
+ Use this method for:
249
+ - SELECT statements
250
+ - Stored procedures that return result sets
251
+ - SHOW commands
252
+ - Any query that returns tabular data
242
253
 
243
254
  Parameter Binding:
244
255
  Parameters are bound using positional placeholders (@P1, @P2, etc.) in the
@@ -258,7 +269,7 @@ class Connection:
258
269
  - uuid.UUID (uniqueidentifier)
259
270
 
260
271
  Args:
261
- query (str): SQL query to execute. Use @P1, @P2, etc. for parameters.
272
+ query (str): SQL SELECT query to execute. Use @P1, @P2, etc. for parameters.
262
273
  Example: "SELECT * FROM users WHERE age > @P1 AND city = @P2"
263
274
 
264
275
  parameters (list, optional): List of parameter values in order.
@@ -280,56 +291,165 @@ class Connection:
280
291
 
281
292
  Examples:
282
293
  # Simple SELECT query
283
- >>> result = await conn.execute("SELECT * FROM users")
294
+ >>> result = await conn.query("SELECT * FROM users")
284
295
  >>> async for row in result:
285
296
  ... print(f"User ID: {row['id']}, Name: {row['name']}")
286
297
 
287
298
  # Parameterized query
288
- >>> result = await conn.execute(
299
+ >>> result = await conn.query(
289
300
  ... "SELECT * FROM orders WHERE created_date > @P1 AND amount > @P2",
290
301
  ... [datetime(2023, 1, 1), 100.0]
291
302
  ... )
292
303
  >>> rows = await result.fetchall()
293
304
  >>> print(f"Found {len(rows)} orders")
294
305
 
295
- # INSERT with parameters
296
- >>> result = await conn.execute(
297
- ... "INSERT INTO users (name, email, age) VALUES (@P1, @P2, @P3)",
298
- ... ["John Doe", "john@example.com", 30]
306
+ # Complex SELECT with joins
307
+ >>> result = await conn.query(
308
+ ... \"\"\"SELECT u.name, u.email, COUNT(o.id) as order_count
309
+ ... FROM users u
310
+ ... LEFT JOIN orders o ON u.id = o.user_id
311
+ ... WHERE u.created_date > @P1
312
+ ... GROUP BY u.id, u.name, u.email
313
+ ... ORDER BY order_count DESC\"\"\",
314
+ ... [datetime(2023, 1, 1)]
299
315
  ... )
300
- >>> print(f"Inserted {result.rowcount} row(s)")
316
+ >>> async for row in result:
317
+ ... print(f"{row['name']}: {row['order_count']} orders")
301
318
 
302
- # Stored procedure call
303
- >>> result = await conn.execute(
319
+ # Stored procedure that returns data
320
+ >>> result = await conn.query(
304
321
  ... "EXEC GetUsersByDepartment @P1, @P2",
305
322
  ... ["Engineering", True] # department, active_only
306
323
  ... )
307
324
  >>> users = await result.fetchall()
308
-
309
- # Complex query with multiple data types
310
- >>> from decimal import Decimal
311
- >>> from datetime import datetime
312
- >>> import uuid
313
- >>>
314
- >>> result = await conn.execute(
315
- ... \"\"\"UPDATE products
316
- ... SET price = @P1, updated_date = @P2, active = @P3
317
- ... WHERE product_id = @P4\"\"\",
318
- ... [Decimal('29.99'), datetime.now(), True, uuid.uuid4()]
319
- ... )
320
325
 
321
326
  Performance Tips:
322
- - Use parameterized queries instead of string formatting for better performance
327
+ - Use this method instead of execute() for SELECT queries for better performance
323
328
  - For large result sets, iterate asynchronously rather than calling fetchall()
324
329
  - Reuse Connection instances to benefit from connection pooling
325
- - Consider batch operations for bulk data manipulation
330
+ - Use appropriate indexes on filtered columns
331
+ """
332
+ return await self._conn.query(query, parameters)
333
+
334
+ async def execute(self, query, parameters=None):
335
+ """
336
+ Execute a SQL command that doesn't return rows (INSERT/UPDATE/DELETE/DDL) asynchronously.
337
+
338
+ This method is specifically designed for SQL commands that modify data or database
339
+ structure but don't return result sets. It uses the optimized execute() method
340
+ internally for maximum performance when performing data modifications.
341
+
342
+ Use this method for:
343
+ - INSERT statements
344
+ - UPDATE statements
345
+ - DELETE statements
346
+ - DDL commands (CREATE, ALTER, DROP)
347
+ - Stored procedures that don't return result sets
348
+ - MERGE statements
349
+
350
+ Parameter Binding:
351
+ Parameters are bound using positional placeholders (@P1, @P2, etc.) in the
352
+ query string. The parameter values are provided as a list in the same order.
353
+
354
+ Supported Parameter Types:
355
+ - None (NULL)
356
+ - bool
357
+ - int (32-bit and 64-bit)
358
+ - float (32-bit and 64-bit)
359
+ - str (varchar, nvarchar, text)
360
+ - bytes (varbinary, image)
361
+ - datetime.datetime (datetime, datetime2)
362
+ - datetime.date (date)
363
+ - datetime.time (time)
364
+ - decimal.Decimal (decimal, money)
365
+ - uuid.UUID (uniqueidentifier)
366
+
367
+ Args:
368
+ query (str): SQL command to execute. Use @P1, @P2, etc. for parameters.
369
+ Example: "INSERT INTO users (name, email, age) VALUES (@P1, @P2, @P3)"
370
+
371
+ parameters (list, optional): List of parameter values in order.
372
+ Values are automatically converted to appropriate SQL types.
373
+ Example: ["John Doe", "john@example.com", 30]
374
+
375
+ Returns:
376
+ int: Number of rows affected by the command.
377
+ - For INSERT: Number of rows inserted
378
+ - For UPDATE: Number of rows updated
379
+ - For DELETE: Number of rows deleted
380
+ - For DDL: Usually 0 (structure changes don't affect rows)
381
+
382
+ Raises:
383
+ SqlError: If the SQL command contains syntax errors or constraint violations.
384
+ ConnectionError: If the database connection is lost during execution.
385
+ TimeoutError: If the command execution exceeds configured timeouts.
386
+ ParameterError: If parameter types cannot be converted or are invalid.
387
+
388
+ Examples:
389
+ # INSERT with parameters
390
+ >>> affected = await conn.execute(
391
+ ... "INSERT INTO users (name, email, age) VALUES (@P1, @P2, @P3)",
392
+ ... ["John Doe", "john@example.com", 30]
393
+ ... )
394
+ >>> print(f"Inserted {affected} row(s)")
395
+
396
+ # UPDATE with conditions
397
+ >>> affected = await conn.execute(
398
+ ... "UPDATE users SET age = @P1, updated_date = @P2 WHERE id = @P3",
399
+ ... [31, datetime.now(), 123]
400
+ ... )
401
+ >>> print(f"Updated {affected} user(s)")
402
+
403
+ # DELETE with parameters
404
+ >>> affected = await conn.execute(
405
+ ... "DELETE FROM users WHERE age < @P1 AND last_login < @P2",
406
+ ... [18, datetime(2020, 1, 1)]
407
+ ... )
408
+ >>> print(f"Deleted {affected} inactive users")
409
+
410
+ # DDL commands
411
+ >>> affected = await conn.execute(
412
+ ... \"\"\"CREATE TABLE temp_data (
413
+ ... id INT IDENTITY(1,1) PRIMARY KEY,
414
+ ... name NVARCHAR(100) NOT NULL,
415
+ ... created_date DATETIME2 DEFAULT GETDATE()
416
+ ... )\"\"\"
417
+ ... )
418
+ >>> print(f"Table created (affected rows: {affected})")
419
+
420
+ # Stored procedure that modifies data
421
+ >>> affected = await conn.execute(
422
+ ... "EXEC UpdateUserPreferences @P1, @P2",
423
+ ... [user_id, json.dumps(preferences)]
424
+ ... )
425
+ >>> print(f"Updated preferences for {affected} user(s)")
426
+
427
+ # Batch operations
428
+ >>> users_to_insert = [
429
+ ... ["Alice Johnson", "alice@example.com", 28],
430
+ ... ["Bob Smith", "bob@example.com", 32],
431
+ ... ["Carol Davis", "carol@example.com", 25]
432
+ ... ]
433
+ >>> total_affected = 0
434
+ >>> for user_data in users_to_insert:
435
+ ... affected = await conn.execute(
436
+ ... "INSERT INTO users (name, email, age) VALUES (@P1, @P2, @P3)",
437
+ ... user_data
438
+ ... )
439
+ ... total_affected += affected
440
+ >>> print(f"Inserted {total_affected} users total")
441
+
442
+ Performance Tips:
443
+ - Use this method instead of query() for data modification commands
444
+ - For bulk operations, consider using batch processing or table-valued parameters
445
+ - Use transactions for multiple related operations
446
+ - Monitor the returned affected row count for validation
326
447
 
327
448
  Security Notes:
328
449
  - Always use parameterized queries to prevent SQL injection attacks
329
- - Parameter values are automatically escaped and type-checked
330
- - Never concatenate user input directly into SQL query strings
450
+ - Validate affected row counts match expectations
451
+ - Consider using transactions for data consistency
331
452
  """
332
- # The Rust implementation now returns results directly
333
453
  return await self._conn.execute(query, parameters)
334
454
 
335
455
 
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmssql
3
- Version: 0.2.8
3
+ Version: 0.2.9
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: Other/Proprietary License
@@ -46,7 +46,23 @@ A Python library for Microsoft SQL Server built with Rust using the [Tiberius](h
46
46
  - **Type Safety**: Strong typing with automatic Python type conversion
47
47
  - **Thread Safety**: Support for concurrent operations
48
48
  - **Cross-Platform**: Works on Windows, macOS, and Linux
49
- - **Simple API**: Clean, intuitive async-only interface
49
+ - **Simple API**: Clean, intuitive async-only interface with separate `query()` and `execute()` methods
50
+
51
+ ## Key API Methods
52
+
53
+ FastMSSQL provides two distinct methods for database operations:
54
+
55
+ - **`query()`** - For SELECT statements that return rows
56
+ - **`execute()`** - For INSERT/UPDATE/DELETE statements that return affected row count
57
+
58
+ ```python
59
+ # Use query() for SELECT statements
60
+ result = await conn.query("SELECT * FROM users WHERE age > @P1", [25])
61
+ rows = result.rows()
62
+
63
+ # Use execute() for data modification
64
+ affected = await conn.execute("INSERT INTO users (name) VALUES (@P1)", ["John"])
65
+ ```
50
66
 
51
67
  ## Performance Highlights
52
68
 
@@ -125,7 +141,9 @@ async def main():
125
141
 
126
142
  # Automatic connection pool management
127
143
  async with Connection(connection_string) as conn:
128
- rows = await conn.execute("SELECT @@VERSION as version")
144
+ # Use query() for SELECT statements that return rows
145
+ result = await conn.query("SELECT @@VERSION as version")
146
+ rows = result.rows()
129
147
  for row in rows:
130
148
  print(row['version'])
131
149
 
@@ -151,8 +169,10 @@ async def main():
151
169
  connection_string = "Server=localhost;Database=master;User Id=myuser;Password=mypass"
152
170
 
153
171
  async with Connection(connection_string=connection_string) as conn:
154
- result = await conn.execute("SELECT @@VERSION as version")
155
- for row in result.rows():
172
+ # Use query() for SELECT statements that return rows
173
+ result = await conn.query("SELECT @@VERSION as version")
174
+ rows = result.rows()
175
+ for row in rows:
156
176
  print(row['version'])
157
177
 
158
178
  asyncio.run(main())
@@ -174,8 +194,10 @@ async def main():
174
194
  username="myuser",
175
195
  password="mypassword"
176
196
  ) as conn:
177
- result = await conn.execute("SELECT SUSER_NAME() as login")
178
- for row in result.rows():
197
+ # Use query() for SELECT statements that return rows
198
+ result = await conn.query("SELECT SUSER_NAME() as login")
199
+ rows = result.rows()
200
+ for row in rows:
179
201
  print(f"Logged in as: {row['login']}")
180
202
 
181
203
  asyncio.run(main())
@@ -198,8 +220,9 @@ async def high_performance_pattern():
198
220
  # Each worker gets its own Connection object for maximum throughput
199
221
  async with Connection(connection_string, pool_config=config) as conn:
200
222
  for _ in range(1000):
201
- # Use proper SQL Server parameterization with @param syntax
202
- result = await conn.execute("SELECT data FROM my_table WHERE id = @id", {"id": 123})
223
+ # Use query() for SELECT statements that return rows
224
+ result = await conn.query("SELECT data FROM my_table WHERE id = @P1", [123])
225
+ rows = result.rows()
203
226
  # Process results...
204
227
 
205
228
  # Launch multiple workers - each with their own connection
@@ -234,7 +257,11 @@ async def main():
234
257
  )
235
258
 
236
259
  async with Connection(connection_string, pool_config) as conn:
237
- result = await conn.execute("SELECT * FROM users")
260
+ # Use query() for SELECT statements that return rows
261
+ result = await conn.query("SELECT * FROM users")
262
+ rows = result.rows()
263
+ for row in rows:
264
+ print(f"User: {row['name']}")
238
265
 
239
266
  # Predefined configurations for different scenarios
240
267
  high_throughput_config = PoolConfig.high_throughput() # 100 connections, optimized for high RPS
@@ -248,7 +275,8 @@ async def main():
248
275
  # For maximum throughput, use multiple Connection objects:
249
276
  async def high_perf_worker():
250
277
  async with Connection(connection_string, maximum_performance) as conn:
251
- result = await conn.execute("SELECT * FROM fast_table")
278
+ # Use query() for SELECT statements that return rows
279
+ result = await conn.query("SELECT * FROM fast_table")
252
280
  return result.rows()
253
281
 
254
282
  # Each worker gets its own connection for optimal performance
@@ -283,21 +311,37 @@ from fastmssql import Connection
283
311
 
284
312
  async def main():
285
313
  async with Connection(connection_string) as conn:
286
- # Execute queries
287
- users = await conn.execute("SELECT id, name, email FROM users WHERE active = 1")
314
+ # === SELECT QUERIES - Use query() method (returns rows) ===
315
+ result = await conn.query("SELECT id, name, email FROM users WHERE active = 1")
316
+ rows = result.rows()
288
317
 
289
318
  # Iterate through results
290
- for user in users:
291
- print(f"User {user['id']}: {user['name']} ({user['email']})")
319
+ for row in rows:
320
+ print(f"User {row['id']}: {row['name']} ({row['email']})")
321
+
322
+ # === DATA MODIFICATION - Use execute() method (returns affected row count) ===
323
+ # INSERT operation
324
+ rows_affected = await conn.execute(
325
+ "INSERT INTO users (name, email, active) VALUES (@P1, @P2, @P3)",
326
+ ["John Doe", "john@example.com", 1]
327
+ )
328
+ print(f"Inserted {rows_affected} row(s)")
329
+
330
+ # UPDATE operation
331
+ rows_affected = await conn.execute(
332
+ "UPDATE users SET last_login = GETDATE() WHERE id = @P1",
333
+ [123]
334
+ )
335
+ print(f"Updated {rows_affected} row(s)")
292
336
 
293
- # Execute non-query operations
294
- rows_affected = await conn.execute_non_query(
295
- "UPDATE users SET last_login = GETDATE() WHERE id = 123"
337
+ # DELETE operation
338
+ rows_affected = await conn.execute(
339
+ "DELETE FROM users WHERE active = 0 AND last_login < DATEADD(year, -1, GETDATE())"
296
340
  )
297
- print(f"Updated {rows_affected} rows")
341
+ print(f"Deleted {rows_affected} inactive users")
298
342
 
299
- # Work with different data types
300
- data = await conn.execute("""
343
+ # === WORKING WITH DIFFERENT DATA TYPES ===
344
+ result = await conn.query("""
301
345
  SELECT
302
346
  42 as int_value,
303
347
  3.14159 as float_value,
@@ -307,9 +351,11 @@ async def main():
307
351
  NULL as null_value
308
352
  """)
309
353
 
310
- row = data[0]
311
- for column_name, value in row.items():
312
- print(f"{column_name}: {value} (type: {type(value).__name__})")
354
+ rows = result.rows()
355
+ if rows:
356
+ row = rows[0]
357
+ for column_name, value in row.items():
358
+ print(f"{column_name}: {value} (type: {type(value).__name__})")
313
359
 
314
360
  asyncio.run(main())
315
361
  ```
@@ -329,7 +375,9 @@ async def main():
329
375
 
330
376
  # Async context manager with automatic pool management
331
377
  async with Connection(connection_string) as conn:
332
- rows = await conn.execute("SELECT name FROM sys.databases")
378
+ # Use query() for SELECT statements that return rows
379
+ result = await conn.query("SELECT name FROM sys.databases")
380
+ rows = result.rows()
333
381
  for row in rows:
334
382
  print(row['name'])
335
383
 
@@ -340,7 +388,9 @@ async def main():
340
388
  # High-performance concurrent operations
341
389
  async def fetch_user_data(user_id):
342
390
  async with Connection(connection_string) as conn:
343
- return await conn.execute(f"SELECT * FROM users WHERE id = {user_id}")
391
+ # Use query() for SELECT statements that return rows
392
+ result = await conn.query(f"SELECT * FROM users WHERE id = {user_id}")
393
+ return result.rows()
344
394
 
345
395
  # Execute multiple queries concurrently using the connection pool
346
396
  user_ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@@ -407,6 +457,29 @@ python examples/advanced_usage.py
407
457
 
408
458
  ## API Reference
409
459
 
460
+ ### Query vs Execute Methods
461
+
462
+ FastMSSQL provides two distinct methods for database operations:
463
+
464
+ - **`query()`** - For SELECT statements that return rows
465
+ - Returns a `QueryResult` object with a `rows()` method
466
+ - Use for retrieving data from the database
467
+
468
+ - **`execute()`** - For INSERT, UPDATE, DELETE statements
469
+ - Returns the number of affected rows as an integer
470
+ - Use for modifying data in the database
471
+
472
+ **SQL Server Parameter Syntax**: Use positional parameters `@P1`, `@P2`, `@P3`, etc.
473
+
474
+ ```python
475
+ # SELECT queries - use query()
476
+ result = await conn.query("SELECT * FROM users WHERE age > @P1 AND city = @P2", [25, "New York"])
477
+ rows = result.rows()
478
+
479
+ # INSERT/UPDATE/DELETE - use execute()
480
+ affected = await conn.execute("INSERT INTO users (name, email) VALUES (@P1, @P2)", ["John", "john@example.com"])
481
+ ```
482
+
410
483
  ### Core Classes
411
484
 
412
485
  #### `Connection`
@@ -419,21 +492,45 @@ Connection(connection_string: str, pool_config: Optional[PoolConfig] = None)
419
492
 
420
493
  **Context Manager Support:**
421
494
  ```python
422
- # Synchronous
423
- with Connection(conn_str) as conn:
424
- result = conn.execute("SELECT * FROM table")
425
-
426
- # Asynchronous
495
+ # Asynchronous (recommended)
427
496
  async with Connection(conn_str) as conn:
428
- result = await conn.execute_async("SELECT * FROM table")
497
+ # Use query() for SELECT statements
498
+ result = await conn.query("SELECT * FROM table")
499
+ rows = result.rows()
500
+
501
+ # Use execute() for INSERT/UPDATE/DELETE statements
502
+ affected = await conn.execute("INSERT INTO table (col) VALUES (@P1)", ["value"])
503
+ ```
429
504
  ```
430
505
 
431
506
  **Methods:**
432
- - `execute(sql: str) -> List[Row]` - Execute a query synchronously
507
+ - `query(sql: str, params: Optional[List] = None) -> QueryResult` - Execute SELECT queries that return rows
508
+ - `execute(sql: str, params: Optional[List] = None) -> int` - Execute INSERT/UPDATE/DELETE statements, returns affected row count
433
509
  - `pool_stats() -> dict` - Get connection pool statistics
434
510
  - `disconnect()` - Close the connection pool
435
511
  - `is_connected() -> bool` - Check if pool is active
436
512
 
513
+ **Method Details:**
514
+
515
+ `query()` - For SELECT statements that return data:
516
+ ```python
517
+ # Returns a QueryResult object with rows() method
518
+ result = await conn.query("SELECT * FROM users WHERE age > @P1", [21])
519
+ rows = result.rows()
520
+ for row in rows:
521
+ print(row['name'])
522
+ ```
523
+
524
+ `execute()` - For INSERT/UPDATE/DELETE statements:
525
+ ```python
526
+ # Returns the number of affected rows
527
+ affected = await conn.execute("INSERT INTO users (name) VALUES (@P1)", ["John"])
528
+ print(f"Inserted {affected} row(s)")
529
+
530
+ affected = await conn.execute("UPDATE users SET age = @P1 WHERE name = @P2", [25, "John"])
531
+ print(f"Updated {affected} row(s)")
532
+ ```
533
+
437
534
  **Pool Statistics:**
438
535
  ```python
439
536
  stats = conn.pool_stats()
@@ -484,15 +581,17 @@ Represents a database row with column access.
484
581
 
485
582
  #### Connection Management
486
583
  ```python
487
- # Create connection with default pool settings
488
- connect(connection_string: str) -> Connection
489
-
490
- # Create async connection with default pool settings
491
- connect_async(connection_string: str) -> Connection
492
-
493
- # One-liner query execution
494
- execute(connection_string: str, sql: str) -> List[dict]
495
- execute_async(connection_string: str, sql: str) -> List[dict]
584
+ # Create connection with connection pooling
585
+ Connection(connection_string: str, pool_config: Optional[PoolConfig] = None) -> Connection
586
+
587
+ # Usage with async context manager (recommended)
588
+ async with Connection(connection_string) as conn:
589
+ # Use query() for SELECT statements that return rows
590
+ result = await conn.query("SELECT * FROM users")
591
+ rows = result.rows()
592
+
593
+ # Use execute() for INSERT/UPDATE/DELETE statements that return affected count
594
+ affected = await conn.execute("INSERT INTO users (name) VALUES (@P1)", ["John"])
496
595
  ```
497
596
 
498
597
  #### Utility Functions
@@ -515,7 +614,8 @@ The library uses the bb8 connection pool for efficient resource management:
515
614
  ```python
516
615
  try:
517
616
  async with mssql.connect_async(connection_string) as conn:
518
- result = await conn.execute("SELECT * FROM invalid_table")
617
+ result = await conn.query("SELECT * FROM invalid_table")
618
+ rows = result.rows()
519
619
  except Exception as e:
520
620
  print(f"Database error: {e}")
521
621
  # Connection automatically returned to pool even on error
@@ -529,7 +629,8 @@ This library has been upgraded to use async-only operations with the bb8 connect
529
629
  ```python
530
630
  # Async-only with automatic connection pooling
531
631
  async with mssql.connect_async(conn_str) as conn:
532
- result = await conn.execute("SELECT * FROM table")
632
+ result = await conn.query("SELECT * FROM table")
633
+ rows = result.rows()
533
634
 
534
635
  # Pool statistics
535
636
  stats = conn.pool_stats()
@@ -601,7 +702,7 @@ async def oltp_operations():
601
702
  async with mssql.connect_async(conn_str, oltp_config) as conn:
602
703
  # Fast, concurrent transactions
603
704
  tasks = [
604
- conn.execute_async("SELECT * FROM users WHERE id = $1", [user_id])
705
+ conn.query("SELECT * FROM users WHERE id = @P1", [user_id])
605
706
  for user_id in range(1, 101)
606
707
  ]
607
708
  results = await asyncio.gather(*tasks)
@@ -611,7 +712,7 @@ olap_config = PoolConfig.low_resource()
611
712
  async def olap_operations():
612
713
  async with mssql.connect_async(conn_str, olap_config) as conn:
613
714
  # Long-running analytical queries
614
- quarterly_report = await conn.execute_async("""
715
+ result = await conn.query("""
615
716
  SELECT
616
717
  DATE_TRUNC('quarter', order_date) as quarter,
617
718
  SUM(total_amount) as total_revenue,
@@ -621,7 +722,7 @@ async def olap_operations():
621
722
  GROUP BY DATE_TRUNC('quarter', order_date)
622
723
  ORDER BY quarter
623
724
  """)
624
- return quarterly_report
725
+ return result.rows()
625
726
  ```
626
727
 
627
728
  ## API Reference
@@ -0,0 +1,6 @@
1
+ fastmssql/__init__.py,sha256=pFvT4Iki4PdpHWl3APWVeXccWxakueCkU57jbEKcIDA,30407
2
+ fastmssql/fastmssql.cpython-39-darwin.so,sha256=ViAMZHQDCRqIRhJbx9DYfGYLlRY2IsGtoW_dBCIV6rQ,1985984
3
+ fastmssql-0.2.9.dist-info/RECORD,,
4
+ fastmssql-0.2.9.dist-info/WHEEL,sha256=XNDUDUieSorG-Y7wZ8qiKEUDK0umKv3PscUlyjQeFKE,102
5
+ fastmssql-0.2.9.dist-info/METADATA,sha256=pDIeOAYMQ_EiMBU1XSn0i5EUWhukgpXOaHY3nzAli9g,28566
6
+ fastmssql-0.2.9.dist-info/licenses/LICENSE,sha256=NwufX3BNj7RvVtnrshWhkpFOLvWc_YVpGpr3UZGFz_E,4765
@@ -1,6 +0,0 @@
1
- fastmssql/__init__.py,sha256=5D3MpxBm8I33nKOml8wlHJbfH1-9bak68md3xj1Rds0,24923
2
- fastmssql/fastmssql.cpython-39-darwin.so,sha256=ffOLTp3hkeGZgAy6G5mdGJeKyJfpjyt30Q67WuXN88s,2002480
3
- fastmssql-0.2.8.dist-info/RECORD,,
4
- fastmssql-0.2.8.dist-info/WHEEL,sha256=XNDUDUieSorG-Y7wZ8qiKEUDK0umKv3PscUlyjQeFKE,102
5
- fastmssql-0.2.8.dist-info/METADATA,sha256=pbN2t4Cuhy1rzvxweu537UUq6vrP42RZNmoOyg_Y94o,24664
6
- fastmssql-0.2.8.dist-info/licenses/LICENSE,sha256=NwufX3BNj7RvVtnrshWhkpFOLvWc_YVpGpr3UZGFz_E,4765