e6data-python-connector 2.3.12rc11__tar.gz → 2.3.12rc31__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.12rc11/e6data_python_connector.egg-info → e6data_python_connector-2.3.12rc31}/PKG-INFO +49 -2
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/README.md +48 -1
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/datainputstream.py +24 -7
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/e6data_grpc.py +33 -52
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31/e6data_python_connector.egg-info}/PKG-INFO +49 -2
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/setup.py +1 -1
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/LICENSE +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/MANIFEST.in +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/__init__.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/cluster_manager.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/cluster_server/__init__.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/cluster_server/cluster_pb2.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/cluster_server/cluster_pb2_grpc.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/common.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/connection_pool.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/constants.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/date_time_utils.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/dialect.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/e6x_vector/__init__.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/e6x_vector/constants.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/e6x_vector/ttypes.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/exceptions.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/QueryEngineService.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/__init__.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/constants.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/e6x_engine_pb2.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/e6x_engine_pb2.pyi +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/e6x_engine_pb2_grpc.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/server/ttypes.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/strategy.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector/typeId.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector.egg-info/SOURCES.txt +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector.egg-info/dependency_links.txt +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector.egg-info/entry_points.txt +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector.egg-info/requires.txt +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/e6data_python_connector.egg-info/top_level.txt +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/gen-py/__init__.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/gen-py/e6x_vector/__init__.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/gen-py/e6x_vector/constants.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/gen-py/e6x_vector/ttypes.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/pyproject.toml +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/setup.cfg +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/__init__.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_38_nines.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_all_cases.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_binary.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_correct_value.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_fields.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/check_decimal_errors.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/cleanup_test_files.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/debug_38_nines.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/debug_binary.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/final_test.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/move_tests.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/quick_test.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_38_nines.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_all_decimal128_cases.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_cluster_manager_efficiency.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_cluster_manager_none_strategy.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_cluster_manager_strategy.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_comprehensive.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_connection_pool.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_connection_pool_e2e.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_current_implementation.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_decimal128_binary_parsing.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_decimal128_parsing.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_fix.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_improved_parsing.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_known_case.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_manual_analysis.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_mock_server.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_multiprocessing_fix.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_new_implementation.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_pool_concurrency_simple.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_pool_threading_multiprocessing.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_simple_connection_pool.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_specific_binary.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_strategy.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_strategy_logic.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_strategy_persistence_fix.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_strategy_sharing_fix.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_user_binary_value.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/tests.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/tests_grpc.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/validate_decimal128.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/validate_implementation.py +0 -0
- {e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/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.12rc31
|
|
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
|
|
|
@@ -125,6 +125,7 @@ The `Connection` class supports the following parameters:
|
|
|
125
125
|
| `auto_resume` | bool | No | True | Automatically resume cluster if suspended |
|
|
126
126
|
| `grpc_options` | dict | No | None | Additional gRPC configuration options |
|
|
127
127
|
| `debug` | bool | No | False | Enable debug logging for troubleshooting |
|
|
128
|
+
| `require_fastbinary` | bool | No | True | Require fastbinary module for Thrift deserialization. Set to False to use pure Python implementation if system dependencies cannot be installed |
|
|
128
129
|
|
|
129
130
|
#### Secure Connection Example
|
|
130
131
|
|
|
@@ -158,6 +159,51 @@ conn = Connection(
|
|
|
158
159
|
)
|
|
159
160
|
```
|
|
160
161
|
|
|
162
|
+
#### Handling Missing System Dependencies
|
|
163
|
+
|
|
164
|
+
The e6data connector uses the `fastbinary` module (from Apache Thrift) for optimal performance when deserializing data. This module requires system-level dependencies (`python3-devel` and `gcc-c++`) to be installed.
|
|
165
|
+
|
|
166
|
+
**Default Behavior (Recommended):**
|
|
167
|
+
By default, the connector requires `fastbinary` to be available. If it's not found, the connection will fail immediately with a clear error message:
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
conn = Connection(
|
|
171
|
+
host=host,
|
|
172
|
+
port=port,
|
|
173
|
+
username=username,
|
|
174
|
+
password=password,
|
|
175
|
+
database=database
|
|
176
|
+
)
|
|
177
|
+
# Raises exception if fastbinary is not available
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Fallback to Pure Python:**
|
|
181
|
+
If you cannot install system dependencies (e.g., in restricted environments, serverless platforms, or containers without build tools), you can disable the `fastbinary` requirement. The connector will fall back to a pure Python implementation with a performance penalty:
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
conn = Connection(
|
|
185
|
+
host=host,
|
|
186
|
+
port=port,
|
|
187
|
+
username=username,
|
|
188
|
+
password=password,
|
|
189
|
+
database=database,
|
|
190
|
+
require_fastbinary=False # Allow operation without fastbinary
|
|
191
|
+
)
|
|
192
|
+
# Logs warning but continues with pure Python implementation
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**When to use `require_fastbinary=False`:**
|
|
196
|
+
- Running in AWS Lambda or other serverless environments
|
|
197
|
+
- Docker containers built without compilation tools
|
|
198
|
+
- Restricted environments where system packages cannot be installed
|
|
199
|
+
- Development/testing environments where performance is not critical
|
|
200
|
+
|
|
201
|
+
**Performance Impact:**
|
|
202
|
+
- With `fastbinary`: Optimal performance for data deserialization
|
|
203
|
+
- Without `fastbinary` (pure Python): ~2-3x slower deserialization, but otherwise fully functional
|
|
204
|
+
|
|
205
|
+
**Note:** It's strongly recommended to install system dependencies when possible for best performance. The `require_fastbinary=False` option should only be used when system dependencies cannot be installed.
|
|
206
|
+
|
|
161
207
|
### Perform a Queries & Get Results
|
|
162
208
|
|
|
163
209
|
```python
|
|
@@ -691,5 +737,6 @@ python your_script.py
|
|
|
691
737
|
| 456 Strategy Error | Automatic blue-green failover will handle this |
|
|
692
738
|
| Memory issues with large results | Use `fetchall_buffer()` instead of `fetchall()` |
|
|
693
739
|
| gRPC message size errors | Configure `grpc_options` with appropriate message size limits |
|
|
740
|
+
| fastbinary import error | Install system dependencies (`python3-devel`, `gcc-c++`) or set `require_fastbinary=False` |
|
|
694
741
|
|
|
695
742
|
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
|
|
|
@@ -86,6 +86,7 @@ The `Connection` class supports the following parameters:
|
|
|
86
86
|
| `auto_resume` | bool | No | True | Automatically resume cluster if suspended |
|
|
87
87
|
| `grpc_options` | dict | No | None | Additional gRPC configuration options |
|
|
88
88
|
| `debug` | bool | No | False | Enable debug logging for troubleshooting |
|
|
89
|
+
| `require_fastbinary` | bool | No | True | Require fastbinary module for Thrift deserialization. Set to False to use pure Python implementation if system dependencies cannot be installed |
|
|
89
90
|
|
|
90
91
|
#### Secure Connection Example
|
|
91
92
|
|
|
@@ -119,6 +120,51 @@ conn = Connection(
|
|
|
119
120
|
)
|
|
120
121
|
```
|
|
121
122
|
|
|
123
|
+
#### Handling Missing System Dependencies
|
|
124
|
+
|
|
125
|
+
The e6data connector uses the `fastbinary` module (from Apache Thrift) for optimal performance when deserializing data. This module requires system-level dependencies (`python3-devel` and `gcc-c++`) to be installed.
|
|
126
|
+
|
|
127
|
+
**Default Behavior (Recommended):**
|
|
128
|
+
By default, the connector requires `fastbinary` to be available. If it's not found, the connection will fail immediately with a clear error message:
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
conn = Connection(
|
|
132
|
+
host=host,
|
|
133
|
+
port=port,
|
|
134
|
+
username=username,
|
|
135
|
+
password=password,
|
|
136
|
+
database=database
|
|
137
|
+
)
|
|
138
|
+
# Raises exception if fastbinary is not available
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Fallback to Pure Python:**
|
|
142
|
+
If you cannot install system dependencies (e.g., in restricted environments, serverless platforms, or containers without build tools), you can disable the `fastbinary` requirement. The connector will fall back to a pure Python implementation with a performance penalty:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
conn = Connection(
|
|
146
|
+
host=host,
|
|
147
|
+
port=port,
|
|
148
|
+
username=username,
|
|
149
|
+
password=password,
|
|
150
|
+
database=database,
|
|
151
|
+
require_fastbinary=False # Allow operation without fastbinary
|
|
152
|
+
)
|
|
153
|
+
# Logs warning but continues with pure Python implementation
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**When to use `require_fastbinary=False`:**
|
|
157
|
+
- Running in AWS Lambda or other serverless environments
|
|
158
|
+
- Docker containers built without compilation tools
|
|
159
|
+
- Restricted environments where system packages cannot be installed
|
|
160
|
+
- Development/testing environments where performance is not critical
|
|
161
|
+
|
|
162
|
+
**Performance Impact:**
|
|
163
|
+
- With `fastbinary`: Optimal performance for data deserialization
|
|
164
|
+
- Without `fastbinary` (pure Python): ~2-3x slower deserialization, but otherwise fully functional
|
|
165
|
+
|
|
166
|
+
**Note:** It's strongly recommended to install system dependencies when possible for best performance. The `require_fastbinary=False` option should only be used when system dependencies cannot be installed.
|
|
167
|
+
|
|
122
168
|
### Perform a Queries & Get Results
|
|
123
169
|
|
|
124
170
|
```python
|
|
@@ -652,5 +698,6 @@ python your_script.py
|
|
|
652
698
|
| 456 Strategy Error | Automatic blue-green failover will handle this |
|
|
653
699
|
| Memory issues with large results | Use `fetchall_buffer()` instead of `fetchall()` |
|
|
654
700
|
| gRPC message size errors | Configure `grpc_options` with appropriate message size limits |
|
|
701
|
+
| fastbinary import error | Install system dependencies (`python3-devel`, `gcc-c++`) or set `require_fastbinary=False` |
|
|
655
702
|
|
|
656
703
|
See [TECH_DOC.md](TECH_DOC.md) for detailed technical documentation.
|
|
@@ -12,20 +12,27 @@ from e6data_python_connector.e6x_vector.ttypes import Chunk, Vector, VectorType
|
|
|
12
12
|
from e6data_python_connector.constants import ZONE
|
|
13
13
|
from e6data_python_connector.date_time_utils import floor_div, floor_mod, timezone_from_offset
|
|
14
14
|
|
|
15
|
+
# Try to import fastbinary - it's optional but provides better performance
|
|
16
|
+
_fastbinary_available = False
|
|
15
17
|
try:
|
|
16
18
|
from thrift.protocol import fastbinary
|
|
19
|
+
_fastbinary_available = True
|
|
17
20
|
except ImportError:
|
|
18
|
-
|
|
19
|
-
"""
|
|
20
|
-
Failed to import fastbinary.
|
|
21
|
-
Did you install system dependencies?
|
|
22
|
-
Please verify https://github.com/e6x-labs/e6data-python-connector#dependencies
|
|
23
|
-
"""
|
|
24
|
-
)
|
|
21
|
+
pass # Will check require_fastbinary flag at connection creation time
|
|
25
22
|
|
|
26
23
|
_logger = logging.getLogger(__name__)
|
|
27
24
|
|
|
28
25
|
|
|
26
|
+
def is_fastbinary_available():
|
|
27
|
+
"""
|
|
28
|
+
Check if fastbinary module is available.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
bool: True if fastbinary is available, False otherwise
|
|
32
|
+
"""
|
|
33
|
+
return _fastbinary_available
|
|
34
|
+
|
|
35
|
+
|
|
29
36
|
def _binary_to_decimal128(binary_data, scale=None):
|
|
30
37
|
"""
|
|
31
38
|
Convert binary data to Decimal128.
|
|
@@ -504,6 +511,16 @@ def read_values_from_array(query_columns_description: list, dis: DataInputStream
|
|
|
504
511
|
|
|
505
512
|
|
|
506
513
|
def read_rows_from_chunk(query_columns_description: list, buffer):
|
|
514
|
+
"""
|
|
515
|
+
Read rows from a Thrift-encoded chunk buffer.
|
|
516
|
+
|
|
517
|
+
Args:
|
|
518
|
+
query_columns_description: List of column descriptions
|
|
519
|
+
buffer: Thrift-encoded binary buffer
|
|
520
|
+
|
|
521
|
+
Returns:
|
|
522
|
+
List of rows
|
|
523
|
+
"""
|
|
507
524
|
# Create a transport and protocol instance for deserialization
|
|
508
525
|
transport = TTransport.TMemoryBuffer(buffer)
|
|
509
526
|
protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)
|
|
@@ -26,7 +26,7 @@ from e6data_python_connector.cluster_manager import ClusterManager
|
|
|
26
26
|
from e6data_python_connector.strategy import _get_grpc_header as _get_strategy_header
|
|
27
27
|
from e6data_python_connector.common import DBAPITypeObject, ParamEscaper, DBAPICursor
|
|
28
28
|
from e6data_python_connector.constants import *
|
|
29
|
-
from e6data_python_connector.datainputstream import get_query_columns_info, read_rows_from_chunk
|
|
29
|
+
from e6data_python_connector.datainputstream import get_query_columns_info, read_rows_from_chunk, is_fastbinary_available
|
|
30
30
|
from e6data_python_connector.server import e6x_engine_pb2_grpc, e6x_engine_pb2
|
|
31
31
|
from e6data_python_connector.typeId import *
|
|
32
32
|
|
|
@@ -335,6 +335,7 @@ class Connection(object):
|
|
|
335
335
|
scheme: str = 'e6data',
|
|
336
336
|
grpc_options: dict = None,
|
|
337
337
|
debug: bool = False,
|
|
338
|
+
require_fastbinary: bool = True,
|
|
338
339
|
):
|
|
339
340
|
"""
|
|
340
341
|
Parameters
|
|
@@ -368,6 +369,10 @@ class Connection(object):
|
|
|
368
369
|
- keepalive_time_ms: This parameter defines the time, in milliseconds, Default to 30 seconds
|
|
369
370
|
debug: bool, Optional
|
|
370
371
|
Flag to enable debug logging for blue-green deployment strategy changes
|
|
372
|
+
require_fastbinary: bool, Optional
|
|
373
|
+
Flag to require fastbinary module for Thrift deserialization. If True (default),
|
|
374
|
+
raises an exception if fastbinary is not available. If False, logs a warning
|
|
375
|
+
and continues with pure Python implementation (with reduced performance).
|
|
371
376
|
"""
|
|
372
377
|
if not username or not password:
|
|
373
378
|
raise ValueError("username or password cannot be empty.")
|
|
@@ -387,6 +392,29 @@ class Connection(object):
|
|
|
387
392
|
|
|
388
393
|
self._auto_resume = auto_resume
|
|
389
394
|
|
|
395
|
+
# Store require_fastbinary flag
|
|
396
|
+
self._require_fastbinary = require_fastbinary
|
|
397
|
+
|
|
398
|
+
# Check fastbinary availability at connection creation time
|
|
399
|
+
if not is_fastbinary_available():
|
|
400
|
+
if require_fastbinary:
|
|
401
|
+
raise Exception(
|
|
402
|
+
"""
|
|
403
|
+
Failed to import fastbinary.
|
|
404
|
+
Did you install system dependencies?
|
|
405
|
+
Please verify https://github.com/e6x-labs/e6data-python-connector#dependencies
|
|
406
|
+
|
|
407
|
+
To continue without fastbinary (with reduced performance), set require_fastbinary=False
|
|
408
|
+
in the connection parameters.
|
|
409
|
+
"""
|
|
410
|
+
)
|
|
411
|
+
else:
|
|
412
|
+
logger.warning(
|
|
413
|
+
"fastbinary module is not available. Using pure Python implementation. "
|
|
414
|
+
"Performance may be degraded. To enable fastbinary, install system dependencies: "
|
|
415
|
+
"https://github.com/e6x-labs/e6data-python-connector#dependencies"
|
|
416
|
+
)
|
|
417
|
+
|
|
390
418
|
self._grpc_options = grpc_options
|
|
391
419
|
if self._grpc_options is None:
|
|
392
420
|
self._grpc_options = dict()
|
|
@@ -853,56 +881,6 @@ class Connection(object):
|
|
|
853
881
|
)
|
|
854
882
|
return dry_run_response.dryrunValue
|
|
855
883
|
|
|
856
|
-
def get_logical_plan(self, query, catalog=None, schema=None):
|
|
857
|
-
"""
|
|
858
|
-
Gets the logical execution plan for a query without executing it.
|
|
859
|
-
This method performs syntax, parsing, and plan compilation, then returns the logical plan.
|
|
860
|
-
|
|
861
|
-
Args:
|
|
862
|
-
query (str): The SQL query to get the plan for.
|
|
863
|
-
catalog (str, optional): Catalog name. Uses connection's catalog if not provided.
|
|
864
|
-
schema (str, optional): Schema/database name. Uses connection's database if not provided.
|
|
865
|
-
|
|
866
|
-
Returns:
|
|
867
|
-
dict: A dictionary with:
|
|
868
|
-
- 'success' (bool): True if plan generation succeeded, False otherwise
|
|
869
|
-
- 'plan' (str, optional): The logical plan string if successful
|
|
870
|
-
- 'error' (str, optional): Error message if plan generation failed
|
|
871
|
-
|
|
872
|
-
Example:
|
|
873
|
-
>>> result = conn.get_logical_plan("SELECT * FROM table")
|
|
874
|
-
>>> if result['success']:
|
|
875
|
-
... print(f"Plan: {result['plan']}")
|
|
876
|
-
>>> else:
|
|
877
|
-
... print(f"Error: {result['error']}")
|
|
878
|
-
"""
|
|
879
|
-
catalog_to_use = catalog if catalog is not None else self.catalog_name
|
|
880
|
-
schema_to_use = schema if schema is not None else self.database
|
|
881
|
-
|
|
882
|
-
try:
|
|
883
|
-
dry_run_request = e6x_engine_pb2.DryRunRequestV2(
|
|
884
|
-
sessionId=self.get_session_id,
|
|
885
|
-
schema=schema_to_use,
|
|
886
|
-
catalog=catalog_to_use,
|
|
887
|
-
queryString=query
|
|
888
|
-
)
|
|
889
|
-
|
|
890
|
-
dry_run_response = self._client.dryRunV2(
|
|
891
|
-
dry_run_request,
|
|
892
|
-
metadata=_get_grpc_header(cluster=self.cluster_name, strategy=_get_active_strategy())
|
|
893
|
-
)
|
|
894
|
-
|
|
895
|
-
return {
|
|
896
|
-
'success': True,
|
|
897
|
-
'plan': dry_run_response.dryrunValue
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
except Exception as e:
|
|
901
|
-
return {
|
|
902
|
-
'success': False,
|
|
903
|
-
'error': str(e)
|
|
904
|
-
}
|
|
905
|
-
|
|
906
884
|
def get_tables(self, catalog, database):
|
|
907
885
|
"""
|
|
908
886
|
Retrieves the list of tables from the specified catalog and database.
|
|
@@ -1514,7 +1492,10 @@ class Cursor(DBAPICursor):
|
|
|
1514
1492
|
if not buffer or len(buffer) == 0:
|
|
1515
1493
|
return None
|
|
1516
1494
|
# one batch retrieves the predefined set of rows
|
|
1517
|
-
return read_rows_from_chunk(
|
|
1495
|
+
return read_rows_from_chunk(
|
|
1496
|
+
self._query_columns_description,
|
|
1497
|
+
buffer
|
|
1498
|
+
)
|
|
1518
1499
|
|
|
1519
1500
|
def fetchall(self):
|
|
1520
1501
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: e6data-python-connector
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.12rc31
|
|
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
|
|
|
@@ -125,6 +125,7 @@ The `Connection` class supports the following parameters:
|
|
|
125
125
|
| `auto_resume` | bool | No | True | Automatically resume cluster if suspended |
|
|
126
126
|
| `grpc_options` | dict | No | None | Additional gRPC configuration options |
|
|
127
127
|
| `debug` | bool | No | False | Enable debug logging for troubleshooting |
|
|
128
|
+
| `require_fastbinary` | bool | No | True | Require fastbinary module for Thrift deserialization. Set to False to use pure Python implementation if system dependencies cannot be installed |
|
|
128
129
|
|
|
129
130
|
#### Secure Connection Example
|
|
130
131
|
|
|
@@ -158,6 +159,51 @@ conn = Connection(
|
|
|
158
159
|
)
|
|
159
160
|
```
|
|
160
161
|
|
|
162
|
+
#### Handling Missing System Dependencies
|
|
163
|
+
|
|
164
|
+
The e6data connector uses the `fastbinary` module (from Apache Thrift) for optimal performance when deserializing data. This module requires system-level dependencies (`python3-devel` and `gcc-c++`) to be installed.
|
|
165
|
+
|
|
166
|
+
**Default Behavior (Recommended):**
|
|
167
|
+
By default, the connector requires `fastbinary` to be available. If it's not found, the connection will fail immediately with a clear error message:
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
conn = Connection(
|
|
171
|
+
host=host,
|
|
172
|
+
port=port,
|
|
173
|
+
username=username,
|
|
174
|
+
password=password,
|
|
175
|
+
database=database
|
|
176
|
+
)
|
|
177
|
+
# Raises exception if fastbinary is not available
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Fallback to Pure Python:**
|
|
181
|
+
If you cannot install system dependencies (e.g., in restricted environments, serverless platforms, or containers without build tools), you can disable the `fastbinary` requirement. The connector will fall back to a pure Python implementation with a performance penalty:
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
conn = Connection(
|
|
185
|
+
host=host,
|
|
186
|
+
port=port,
|
|
187
|
+
username=username,
|
|
188
|
+
password=password,
|
|
189
|
+
database=database,
|
|
190
|
+
require_fastbinary=False # Allow operation without fastbinary
|
|
191
|
+
)
|
|
192
|
+
# Logs warning but continues with pure Python implementation
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**When to use `require_fastbinary=False`:**
|
|
196
|
+
- Running in AWS Lambda or other serverless environments
|
|
197
|
+
- Docker containers built without compilation tools
|
|
198
|
+
- Restricted environments where system packages cannot be installed
|
|
199
|
+
- Development/testing environments where performance is not critical
|
|
200
|
+
|
|
201
|
+
**Performance Impact:**
|
|
202
|
+
- With `fastbinary`: Optimal performance for data deserialization
|
|
203
|
+
- Without `fastbinary` (pure Python): ~2-3x slower deserialization, but otherwise fully functional
|
|
204
|
+
|
|
205
|
+
**Note:** It's strongly recommended to install system dependencies when possible for best performance. The `require_fastbinary=False` option should only be used when system dependencies cannot be installed.
|
|
206
|
+
|
|
161
207
|
### Perform a Queries & Get Results
|
|
162
208
|
|
|
163
209
|
```python
|
|
@@ -691,5 +737,6 @@ python your_script.py
|
|
|
691
737
|
| 456 Strategy Error | Automatic blue-green failover will handle this |
|
|
692
738
|
| Memory issues with large results | Use `fetchall_buffer()` instead of `fetchall()` |
|
|
693
739
|
| gRPC message size errors | Configure `grpc_options` with appropriate message size limits |
|
|
740
|
+
| fastbinary import error | Install system dependencies (`python3-devel`, `gcc-c++`) or set `require_fastbinary=False` |
|
|
694
741
|
|
|
695
742
|
See [TECH_DOC.md](TECH_DOC.md) for detailed technical documentation.
|
|
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.12rc11 → e6data_python_connector-2.3.12rc31}/gen-py/__init__.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.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_38_nines.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_all_cases.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_binary.py
RENAMED
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/analyze_fields.py
RENAMED
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/cleanup_test_files.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/debug_38_nines.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/debug_binary.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/final_test.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/move_tests.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/quick_test.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/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.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_comprehensive.py
RENAMED
|
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.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_known_case.py
RENAMED
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_mock_server.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.12rc11 → e6data_python_connector-2.3.12rc31}/test/test_strategy.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.12rc11 → e6data_python_connector-2.3.12rc31}/test/tests_grpc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.12rc11 → e6data_python_connector-2.3.12rc31}/test/verify_decimal_fix.py
RENAMED
|
File without changes
|