e6data-python-connector 2.3.11rc2__tar.gz → 2.3.12rc2__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.
- {e6data_python_connector-2.3.11rc2/e6data_python_connector.egg-info → e6data_python_connector-2.3.12rc2}/PKG-INFO +57 -2
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/README.md +56 -1
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/datainputstream.py +31 -19
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/e6data_grpc.py +63 -6
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2/e6data_python_connector.egg-info}/PKG-INFO +57 -2
- {e6data_python_connector-2.3.11rc2/e6data_python_connector → e6data_python_connector-2.3.12rc2/gen-py}/e6x_vector/ttypes.py +26 -2
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/setup.py +1 -1
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/LICENSE +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/MANIFEST.in +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/__init__.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/cluster_manager.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/cluster_server/__init__.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/cluster_server/cluster_pb2.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/cluster_server/cluster_pb2_grpc.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/common.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/connection_pool.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/constants.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/date_time_utils.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/dialect.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/e6x_vector/__init__.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/e6x_vector/constants.py +0 -0
- {e6data_python_connector-2.3.11rc2/gen-py → e6data_python_connector-2.3.12rc2/e6data_python_connector}/e6x_vector/ttypes.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/exceptions.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/server/QueryEngineService.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/server/__init__.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/server/constants.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/server/e6x_engine_pb2.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/server/e6x_engine_pb2.pyi +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/server/e6x_engine_pb2_grpc.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/server/ttypes.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/strategy.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector/typeId.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector.egg-info/SOURCES.txt +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector.egg-info/dependency_links.txt +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector.egg-info/entry_points.txt +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector.egg-info/requires.txt +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/e6data_python_connector.egg-info/top_level.txt +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/gen-py/__init__.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/gen-py/e6x_vector/__init__.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/gen-py/e6x_vector/constants.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/pyproject.toml +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/setup.cfg +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/__init__.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/analyze_38_nines.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/analyze_all_cases.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/analyze_binary.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/analyze_correct_value.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/analyze_fields.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/check_decimal_errors.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/cleanup_test_files.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/debug_38_nines.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/debug_binary.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/final_test.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/move_tests.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/quick_test.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_38_nines.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_all_decimal128_cases.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_cluster_manager_efficiency.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_cluster_manager_none_strategy.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_cluster_manager_strategy.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_comprehensive.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_connection_pool.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_connection_pool_e2e.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_current_implementation.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_decimal128_binary_parsing.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_decimal128_parsing.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_fix.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_improved_parsing.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_known_case.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_manual_analysis.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_mock_server.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_multiprocessing_fix.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_new_implementation.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_pool_concurrency_simple.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_pool_threading_multiprocessing.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_simple_connection_pool.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_specific_binary.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_strategy.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_strategy_logic.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_strategy_persistence_fix.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_strategy_sharing_fix.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_user_binary_value.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/tests.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/tests_grpc.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/validate_decimal128.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/validate_implementation.py +0 -0
- {e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/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.
|
|
3
|
+
Version: 2.3.12rc2
|
|
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.
|
|
@@ -39,7 +39,7 @@ Dynamic: summary
|
|
|
39
39
|
|
|
40
40
|
# e6data Python Connector
|
|
41
41
|
|
|
42
|
-

|
|
43
43
|
|
|
44
44
|
## Introduction
|
|
45
45
|
|
|
@@ -124,6 +124,7 @@ The `Connection` class supports the following parameters:
|
|
|
124
124
|
| `secure` | bool | No | False | Enable SSL/TLS for secure connections |
|
|
125
125
|
| `auto_resume` | bool | No | True | Automatically resume cluster if suspended |
|
|
126
126
|
| `grpc_options` | dict | No | None | Additional gRPC configuration options |
|
|
127
|
+
| `debug` | bool | No | False | Enable debug logging for troubleshooting |
|
|
127
128
|
|
|
128
129
|
#### Secure Connection Example
|
|
129
130
|
|
|
@@ -637,4 +638,58 @@ conn.close()
|
|
|
637
638
|
- Graceful connection recovery and retry logic
|
|
638
639
|
- Blue-green deployment support with automatic failover
|
|
639
640
|
|
|
641
|
+
## Debugging and Troubleshooting
|
|
642
|
+
|
|
643
|
+
### Enable Debug Mode
|
|
644
|
+
|
|
645
|
+
Enable comprehensive debugging to troubleshoot connection and query issues:
|
|
646
|
+
|
|
647
|
+
```python
|
|
648
|
+
from e6data_python_connector import Connection
|
|
649
|
+
|
|
650
|
+
conn = Connection(
|
|
651
|
+
host=host,
|
|
652
|
+
port=port,
|
|
653
|
+
username=username,
|
|
654
|
+
password=password,
|
|
655
|
+
database=database,
|
|
656
|
+
debug=True # Enable debug logging
|
|
657
|
+
)
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
When `debug=True`, the following features are enabled:
|
|
661
|
+
- Python logging at DEBUG level for all operations
|
|
662
|
+
- Blue-green strategy transition logging
|
|
663
|
+
- Connection lifecycle logging
|
|
664
|
+
- Query execution detailed logging
|
|
665
|
+
|
|
666
|
+
### gRPC Network Tracing
|
|
667
|
+
|
|
668
|
+
For low-level gRPC network debugging (HTTP/2 frames, TCP events), set environment variables **before** running your Python script:
|
|
669
|
+
|
|
670
|
+
```bash
|
|
671
|
+
# Enable gRPC network tracing
|
|
672
|
+
export GRPC_VERBOSITY=DEBUG
|
|
673
|
+
export GRPC_TRACE=client_channel,http2
|
|
674
|
+
|
|
675
|
+
# For comprehensive tracing
|
|
676
|
+
export GRPC_TRACE=api,call_error,channel,client_channel,connectivity_state,http,http2_stream,tcp,transport_security
|
|
677
|
+
|
|
678
|
+
# Run your script
|
|
679
|
+
python your_script.py
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
**Note**: These environment variables must be set before Python starts, as the gRPC C++ core reads them at module import time.
|
|
683
|
+
|
|
684
|
+
### Common Issues and Solutions
|
|
685
|
+
|
|
686
|
+
| Issue | Solution |
|
|
687
|
+
|-------|----------|
|
|
688
|
+
| Connection timeout | Check network connectivity, firewall rules, and ensure port 80/443 is open |
|
|
689
|
+
| Authentication failure | Verify username (email) and access token are correct |
|
|
690
|
+
| 503 Service Unavailable | Cluster may be suspended; enable `auto_resume=True` |
|
|
691
|
+
| 456 Strategy Error | Automatic blue-green failover will handle this |
|
|
692
|
+
| Memory issues with large results | Use `fetchall_buffer()` instead of `fetchall()` |
|
|
693
|
+
| gRPC message size errors | Configure `grpc_options` with appropriate message size limits |
|
|
694
|
+
|
|
640
695
|
See [TECH_DOC.md](TECH_DOC.md) for detailed technical documentation.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# e6data Python Connector
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|
|
|
5
5
|
## Introduction
|
|
6
6
|
|
|
@@ -85,6 +85,7 @@ The `Connection` class supports the following parameters:
|
|
|
85
85
|
| `secure` | bool | No | False | Enable SSL/TLS for secure connections |
|
|
86
86
|
| `auto_resume` | bool | No | True | Automatically resume cluster if suspended |
|
|
87
87
|
| `grpc_options` | dict | No | None | Additional gRPC configuration options |
|
|
88
|
+
| `debug` | bool | No | False | Enable debug logging for troubleshooting |
|
|
88
89
|
|
|
89
90
|
#### Secure Connection Example
|
|
90
91
|
|
|
@@ -598,4 +599,58 @@ conn.close()
|
|
|
598
599
|
- Graceful connection recovery and retry logic
|
|
599
600
|
- Blue-green deployment support with automatic failover
|
|
600
601
|
|
|
602
|
+
## Debugging and Troubleshooting
|
|
603
|
+
|
|
604
|
+
### Enable Debug Mode
|
|
605
|
+
|
|
606
|
+
Enable comprehensive debugging to troubleshoot connection and query issues:
|
|
607
|
+
|
|
608
|
+
```python
|
|
609
|
+
from e6data_python_connector import Connection
|
|
610
|
+
|
|
611
|
+
conn = Connection(
|
|
612
|
+
host=host,
|
|
613
|
+
port=port,
|
|
614
|
+
username=username,
|
|
615
|
+
password=password,
|
|
616
|
+
database=database,
|
|
617
|
+
debug=True # Enable debug logging
|
|
618
|
+
)
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
When `debug=True`, the following features are enabled:
|
|
622
|
+
- Python logging at DEBUG level for all operations
|
|
623
|
+
- Blue-green strategy transition logging
|
|
624
|
+
- Connection lifecycle logging
|
|
625
|
+
- Query execution detailed logging
|
|
626
|
+
|
|
627
|
+
### gRPC Network Tracing
|
|
628
|
+
|
|
629
|
+
For low-level gRPC network debugging (HTTP/2 frames, TCP events), set environment variables **before** running your Python script:
|
|
630
|
+
|
|
631
|
+
```bash
|
|
632
|
+
# Enable gRPC network tracing
|
|
633
|
+
export GRPC_VERBOSITY=DEBUG
|
|
634
|
+
export GRPC_TRACE=client_channel,http2
|
|
635
|
+
|
|
636
|
+
# For comprehensive tracing
|
|
637
|
+
export GRPC_TRACE=api,call_error,channel,client_channel,connectivity_state,http,http2_stream,tcp,transport_security
|
|
638
|
+
|
|
639
|
+
# Run your script
|
|
640
|
+
python your_script.py
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
**Note**: These environment variables must be set before Python starts, as the gRPC C++ core reads them at module import time.
|
|
644
|
+
|
|
645
|
+
### Common Issues and Solutions
|
|
646
|
+
|
|
647
|
+
| Issue | Solution |
|
|
648
|
+
|-------|----------|
|
|
649
|
+
| Connection timeout | Check network connectivity, firewall rules, and ensure port 80/443 is open |
|
|
650
|
+
| Authentication failure | Verify username (email) and access token are correct |
|
|
651
|
+
| 503 Service Unavailable | Cluster may be suspended; enable `auto_resume=True` |
|
|
652
|
+
| 456 Strategy Error | Automatic blue-green failover will handle this |
|
|
653
|
+
| Memory issues with large results | Use `fetchall_buffer()` instead of `fetchall()` |
|
|
654
|
+
| gRPC message size errors | Configure `grpc_options` with appropriate message size limits |
|
|
655
|
+
|
|
601
656
|
See [TECH_DOC.md](TECH_DOC.md) for detailed technical documentation.
|
|
@@ -26,16 +26,18 @@ except ImportError:
|
|
|
26
26
|
_logger = logging.getLogger(__name__)
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
def _binary_to_decimal128(binary_data):
|
|
29
|
+
def _binary_to_decimal128(binary_data, scale=None):
|
|
30
30
|
"""
|
|
31
31
|
Convert binary data to Decimal128.
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
The binary data represents a 128-bit decimal number in IEEE 754-2008 Decimal128 format.
|
|
34
34
|
Based on the Java implementation from e6data's JDBC driver.
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
Args:
|
|
37
37
|
binary_data (bytes): Binary representation of Decimal128
|
|
38
|
-
|
|
38
|
+
scale (int, optional): Scale parameter for decimal precision. If None,
|
|
39
|
+
attempts to decode from IEEE format or defaults to 0.
|
|
40
|
+
|
|
39
41
|
Returns:
|
|
40
42
|
Decimal: Python Decimal object
|
|
41
43
|
"""
|
|
@@ -59,7 +61,7 @@ def _binary_to_decimal128(binary_data):
|
|
|
59
61
|
|
|
60
62
|
# Handle IEEE 754-2008 Decimal128 binary format
|
|
61
63
|
if len(binary_data) == 16: # Decimal128 should be exactly 16 bytes
|
|
62
|
-
return _decode_decimal128_binary_java_style(binary_data)
|
|
64
|
+
return _decode_decimal128_binary_java_style(binary_data, scale)
|
|
63
65
|
else:
|
|
64
66
|
_logger.warning(f"Invalid Decimal128 binary length: {len(binary_data)} bytes, expected 16")
|
|
65
67
|
return Decimal('0')
|
|
@@ -73,16 +75,17 @@ def _binary_to_decimal128(binary_data):
|
|
|
73
75
|
return Decimal('0')
|
|
74
76
|
|
|
75
77
|
|
|
76
|
-
def _decode_decimal128_binary_java_style(binary_data):
|
|
78
|
+
def _decode_decimal128_binary_java_style(binary_data, scale=None):
|
|
77
79
|
"""
|
|
78
80
|
Decode IEEE 754-2008 Decimal128 binary format following Java implementation.
|
|
79
|
-
|
|
81
|
+
|
|
80
82
|
Based on the Java implementation from e6data's JDBC driver getFieldDataFromChunk method.
|
|
81
83
|
This method follows the same logic as the Java BigDecimal creation from ByteBuffer.
|
|
82
|
-
|
|
84
|
+
|
|
83
85
|
Args:
|
|
84
86
|
binary_data (bytes): 16-byte binary representation
|
|
85
|
-
|
|
87
|
+
scale (int, optional): Scale parameter for decimal precision
|
|
88
|
+
|
|
86
89
|
Returns:
|
|
87
90
|
Decimal: Python Decimal object
|
|
88
91
|
"""
|
|
@@ -103,17 +106,21 @@ def _decode_decimal128_binary_java_style(binary_data):
|
|
|
103
106
|
if big_int_value == 0:
|
|
104
107
|
return Decimal('0')
|
|
105
108
|
|
|
106
|
-
# The Java code creates BigDecimal from BigInteger with scale
|
|
107
|
-
#
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
# The Java code creates BigDecimal from BigInteger with the provided scale
|
|
110
|
+
# If scale is provided, use it to create the properly scaled decimal
|
|
111
|
+
if scale is not None:
|
|
112
|
+
# Create decimal with the specified scale (like Java's BigDecimal constructor)
|
|
113
|
+
# This treats big_int_value as the unscaled value
|
|
114
|
+
decimal_value = Decimal(big_int_value) / (Decimal(10) ** scale)
|
|
115
|
+
else:
|
|
116
|
+
# Fallback: try to create decimal directly from the integer value
|
|
117
|
+
decimal_value = Decimal(big_int_value)
|
|
112
118
|
|
|
113
119
|
# Check if this produces a reasonable decimal value
|
|
114
120
|
# Decimal128 should represent normal decimal numbers
|
|
115
|
-
if
|
|
116
|
-
|
|
121
|
+
# Only check range if scale was not provided (backward compatibility)
|
|
122
|
+
if scale is None and (abs(decimal_value) < Decimal('1E-6143') or abs(decimal_value) > Decimal(
|
|
123
|
+
'9.999999999999999999999999999999999E+6144')):
|
|
117
124
|
# Value is outside normal Decimal128 range, try alternative interpretation
|
|
118
125
|
return _decode_decimal128_alternative(binary_data)
|
|
119
126
|
|
|
@@ -624,10 +631,12 @@ def get_column_from_chunk(vector: Vector) -> list:
|
|
|
624
631
|
if vector.isConstantVector:
|
|
625
632
|
# For constant vectors, get the binary data and convert it once
|
|
626
633
|
binary_data = vector.data.numericDecimal128ConstantData.data
|
|
634
|
+
# Get scale with backward compatibility for older engines
|
|
635
|
+
scale = getattr(vector.data.numericDecimal128ConstantData, 'scale', None)
|
|
627
636
|
|
|
628
637
|
# Convert binary data to BigDecimal equivalent
|
|
629
638
|
if binary_data:
|
|
630
|
-
decimal_value = _binary_to_decimal128(binary_data)
|
|
639
|
+
decimal_value = _binary_to_decimal128(binary_data, scale)
|
|
631
640
|
else:
|
|
632
641
|
decimal_value = Decimal('0')
|
|
633
642
|
|
|
@@ -639,13 +648,16 @@ def get_column_from_chunk(vector: Vector) -> list:
|
|
|
639
648
|
value_array.append(decimal_value)
|
|
640
649
|
else:
|
|
641
650
|
# For non-constant vectors, process each row individually
|
|
651
|
+
# Get scale from decimal128Data (with backward compatibility)
|
|
652
|
+
scale = getattr(vector.data.decimal128Data, 'scale', None)
|
|
653
|
+
|
|
642
654
|
for row in range(vector.size):
|
|
643
655
|
if get_null(vector, row):
|
|
644
656
|
value_array.append(None)
|
|
645
657
|
continue
|
|
646
658
|
# Get binary data for this row
|
|
647
659
|
binary_data = vector.data.decimal128Data.data[row]
|
|
648
|
-
decimal_value = _binary_to_decimal128(binary_data)
|
|
660
|
+
decimal_value = _binary_to_decimal128(binary_data, scale)
|
|
649
661
|
value_array.append(decimal_value)
|
|
650
662
|
else:
|
|
651
663
|
value_array.append(None)
|
|
@@ -8,6 +8,8 @@ from __future__ import unicode_literals
|
|
|
8
8
|
|
|
9
9
|
import datetime
|
|
10
10
|
import logging
|
|
11
|
+
import os
|
|
12
|
+
|
|
11
13
|
import re
|
|
12
14
|
import sys
|
|
13
15
|
import time
|
|
@@ -386,6 +388,7 @@ class Connection(object):
|
|
|
386
388
|
self._auto_resume = auto_resume
|
|
387
389
|
|
|
388
390
|
self._grpc_options = grpc_options
|
|
391
|
+
|
|
389
392
|
if self._grpc_options is None:
|
|
390
393
|
self._grpc_options = dict()
|
|
391
394
|
self.grpc_prepare_timeout = self._grpc_options.get('grpc_prepare_timeout') or 10 * 60 # 10 minutes
|
|
@@ -395,13 +398,64 @@ class Connection(object):
|
|
|
395
398
|
The default maximum time on client side to wait for the cluster to resume is 5 minutes.
|
|
396
399
|
"""
|
|
397
400
|
self.grpc_auto_resume_timeout_seconds = self._grpc_options.pop('grpc_auto_resume_timeout_seconds')
|
|
398
|
-
|
|
401
|
+
|
|
402
|
+
self.timeout = 500
|
|
403
|
+
if 'timeout' in self._grpc_options:
|
|
404
|
+
"""
|
|
405
|
+
The default maximum time on client side to wait for the cluster to resume is 5 minutes.
|
|
406
|
+
"""
|
|
407
|
+
self.timeout = self._grpc_options.pop('timeout')
|
|
408
|
+
|
|
409
|
+
|
|
399
410
|
# Store debug flag and register with debug connections
|
|
400
411
|
self._debug = debug
|
|
401
412
|
if self._debug:
|
|
402
413
|
_debug_connections.add(id(self))
|
|
414
|
+
|
|
415
|
+
# Enable comprehensive debugging if debug flag is set
|
|
416
|
+
if self._debug:
|
|
417
|
+
# Configure root logger for DEBUG level
|
|
418
|
+
logging.basicConfig(
|
|
419
|
+
level=logging.DEBUG,
|
|
420
|
+
format='[%(name)s] %(asctime)s - %(levelname)s - %(message)s',
|
|
421
|
+
datefmt='%Y-%m-%d %H:%M:%S',
|
|
422
|
+
force=True # Force reconfiguration even if logging is already configured
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
# Note: gRPC C++ core tracing (GRPC_VERBOSITY and GRPC_TRACE) must be set
|
|
426
|
+
# BEFORE the gRPC module is imported to take effect. Setting them at runtime
|
|
427
|
+
# will not enable HTTP/2 frame logs or low-level tracing.
|
|
428
|
+
#
|
|
429
|
+
# To enable full gRPC network tracing, set these environment variables
|
|
430
|
+
# before starting your Python script:
|
|
431
|
+
# export GRPC_VERBOSITY=DEBUG
|
|
432
|
+
# export GRPC_TRACE=client_channel,http2
|
|
433
|
+
#
|
|
434
|
+
# The following runtime settings only affect Python-level logging:
|
|
435
|
+
|
|
436
|
+
# Enable gRPC Python logging (this works at runtime)
|
|
437
|
+
os.environ['GRPC_PYTHON_LOG_LEVEL'] = 'DEBUG'
|
|
438
|
+
os.environ['GRPC_PYTHON_LOG_STDERR'] = '1'
|
|
439
|
+
|
|
440
|
+
# Ensure gRPC logger is at DEBUG level
|
|
441
|
+
grpc_logger = logging.getLogger('grpc')
|
|
442
|
+
grpc_logger.setLevel(logging.DEBUG)
|
|
443
|
+
|
|
444
|
+
# Enable gRPC transport logger
|
|
445
|
+
grpc_transport_logger = logging.getLogger('grpc._channel')
|
|
446
|
+
grpc_transport_logger.setLevel(logging.DEBUG)
|
|
447
|
+
|
|
448
|
+
# Enable gRPC server logger
|
|
449
|
+
grpc_server_logger = logging.getLogger('grpc._server')
|
|
450
|
+
grpc_server_logger.setLevel(logging.DEBUG)
|
|
451
|
+
|
|
452
|
+
# Set e6data connector logger to DEBUG
|
|
453
|
+
e6data_logger = logging.getLogger('e6data_python_connector')
|
|
454
|
+
e6data_logger.setLevel(logging.DEBUG)
|
|
455
|
+
|
|
403
456
|
_strategy_debug_log(f"Debug mode enabled for connection {id(self)}")
|
|
404
|
-
|
|
457
|
+
_strategy_debug_log(f"GRPC_TRACE={os.environ.get('GRPC_TRACE')}")
|
|
458
|
+
|
|
405
459
|
self._create_client()
|
|
406
460
|
|
|
407
461
|
@property
|
|
@@ -453,6 +507,7 @@ class Connection(object):
|
|
|
453
507
|
Raises:
|
|
454
508
|
grpc.RpcError: If there is an error in creating the gRPC channel or client stub.
|
|
455
509
|
"""
|
|
510
|
+
|
|
456
511
|
if self._secure_channel:
|
|
457
512
|
self._channel = grpc.secure_channel(
|
|
458
513
|
target='{}:{}'.format(self._host, self._port),
|
|
@@ -577,7 +632,7 @@ class Connection(object):
|
|
|
577
632
|
_strategy_debug_log(f"No cached strategy, will try strategies in order: {strategies}")
|
|
578
633
|
last_error = None
|
|
579
634
|
for strategy in strategies:
|
|
580
|
-
_strategy_debug_log(f"
|
|
635
|
+
_strategy_debug_log(f"Attempting authentication with strategy: {strategy}.")
|
|
581
636
|
try:
|
|
582
637
|
authenticate_response = self._client.authenticate(
|
|
583
638
|
authenticate_request,
|
|
@@ -1288,7 +1343,8 @@ class Cursor(DBAPICursor):
|
|
|
1288
1343
|
client = self.connection.client
|
|
1289
1344
|
execute_response = client.executeStatementV2(
|
|
1290
1345
|
execute_statement_request,
|
|
1291
|
-
metadata=self.metadata
|
|
1346
|
+
metadata=self.metadata,
|
|
1347
|
+
timeout=self.connection.timeout
|
|
1292
1348
|
)
|
|
1293
1349
|
|
|
1294
1350
|
# Check for new strategy in execute response
|
|
@@ -1397,13 +1453,14 @@ class Cursor(DBAPICursor):
|
|
|
1397
1453
|
get_next_result_batch_request = e6x_engine_pb2.GetNextResultBatchRequest(
|
|
1398
1454
|
engineIP=self._engine_ip,
|
|
1399
1455
|
sessionId=self.connection.get_session_id,
|
|
1400
|
-
queryId=self._query_id
|
|
1456
|
+
queryId=self._query_id,
|
|
1401
1457
|
)
|
|
1402
1458
|
# Get fresh client after session access (may have been invalidated)
|
|
1403
1459
|
client = self.connection.client
|
|
1404
1460
|
get_next_result_batch_response = client.getNextResultBatch(
|
|
1405
1461
|
get_next_result_batch_request,
|
|
1406
|
-
metadata=self.metadata
|
|
1462
|
+
metadata=self.metadata,
|
|
1463
|
+
timeout=self.connection.timeout
|
|
1407
1464
|
)
|
|
1408
1465
|
|
|
1409
1466
|
# Check for new strategy in batch response
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: e6data-python-connector
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.12rc2
|
|
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.
|
|
@@ -39,7 +39,7 @@ Dynamic: summary
|
|
|
39
39
|
|
|
40
40
|
# e6data Python Connector
|
|
41
41
|
|
|
42
|
-

|
|
43
43
|
|
|
44
44
|
## Introduction
|
|
45
45
|
|
|
@@ -124,6 +124,7 @@ The `Connection` class supports the following parameters:
|
|
|
124
124
|
| `secure` | bool | No | False | Enable SSL/TLS for secure connections |
|
|
125
125
|
| `auto_resume` | bool | No | True | Automatically resume cluster if suspended |
|
|
126
126
|
| `grpc_options` | dict | No | None | Additional gRPC configuration options |
|
|
127
|
+
| `debug` | bool | No | False | Enable debug logging for troubleshooting |
|
|
127
128
|
|
|
128
129
|
#### Secure Connection Example
|
|
129
130
|
|
|
@@ -637,4 +638,58 @@ conn.close()
|
|
|
637
638
|
- Graceful connection recovery and retry logic
|
|
638
639
|
- Blue-green deployment support with automatic failover
|
|
639
640
|
|
|
641
|
+
## Debugging and Troubleshooting
|
|
642
|
+
|
|
643
|
+
### Enable Debug Mode
|
|
644
|
+
|
|
645
|
+
Enable comprehensive debugging to troubleshoot connection and query issues:
|
|
646
|
+
|
|
647
|
+
```python
|
|
648
|
+
from e6data_python_connector import Connection
|
|
649
|
+
|
|
650
|
+
conn = Connection(
|
|
651
|
+
host=host,
|
|
652
|
+
port=port,
|
|
653
|
+
username=username,
|
|
654
|
+
password=password,
|
|
655
|
+
database=database,
|
|
656
|
+
debug=True # Enable debug logging
|
|
657
|
+
)
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
When `debug=True`, the following features are enabled:
|
|
661
|
+
- Python logging at DEBUG level for all operations
|
|
662
|
+
- Blue-green strategy transition logging
|
|
663
|
+
- Connection lifecycle logging
|
|
664
|
+
- Query execution detailed logging
|
|
665
|
+
|
|
666
|
+
### gRPC Network Tracing
|
|
667
|
+
|
|
668
|
+
For low-level gRPC network debugging (HTTP/2 frames, TCP events), set environment variables **before** running your Python script:
|
|
669
|
+
|
|
670
|
+
```bash
|
|
671
|
+
# Enable gRPC network tracing
|
|
672
|
+
export GRPC_VERBOSITY=DEBUG
|
|
673
|
+
export GRPC_TRACE=client_channel,http2
|
|
674
|
+
|
|
675
|
+
# For comprehensive tracing
|
|
676
|
+
export GRPC_TRACE=api,call_error,channel,client_channel,connectivity_state,http,http2_stream,tcp,transport_security
|
|
677
|
+
|
|
678
|
+
# Run your script
|
|
679
|
+
python your_script.py
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
**Note**: These environment variables must be set before Python starts, as the gRPC C++ core reads them at module import time.
|
|
683
|
+
|
|
684
|
+
### Common Issues and Solutions
|
|
685
|
+
|
|
686
|
+
| Issue | Solution |
|
|
687
|
+
|-------|----------|
|
|
688
|
+
| Connection timeout | Check network connectivity, firewall rules, and ensure port 80/443 is open |
|
|
689
|
+
| Authentication failure | Verify username (email) and access token are correct |
|
|
690
|
+
| 503 Service Unavailable | Cluster may be suspended; enable `auto_resume=True` |
|
|
691
|
+
| 456 Strategy Error | Automatic blue-green failover will handle this |
|
|
692
|
+
| Memory issues with large results | Use `fetchall_buffer()` instead of `fetchall()` |
|
|
693
|
+
| gRPC message size errors | Configure `grpc_options` with appropriate message size limits |
|
|
694
|
+
|
|
640
695
|
See [TECH_DOC.md](TECH_DOC.md) for detailed technical documentation.
|
|
@@ -881,13 +881,15 @@ class Decimal128Data(object):
|
|
|
881
881
|
"""
|
|
882
882
|
Attributes:
|
|
883
883
|
- data
|
|
884
|
+
- scale
|
|
884
885
|
|
|
885
886
|
"""
|
|
886
887
|
thrift_spec = None
|
|
887
888
|
|
|
888
889
|
|
|
889
|
-
def __init__(self, data = None,):
|
|
890
|
+
def __init__(self, data = None, scale = None,):
|
|
890
891
|
self.data = data
|
|
892
|
+
self.scale = scale
|
|
891
893
|
|
|
892
894
|
def read(self, iprot):
|
|
893
895
|
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
|
|
@@ -908,6 +910,11 @@ class Decimal128Data(object):
|
|
|
908
910
|
iprot.readListEnd()
|
|
909
911
|
else:
|
|
910
912
|
iprot.skip(ftype)
|
|
913
|
+
elif fid == 2:
|
|
914
|
+
if ftype == TType.I32:
|
|
915
|
+
self.scale = iprot.readI32()
|
|
916
|
+
else:
|
|
917
|
+
iprot.skip(ftype)
|
|
911
918
|
else:
|
|
912
919
|
iprot.skip(ftype)
|
|
913
920
|
iprot.readFieldEnd()
|
|
@@ -926,6 +933,10 @@ class Decimal128Data(object):
|
|
|
926
933
|
oprot.writeBinary(iter55)
|
|
927
934
|
oprot.writeListEnd()
|
|
928
935
|
oprot.writeFieldEnd()
|
|
936
|
+
if self.scale is not None:
|
|
937
|
+
oprot.writeFieldBegin('scale', TType.I32, 2)
|
|
938
|
+
oprot.writeI32(self.scale)
|
|
939
|
+
oprot.writeFieldEnd()
|
|
929
940
|
oprot.writeFieldStop()
|
|
930
941
|
oprot.writeStructEnd()
|
|
931
942
|
|
|
@@ -1310,13 +1321,15 @@ class NumericDecimal128ConstantData(object):
|
|
|
1310
1321
|
"""
|
|
1311
1322
|
Attributes:
|
|
1312
1323
|
- data
|
|
1324
|
+
- scale
|
|
1313
1325
|
|
|
1314
1326
|
"""
|
|
1315
1327
|
thrift_spec = None
|
|
1316
1328
|
|
|
1317
1329
|
|
|
1318
|
-
def __init__(self, data = None,):
|
|
1330
|
+
def __init__(self, data = None, scale = None,):
|
|
1319
1331
|
self.data = data
|
|
1332
|
+
self.scale = scale
|
|
1320
1333
|
|
|
1321
1334
|
def read(self, iprot):
|
|
1322
1335
|
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
|
|
@@ -1332,6 +1345,11 @@ class NumericDecimal128ConstantData(object):
|
|
|
1332
1345
|
self.data = iprot.readBinary()
|
|
1333
1346
|
else:
|
|
1334
1347
|
iprot.skip(ftype)
|
|
1348
|
+
elif fid == 2:
|
|
1349
|
+
if ftype == TType.I32:
|
|
1350
|
+
self.scale = iprot.readI32()
|
|
1351
|
+
else:
|
|
1352
|
+
iprot.skip(ftype)
|
|
1335
1353
|
else:
|
|
1336
1354
|
iprot.skip(ftype)
|
|
1337
1355
|
iprot.readFieldEnd()
|
|
@@ -1347,6 +1365,10 @@ class NumericDecimal128ConstantData(object):
|
|
|
1347
1365
|
oprot.writeFieldBegin('data', TType.STRING, 1)
|
|
1348
1366
|
oprot.writeBinary(self.data)
|
|
1349
1367
|
oprot.writeFieldEnd()
|
|
1368
|
+
if self.scale is not None:
|
|
1369
|
+
oprot.writeFieldBegin('scale', TType.I32, 2)
|
|
1370
|
+
oprot.writeI32(self.scale)
|
|
1371
|
+
oprot.writeFieldEnd()
|
|
1350
1372
|
oprot.writeFieldStop()
|
|
1351
1373
|
oprot.writeStructEnd()
|
|
1352
1374
|
|
|
@@ -1783,6 +1805,7 @@ all_structs.append(Decimal128Data)
|
|
|
1783
1805
|
Decimal128Data.thrift_spec = (
|
|
1784
1806
|
None, # 0
|
|
1785
1807
|
(1, TType.LIST, 'data', (TType.STRING, 'BINARY', False), None, ), # 1
|
|
1808
|
+
(2, TType.I32, 'scale', None, None, ), # 2
|
|
1786
1809
|
)
|
|
1787
1810
|
all_structs.append(VarcharData)
|
|
1788
1811
|
VarcharData.thrift_spec = (
|
|
@@ -1818,6 +1841,7 @@ all_structs.append(NumericDecimal128ConstantData)
|
|
|
1818
1841
|
NumericDecimal128ConstantData.thrift_spec = (
|
|
1819
1842
|
None, # 0
|
|
1820
1843
|
(1, TType.STRING, 'data', 'BINARY', None, ), # 1
|
|
1844
|
+
(2, TType.I32, 'scale', None, None, ), # 2
|
|
1821
1845
|
)
|
|
1822
1846
|
all_structs.append(TemporalIntervalConstantData)
|
|
1823
1847
|
TemporalIntervalConstantData.thrift_spec = (
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/analyze_38_nines.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/analyze_all_cases.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/analyze_binary.py
RENAMED
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/analyze_fields.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/check_decimal_errors.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/cleanup_test_files.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/debug_38_nines.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/debug_binary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_38_nines.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_comprehensive.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_connection_pool.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_known_case.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_manual_analysis.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_mock_server.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_specific_binary.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_strategy.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/test_strategy_logic.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/validate_decimal128.py
RENAMED
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.11rc2 → e6data_python_connector-2.3.12rc2}/test/verify_decimal_fix.py
RENAMED
|
File without changes
|