e6data-python-connector 2.3.10rc5__tar.gz → 2.3.10rc7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. {e6data_python_connector-2.3.10rc5/e6data_python_connector.egg-info → e6data_python_connector-2.3.10rc7}/PKG-INFO +204 -10
  2. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/README.md +195 -2
  3. e6data_python_connector-2.3.10rc7/e6data_python_connector/__init__.py +4 -0
  4. e6data_python_connector-2.3.10rc7/e6data_python_connector/connection_pool.py +495 -0
  5. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/e6data_grpc.py +40 -128
  6. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7/e6data_python_connector.egg-info}/PKG-INFO +204 -10
  7. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector.egg-info/SOURCES.txt +6 -0
  8. e6data_python_connector-2.3.10rc7/e6data_python_connector.egg-info/requires.txt +8 -0
  9. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/setup.py +9 -8
  10. e6data_python_connector-2.3.10rc7/test/test_connection_pool.py +410 -0
  11. e6data_python_connector-2.3.10rc7/test/test_connection_pool_e2e.py +564 -0
  12. e6data_python_connector-2.3.10rc7/test/test_pool_concurrency_simple.py +573 -0
  13. e6data_python_connector-2.3.10rc7/test/test_pool_threading_multiprocessing.py +679 -0
  14. e6data_python_connector-2.3.10rc7/test/test_simple_connection_pool.py +278 -0
  15. e6data_python_connector-2.3.10rc5/e6data_python_connector/__init__.py +0 -3
  16. e6data_python_connector-2.3.10rc5/e6data_python_connector.egg-info/requires.txt +0 -8
  17. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/LICENSE +0 -0
  18. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/MANIFEST.in +0 -0
  19. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/cluster_manager.py +0 -0
  20. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/cluster_server/__init__.py +0 -0
  21. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/cluster_server/cluster_pb2.py +0 -0
  22. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/cluster_server/cluster_pb2_grpc.py +0 -0
  23. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/common.py +0 -0
  24. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/constants.py +0 -0
  25. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/datainputstream.py +0 -0
  26. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/date_time_utils.py +0 -0
  27. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/dialect.py +0 -0
  28. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/e6x_vector/__init__.py +0 -0
  29. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/e6x_vector/constants.py +0 -0
  30. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/e6x_vector/ttypes.py +0 -0
  31. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/exceptions.py +0 -0
  32. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/server/QueryEngineService.py +0 -0
  33. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/server/__init__.py +0 -0
  34. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/server/constants.py +0 -0
  35. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/server/e6x_engine_pb2.py +0 -0
  36. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/server/e6x_engine_pb2.pyi +0 -0
  37. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/server/e6x_engine_pb2_grpc.py +0 -0
  38. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/server/ttypes.py +0 -0
  39. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/strategy.py +0 -0
  40. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector/typeId.py +0 -0
  41. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector.egg-info/dependency_links.txt +0 -0
  42. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector.egg-info/entry_points.txt +0 -0
  43. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/e6data_python_connector.egg-info/top_level.txt +0 -0
  44. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/pyproject.toml +0 -0
  45. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/setup.cfg +0 -0
  46. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/__init__.py +0 -0
  47. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/analyze_38_nines.py +0 -0
  48. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/analyze_all_cases.py +0 -0
  49. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/analyze_binary.py +0 -0
  50. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/analyze_correct_value.py +0 -0
  51. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/analyze_fields.py +0 -0
  52. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/check_decimal_errors.py +0 -0
  53. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/cleanup_test_files.py +0 -0
  54. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/debug_38_nines.py +0 -0
  55. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/debug_binary.py +0 -0
  56. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/final_test.py +0 -0
  57. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/move_tests.py +0 -0
  58. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/quick_test.py +0 -0
  59. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_38_nines.py +0 -0
  60. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_all_decimal128_cases.py +0 -0
  61. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_cluster_manager_efficiency.py +0 -0
  62. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_cluster_manager_none_strategy.py +0 -0
  63. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_cluster_manager_strategy.py +0 -0
  64. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_comprehensive.py +0 -0
  65. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_current_implementation.py +0 -0
  66. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_decimal128_binary_parsing.py +0 -0
  67. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_decimal128_parsing.py +0 -0
  68. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_fix.py +0 -0
  69. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_improved_parsing.py +0 -0
  70. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_known_case.py +0 -0
  71. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_manual_analysis.py +0 -0
  72. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_mock_server.py +0 -0
  73. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_multiprocessing_fix.py +0 -0
  74. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_new_implementation.py +0 -0
  75. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_specific_binary.py +0 -0
  76. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_strategy.py +0 -0
  77. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_strategy_logic.py +0 -0
  78. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_strategy_persistence_fix.py +0 -0
  79. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_strategy_sharing_fix.py +0 -0
  80. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/test_user_binary_value.py +0 -0
  81. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/tests.py +0 -0
  82. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/tests_grpc.py +0 -0
  83. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/validate_decimal128.py +0 -0
  84. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/validate_implementation.py +0 -0
  85. {e6data_python_connector-2.3.10rc5 → e6data_python_connector-2.3.10rc7}/test/verify_decimal_fix.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: e6data-python-connector
3
- Version: 2.3.10rc5
3
+ Version: 2.3.10rc7
4
4
  Summary: Client for the e6data distributed SQL Engine.
5
5
  Home-page: https://github.com/e6x-labs/e6data-python-connector
6
6
  Author: e6data, Inc.
@@ -16,16 +16,17 @@ Classifier: Programming Language :: Python :: 3.9
16
16
  Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
18
  Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
19
20
  Description-Content-Type: text/markdown
20
21
  License-File: LICENSE
21
22
  Requires-Dist: sqlalchemy>=1.0.0
22
- Requires-Dist: future==1.0.0
23
- Requires-Dist: python-dateutil==2.9.0.post0
24
- Requires-Dist: pycryptodome==3.19.1
25
- Requires-Dist: pytz==2024.1
26
- Requires-Dist: thrift==0.20.0
27
- Requires-Dist: grpcio==1.65.1
28
- Requires-Dist: grpcio-tools
23
+ Requires-Dist: future>=1.0.0
24
+ Requires-Dist: python-dateutil>=2.9.0
25
+ Requires-Dist: pycryptodome>=3.19.1
26
+ Requires-Dist: pytz>=2024.1
27
+ Requires-Dist: thrift>=0.20.0
28
+ Requires-Dist: grpcio>=1.65.1
29
+ Requires-Dist: grpcio-tools>=1.65.1
29
30
  Dynamic: author
30
31
  Dynamic: author-email
31
32
  Dynamic: classifier
@@ -38,7 +39,7 @@ Dynamic: summary
38
39
 
39
40
  # e6data Python Connector
40
41
 
41
- ![version](https://img.shields.io/badge/version-2.3.10,rc5-blue.svg)
42
+ ![version](https://img.shields.io/badge/version-2.3.10rc7-blue.svg)
42
43
 
43
44
  ## Introduction
44
45
 
@@ -75,6 +76,8 @@ Use your e6data Email ID as the username and your access token as the password.
75
76
 
76
77
  ```python
77
78
  from e6data_python_connector import Connection
79
+ # For connection pooling (recommended for concurrent operations)
80
+ from e6data_python_connector import ConnectionPool
78
81
 
79
82
  username = '<username>' # Your e6data Email ID.
80
83
  password = '<password>' # Access Token generated in the e6data console.
@@ -84,6 +87,7 @@ database = '<database>' # Database to perform the query on.
84
87
  port = 80 # Port of the e6data engine.
85
88
  catalog_name = '<catalog_name>'
86
89
 
90
+ # Single connection (for simple, single-threaded use)
87
91
  conn = Connection(
88
92
  host=host,
89
93
  port=port,
@@ -91,6 +95,17 @@ conn = Connection(
91
95
  database=database,
92
96
  password=password
93
97
  )
98
+
99
+ # Or use connection pool (for concurrent/multi-threaded use)
100
+ pool = ConnectionPool(
101
+ min_size=2,
102
+ max_size=10,
103
+ host=host,
104
+ port=port,
105
+ username=username,
106
+ database=database,
107
+ password=password
108
+ )
94
109
  ```
95
110
 
96
111
  #### Connection Parameters
@@ -439,8 +454,187 @@ For detailed migration instructions, see the [Migration Guide](docs/zero-downtim
439
454
  - Message size optimization for large queries
440
455
 
441
456
  ### Connection Management
442
- - Enable connection pooling for better resource utilization
457
+
458
+ #### Connection Pooling
459
+
460
+ The e6data Python connector now includes a built-in connection pool for efficient connection management and reuse across multiple threads. The `ConnectionPool` class provides:
461
+
462
+ - **Thread-safe connection reuse**: Each thread automatically reuses its assigned connection
463
+ - **Automatic lifecycle management**: Handles connection creation, health checks, and cleanup
464
+ - **Overflow connections**: Creates temporary connections when pool is exhausted
465
+ - **Connection health monitoring**: Automatic detection and replacement of broken connections
466
+ - **Statistics tracking**: Monitor pool usage and performance
467
+
468
+ ##### Basic Connection Pool Usage
469
+
470
+ ```python
471
+ from e6data_python_connector import ConnectionPool
472
+
473
+ # Create a connection pool
474
+ pool = ConnectionPool(
475
+ min_size=2, # Minimum connections to maintain
476
+ max_size=10, # Maximum connections in pool
477
+ max_overflow=5, # Additional temporary connections allowed
478
+ timeout=30.0, # Timeout for getting connection (seconds)
479
+ recycle=3600, # Maximum age before recycling (seconds)
480
+ debug=False, # Enable debug logging
481
+ pre_ping=True, # Check connection health before use
482
+ # Connection parameters
483
+ host=host,
484
+ port=port,
485
+ username=username,
486
+ password=password,
487
+ database=database,
488
+ catalog=catalog_name,
489
+ cluster_name=cluster_name,
490
+ secure=True
491
+ )
492
+
493
+ # Get connection and execute query
494
+ conn = pool.get_connection()
495
+ cursor = conn.cursor()
496
+ cursor.execute("SELECT * FROM table")
497
+ results = cursor.fetchall()
498
+
499
+ # Return connection to pool (important!)
500
+ pool.return_connection(conn)
501
+
502
+ # Clean up when done
503
+ pool.close_all()
504
+ ```
505
+
506
+ ##### Using Context Manager (Recommended)
507
+
508
+ The context manager pattern ensures connections are automatically returned to the pool:
509
+
510
+ ```python
511
+ from e6data_python_connector import ConnectionPool
512
+
513
+ pool = ConnectionPool(
514
+ min_size=2,
515
+ max_size=10,
516
+ host=host,
517
+ port=port,
518
+ username=username,
519
+ password=password,
520
+ database=database
521
+ )
522
+
523
+ # Connection automatically returned to pool after use
524
+ with pool.get_connection_context() as conn:
525
+ cursor = conn.cursor()
526
+ cursor.execute("SELECT * FROM table")
527
+ results = cursor.fetchall()
528
+ print(results)
529
+ ```
530
+
531
+ ##### Concurrent Query Execution
532
+
533
+ Connection pooling is especially beneficial for concurrent query execution:
534
+
535
+ ```python
536
+ import concurrent.futures
537
+ from e6data_python_connector import ConnectionPool
538
+
539
+ def execute_query(pool, query_id, query):
540
+ """Execute a query using a pooled connection."""
541
+ # Each thread will reuse its assigned connection
542
+ conn = pool.get_connection()
543
+ try:
544
+ cursor = conn.cursor()
545
+ cursor.execute(query)
546
+ results = cursor.fetchall()
547
+ return f"Query {query_id}: {len(results)} rows"
548
+ finally:
549
+ pool.return_connection(conn)
550
+
551
+ # Create pool
552
+ pool = ConnectionPool(
553
+ min_size=3,
554
+ max_size=10,
555
+ host=host,
556
+ port=port,
557
+ username=username,
558
+ password=password,
559
+ database=database
560
+ )
561
+
562
+ # Execute multiple queries concurrently
563
+ queries = [
564
+ "SELECT COUNT(*) FROM table1",
565
+ "SELECT AVG(value) FROM table2",
566
+ "SELECT MAX(date) FROM table3"
567
+ ]
568
+
569
+ with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
570
+ futures = [
571
+ executor.submit(execute_query, pool, i, query)
572
+ for i, query in enumerate(queries)
573
+ ]
574
+
575
+ for future in concurrent.futures.as_completed(futures):
576
+ print(future.result())
577
+
578
+ # Clean up
579
+ pool.close_all()
580
+ ```
581
+
582
+ ##### Connection Pool Configuration
583
+
584
+ | Parameter | Type | Default | Description |
585
+ |-----------|------|---------|-------------|
586
+ | `min_size` | int | 2 | Minimum number of connections to maintain |
587
+ | `max_size` | int | 10 | Maximum number of connections in pool |
588
+ | `max_overflow` | int | 5 | Additional temporary connections allowed |
589
+ | `timeout` | float | 30.0 | Timeout for getting connection (seconds) |
590
+ | `recycle` | int | 3600 | Maximum connection age before recycling (seconds) |
591
+ | `debug` | bool | False | Enable debug logging for pool operations |
592
+ | `pre_ping` | bool | True | Check connection health before returning from pool |
593
+
594
+ ##### Monitoring Pool Statistics
595
+
596
+ ```python
597
+ # Get pool statistics
598
+ stats = pool.get_statistics()
599
+ print(f"Active connections: {stats['active_connections']}")
600
+ print(f"Idle connections: {stats['idle_connections']}")
601
+ print(f"Total requests: {stats['total_requests']}")
602
+ print(f"Failed connections: {stats['failed_connections']}")
603
+ ```
604
+
605
+ ##### When to Use Connection Pooling
606
+
607
+ Connection pooling is recommended when:
608
+ - Executing multiple queries concurrently
609
+ - Building web applications or APIs
610
+ - Running batch processing jobs
611
+ - Reducing connection overhead
612
+ - Improving application performance
613
+
614
+ ##### Direct Connection Usage (Without Pool)
615
+
616
+ For simple, single-threaded applications, you can still use direct connections:
617
+
618
+ ```python
619
+ from e6data_python_connector import Connection
620
+
621
+ conn = Connection(
622
+ host=host,
623
+ port=port,
624
+ username=username,
625
+ password=password,
626
+ database=database
627
+ )
628
+
629
+ cursor = conn.cursor()
630
+ cursor.execute("SELECT * FROM table")
631
+ results = cursor.fetchall()
632
+ conn.close()
633
+ ```
634
+
635
+ #### Additional Connection Management Features
443
636
  - Automatic connection health monitoring
444
637
  - Graceful connection recovery and retry logic
638
+ - Blue-green deployment support with automatic failover
445
639
 
446
640
  See [TECH_DOC.md](TECH_DOC.md) for detailed technical documentation.
@@ -1,6 +1,6 @@
1
1
  # e6data Python Connector
2
2
 
3
- ![version](https://img.shields.io/badge/version-2.3.10,rc5-blue.svg)
3
+ ![version](https://img.shields.io/badge/version-2.3.10rc7-blue.svg)
4
4
 
5
5
  ## Introduction
6
6
 
@@ -37,6 +37,8 @@ Use your e6data Email ID as the username and your access token as the password.
37
37
 
38
38
  ```python
39
39
  from e6data_python_connector import Connection
40
+ # For connection pooling (recommended for concurrent operations)
41
+ from e6data_python_connector import ConnectionPool
40
42
 
41
43
  username = '<username>' # Your e6data Email ID.
42
44
  password = '<password>' # Access Token generated in the e6data console.
@@ -46,6 +48,7 @@ database = '<database>' # Database to perform the query on.
46
48
  port = 80 # Port of the e6data engine.
47
49
  catalog_name = '<catalog_name>'
48
50
 
51
+ # Single connection (for simple, single-threaded use)
49
52
  conn = Connection(
50
53
  host=host,
51
54
  port=port,
@@ -53,6 +56,17 @@ conn = Connection(
53
56
  database=database,
54
57
  password=password
55
58
  )
59
+
60
+ # Or use connection pool (for concurrent/multi-threaded use)
61
+ pool = ConnectionPool(
62
+ min_size=2,
63
+ max_size=10,
64
+ host=host,
65
+ port=port,
66
+ username=username,
67
+ database=database,
68
+ password=password
69
+ )
56
70
  ```
57
71
 
58
72
  #### Connection Parameters
@@ -401,8 +415,187 @@ For detailed migration instructions, see the [Migration Guide](docs/zero-downtim
401
415
  - Message size optimization for large queries
402
416
 
403
417
  ### Connection Management
404
- - Enable connection pooling for better resource utilization
418
+
419
+ #### Connection Pooling
420
+
421
+ The e6data Python connector now includes a built-in connection pool for efficient connection management and reuse across multiple threads. The `ConnectionPool` class provides:
422
+
423
+ - **Thread-safe connection reuse**: Each thread automatically reuses its assigned connection
424
+ - **Automatic lifecycle management**: Handles connection creation, health checks, and cleanup
425
+ - **Overflow connections**: Creates temporary connections when pool is exhausted
426
+ - **Connection health monitoring**: Automatic detection and replacement of broken connections
427
+ - **Statistics tracking**: Monitor pool usage and performance
428
+
429
+ ##### Basic Connection Pool Usage
430
+
431
+ ```python
432
+ from e6data_python_connector import ConnectionPool
433
+
434
+ # Create a connection pool
435
+ pool = ConnectionPool(
436
+ min_size=2, # Minimum connections to maintain
437
+ max_size=10, # Maximum connections in pool
438
+ max_overflow=5, # Additional temporary connections allowed
439
+ timeout=30.0, # Timeout for getting connection (seconds)
440
+ recycle=3600, # Maximum age before recycling (seconds)
441
+ debug=False, # Enable debug logging
442
+ pre_ping=True, # Check connection health before use
443
+ # Connection parameters
444
+ host=host,
445
+ port=port,
446
+ username=username,
447
+ password=password,
448
+ database=database,
449
+ catalog=catalog_name,
450
+ cluster_name=cluster_name,
451
+ secure=True
452
+ )
453
+
454
+ # Get connection and execute query
455
+ conn = pool.get_connection()
456
+ cursor = conn.cursor()
457
+ cursor.execute("SELECT * FROM table")
458
+ results = cursor.fetchall()
459
+
460
+ # Return connection to pool (important!)
461
+ pool.return_connection(conn)
462
+
463
+ # Clean up when done
464
+ pool.close_all()
465
+ ```
466
+
467
+ ##### Using Context Manager (Recommended)
468
+
469
+ The context manager pattern ensures connections are automatically returned to the pool:
470
+
471
+ ```python
472
+ from e6data_python_connector import ConnectionPool
473
+
474
+ pool = ConnectionPool(
475
+ min_size=2,
476
+ max_size=10,
477
+ host=host,
478
+ port=port,
479
+ username=username,
480
+ password=password,
481
+ database=database
482
+ )
483
+
484
+ # Connection automatically returned to pool after use
485
+ with pool.get_connection_context() as conn:
486
+ cursor = conn.cursor()
487
+ cursor.execute("SELECT * FROM table")
488
+ results = cursor.fetchall()
489
+ print(results)
490
+ ```
491
+
492
+ ##### Concurrent Query Execution
493
+
494
+ Connection pooling is especially beneficial for concurrent query execution:
495
+
496
+ ```python
497
+ import concurrent.futures
498
+ from e6data_python_connector import ConnectionPool
499
+
500
+ def execute_query(pool, query_id, query):
501
+ """Execute a query using a pooled connection."""
502
+ # Each thread will reuse its assigned connection
503
+ conn = pool.get_connection()
504
+ try:
505
+ cursor = conn.cursor()
506
+ cursor.execute(query)
507
+ results = cursor.fetchall()
508
+ return f"Query {query_id}: {len(results)} rows"
509
+ finally:
510
+ pool.return_connection(conn)
511
+
512
+ # Create pool
513
+ pool = ConnectionPool(
514
+ min_size=3,
515
+ max_size=10,
516
+ host=host,
517
+ port=port,
518
+ username=username,
519
+ password=password,
520
+ database=database
521
+ )
522
+
523
+ # Execute multiple queries concurrently
524
+ queries = [
525
+ "SELECT COUNT(*) FROM table1",
526
+ "SELECT AVG(value) FROM table2",
527
+ "SELECT MAX(date) FROM table3"
528
+ ]
529
+
530
+ with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
531
+ futures = [
532
+ executor.submit(execute_query, pool, i, query)
533
+ for i, query in enumerate(queries)
534
+ ]
535
+
536
+ for future in concurrent.futures.as_completed(futures):
537
+ print(future.result())
538
+
539
+ # Clean up
540
+ pool.close_all()
541
+ ```
542
+
543
+ ##### Connection Pool Configuration
544
+
545
+ | Parameter | Type | Default | Description |
546
+ |-----------|------|---------|-------------|
547
+ | `min_size` | int | 2 | Minimum number of connections to maintain |
548
+ | `max_size` | int | 10 | Maximum number of connections in pool |
549
+ | `max_overflow` | int | 5 | Additional temporary connections allowed |
550
+ | `timeout` | float | 30.0 | Timeout for getting connection (seconds) |
551
+ | `recycle` | int | 3600 | Maximum connection age before recycling (seconds) |
552
+ | `debug` | bool | False | Enable debug logging for pool operations |
553
+ | `pre_ping` | bool | True | Check connection health before returning from pool |
554
+
555
+ ##### Monitoring Pool Statistics
556
+
557
+ ```python
558
+ # Get pool statistics
559
+ stats = pool.get_statistics()
560
+ print(f"Active connections: {stats['active_connections']}")
561
+ print(f"Idle connections: {stats['idle_connections']}")
562
+ print(f"Total requests: {stats['total_requests']}")
563
+ print(f"Failed connections: {stats['failed_connections']}")
564
+ ```
565
+
566
+ ##### When to Use Connection Pooling
567
+
568
+ Connection pooling is recommended when:
569
+ - Executing multiple queries concurrently
570
+ - Building web applications or APIs
571
+ - Running batch processing jobs
572
+ - Reducing connection overhead
573
+ - Improving application performance
574
+
575
+ ##### Direct Connection Usage (Without Pool)
576
+
577
+ For simple, single-threaded applications, you can still use direct connections:
578
+
579
+ ```python
580
+ from e6data_python_connector import Connection
581
+
582
+ conn = Connection(
583
+ host=host,
584
+ port=port,
585
+ username=username,
586
+ password=password,
587
+ database=database
588
+ )
589
+
590
+ cursor = conn.cursor()
591
+ cursor.execute("SELECT * FROM table")
592
+ results = cursor.fetchall()
593
+ conn.close()
594
+ ```
595
+
596
+ #### Additional Connection Management Features
405
597
  - Automatic connection health monitoring
406
598
  - Graceful connection recovery and retry logic
599
+ - Blue-green deployment support with automatic failover
407
600
 
408
601
  See [TECH_DOC.md](TECH_DOC.md) for detailed technical documentation.
@@ -0,0 +1,4 @@
1
+ from e6data_python_connector.e6data_grpc import Connection, Cursor
2
+ from e6data_python_connector.connection_pool import ConnectionPool
3
+
4
+ __all__ = ['Connection', 'Cursor', 'ConnectionPool']