databricks-sql-connector 4.0.3__tar.gz → 4.0.5__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.
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/CHANGELOG.md +12 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/PKG-INFO +3 -2
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/pyproject.toml +1 -1
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/__init__.py +1 -1
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/client.py +23 -1
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/parameters/__init__.py +2 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/parameters/native.py +125 -11
- databricks_sql_connector-4.0.5/src/databricks/sql/thrift_api/TCLIService/ttypes.py +50630 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/thrift_backend.py +17 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/utils.py +38 -17
- databricks_sql_connector-4.0.3/src/databricks/sql/thrift_api/TCLIService/ttypes.py +0 -111775
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/LICENSE +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/README.md +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/__init__.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/auth/__init__.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/auth/auth.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/auth/authenticators.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/auth/endpoint.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/auth/oauth.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/auth/oauth_http_handler.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/auth/retry.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/auth/thrift_http_client.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/cloudfetch/download_manager.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/cloudfetch/downloader.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/exc.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/experimental/__init__.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/experimental/oauth_persistence.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/parameters/py.typed +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/py.typed +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/thrift_api/TCLIService/TCLIService-remote +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/thrift_api/TCLIService/TCLIService.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/thrift_api/TCLIService/__init__.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/thrift_api/TCLIService/constants.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/thrift_api/__init__.py +0 -0
- {databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/types.py +0 -0
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
# 4.0.5 (2025-06-24)
|
|
4
|
+
- Fix: Reverted change in cursor close handling which led to errors impacting users (databricks/databricks-sql-python#613 by @madhav-db)
|
|
5
|
+
|
|
6
|
+
# 4.0.4 (2025-06-16)
|
|
7
|
+
|
|
8
|
+
- Update thrift client library after cleaning up unused fields and structs (databricks/databricks-sql-python#553 by @vikrantpuppala)
|
|
9
|
+
- Refactor decimal conversion in PyArrow tables to use direct casting (databricks/databricks-sql-python#544 by @jayantsing-db)
|
|
10
|
+
- Fix: `fetchall_arrow` to always return results in `arrow` format (databricks/databricks-sql-python#551 by @shivam2680)
|
|
11
|
+
- Enhance cursor close handling and context manager exception management to prevent server side resource leaks (databricks/databricks-sql-python#554 by @madhav-db)
|
|
12
|
+
- Added additional logging to enhance debugging (databricks/databricks-sql-python#556 by @saishreeeee)
|
|
13
|
+
- Feature: Added support for complex data types such as Arrays and Map [Private Preview] (databricks/databricks-sql-python#559 by @jprakash-db)
|
|
14
|
+
|
|
3
15
|
# 4.0.3 (2025-04-22)
|
|
4
16
|
|
|
5
17
|
- Fix: Removed `packaging` dependency in favour of default libraries, for `urllib3` version checks (databricks/databricks-sql-python#547 by @jprakash-db)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: databricks-sql-connector
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.5
|
|
4
4
|
Summary: Databricks SQL Connector for Python
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Author: Databricks
|
|
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
17
|
Provides-Extra: pyarrow
|
|
17
18
|
Requires-Dist: lz4 (>=4.0.2,<5.0.0)
|
|
18
19
|
Requires-Dist: oauthlib (>=3.1.0,<4.0.0)
|
{databricks_sql_connector-4.0.3 → databricks_sql_connector-4.0.5}/src/databricks/sql/client.py
RENAMED
|
@@ -214,6 +214,12 @@ class Connection:
|
|
|
214
214
|
# use_cloud_fetch
|
|
215
215
|
# Enable use of cloud fetch to extract large query results in parallel via cloud storage
|
|
216
216
|
|
|
217
|
+
logger.debug(
|
|
218
|
+
"Connection.__init__(server_hostname=%s, http_path=%s)",
|
|
219
|
+
server_hostname,
|
|
220
|
+
http_path,
|
|
221
|
+
)
|
|
222
|
+
|
|
217
223
|
if access_token:
|
|
218
224
|
access_token_kv = {"access_token": access_token}
|
|
219
225
|
kwargs = {**kwargs, **access_token_kv}
|
|
@@ -787,6 +793,9 @@ class Cursor:
|
|
|
787
793
|
|
|
788
794
|
:returns self
|
|
789
795
|
"""
|
|
796
|
+
logger.debug(
|
|
797
|
+
"Cursor.execute(operation=%s, parameters=%s)", operation, parameters
|
|
798
|
+
)
|
|
790
799
|
|
|
791
800
|
param_approach = self._determine_parameter_approach(parameters)
|
|
792
801
|
if param_approach == ParameterApproach.NONE:
|
|
@@ -1415,9 +1424,22 @@ class ResultSet:
|
|
|
1415
1424
|
while not self.has_been_closed_server_side and self.has_more_rows:
|
|
1416
1425
|
self._fill_results_buffer()
|
|
1417
1426
|
partial_results = self.results.remaining_rows()
|
|
1418
|
-
|
|
1427
|
+
if isinstance(results, ColumnTable) and isinstance(
|
|
1428
|
+
partial_results, ColumnTable
|
|
1429
|
+
):
|
|
1430
|
+
results = self.merge_columnar(results, partial_results)
|
|
1431
|
+
else:
|
|
1432
|
+
results = pyarrow.concat_tables([results, partial_results])
|
|
1419
1433
|
self._next_row_index += partial_results.num_rows
|
|
1420
1434
|
|
|
1435
|
+
# If PyArrow is installed and we have a ColumnTable result, convert it to PyArrow Table
|
|
1436
|
+
# Valid only for metadata commands result set
|
|
1437
|
+
if isinstance(results, ColumnTable) and pyarrow:
|
|
1438
|
+
data = {
|
|
1439
|
+
name: col
|
|
1440
|
+
for name, col in zip(results.column_names, results.column_table)
|
|
1441
|
+
}
|
|
1442
|
+
return pyarrow.Table.from_pydict(data)
|
|
1421
1443
|
return results
|
|
1422
1444
|
|
|
1423
1445
|
def fetchall_columnar(self):
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import decimal
|
|
3
3
|
from enum import Enum, auto
|
|
4
|
-
from typing import Optional, Sequence
|
|
4
|
+
from typing import Optional, Sequence, Any
|
|
5
5
|
|
|
6
6
|
from databricks.sql.exc import NotSupportedError
|
|
7
7
|
from databricks.sql.thrift_api.TCLIService.ttypes import (
|
|
8
8
|
TSparkParameter,
|
|
9
9
|
TSparkParameterValue,
|
|
10
|
+
TSparkParameterValueArg,
|
|
10
11
|
)
|
|
11
12
|
|
|
12
13
|
import datetime
|
|
@@ -54,7 +55,17 @@ class DatabricksSupportedType(Enum):
|
|
|
54
55
|
|
|
55
56
|
|
|
56
57
|
TAllowedParameterValue = Union[
|
|
57
|
-
str,
|
|
58
|
+
str,
|
|
59
|
+
int,
|
|
60
|
+
float,
|
|
61
|
+
datetime.datetime,
|
|
62
|
+
datetime.date,
|
|
63
|
+
bool,
|
|
64
|
+
decimal.Decimal,
|
|
65
|
+
None,
|
|
66
|
+
list,
|
|
67
|
+
dict,
|
|
68
|
+
tuple,
|
|
58
69
|
]
|
|
59
70
|
|
|
60
71
|
|
|
@@ -82,6 +93,7 @@ class DbsqlParameterBase:
|
|
|
82
93
|
|
|
83
94
|
CAST_EXPR: str
|
|
84
95
|
name: Optional[str]
|
|
96
|
+
value: Any
|
|
85
97
|
|
|
86
98
|
def as_tspark_param(self, named: bool) -> TSparkParameter:
|
|
87
99
|
"""Returns a TSparkParameter object that can be passed to the DBR thrift server."""
|
|
@@ -98,6 +110,10 @@ class DbsqlParameterBase:
|
|
|
98
110
|
def _tspark_param_value(self):
|
|
99
111
|
return TSparkParameterValue(stringValue=str(self.value))
|
|
100
112
|
|
|
113
|
+
def _tspark_value_arg(self):
|
|
114
|
+
"""Returns a TSparkParameterValueArg object that can be passed to the DBR thrift server."""
|
|
115
|
+
return TSparkParameterValueArg(value=str(self.value), type=self._cast_expr())
|
|
116
|
+
|
|
101
117
|
def _cast_expr(self):
|
|
102
118
|
return self.CAST_EXPR
|
|
103
119
|
|
|
@@ -428,6 +444,99 @@ class TinyIntParameter(DbsqlParameterBase):
|
|
|
428
444
|
CAST_EXPR = DatabricksSupportedType.TINYINT.name
|
|
429
445
|
|
|
430
446
|
|
|
447
|
+
class ArrayParameter(DbsqlParameterBase):
|
|
448
|
+
"""Wrap a Python `Sequence` that will be bound to a Databricks SQL ARRAY type."""
|
|
449
|
+
|
|
450
|
+
def __init__(self, value: Sequence[Any], name: Optional[str] = None):
|
|
451
|
+
"""
|
|
452
|
+
:value:
|
|
453
|
+
The value to bind for this parameter. This will be casted to a ARRAY.
|
|
454
|
+
:name:
|
|
455
|
+
If None, your query must contain a `?` marker. Like:
|
|
456
|
+
|
|
457
|
+
```sql
|
|
458
|
+
SELECT * FROM table WHERE field = ?
|
|
459
|
+
```
|
|
460
|
+
If not None, your query should contain a named parameter marker. Like:
|
|
461
|
+
```sql
|
|
462
|
+
SELECT * FROM table WHERE field = :my_param
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
The `name` argument to this function would be `my_param`.
|
|
466
|
+
"""
|
|
467
|
+
self.name = name
|
|
468
|
+
self.value = [dbsql_parameter_from_primitive(val) for val in value]
|
|
469
|
+
|
|
470
|
+
def as_tspark_param(self, named: bool = False) -> TSparkParameter:
|
|
471
|
+
"""Returns a TSparkParameter object that can be passed to the DBR thrift server."""
|
|
472
|
+
|
|
473
|
+
tsp = TSparkParameter(type=self._cast_expr())
|
|
474
|
+
tsp.arguments = [val._tspark_value_arg() for val in self.value]
|
|
475
|
+
|
|
476
|
+
if named:
|
|
477
|
+
tsp.name = self.name
|
|
478
|
+
tsp.ordinal = False
|
|
479
|
+
elif not named:
|
|
480
|
+
tsp.ordinal = True
|
|
481
|
+
return tsp
|
|
482
|
+
|
|
483
|
+
def _tspark_value_arg(self):
|
|
484
|
+
"""Returns a TSparkParameterValueArg object that can be passed to the DBR thrift server."""
|
|
485
|
+
tva = TSparkParameterValueArg(type=self._cast_expr())
|
|
486
|
+
tva.arguments = [val._tspark_value_arg() for val in self.value]
|
|
487
|
+
return tva
|
|
488
|
+
|
|
489
|
+
CAST_EXPR = DatabricksSupportedType.ARRAY.name
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
class MapParameter(DbsqlParameterBase):
|
|
493
|
+
"""Wrap a Python `dict` that will be bound to a Databricks SQL MAP type."""
|
|
494
|
+
|
|
495
|
+
def __init__(self, value: dict, name: Optional[str] = None):
|
|
496
|
+
"""
|
|
497
|
+
:value:
|
|
498
|
+
The value to bind for this parameter. This will be casted to a MAP.
|
|
499
|
+
:name:
|
|
500
|
+
If None, your query must contain a `?` marker. Like:
|
|
501
|
+
|
|
502
|
+
```sql
|
|
503
|
+
SELECT * FROM table WHERE field = ?
|
|
504
|
+
```
|
|
505
|
+
If not None, your query should contain a named parameter marker. Like:
|
|
506
|
+
```sql
|
|
507
|
+
SELECT * FROM table WHERE field = :my_param
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
The `name` argument to this function would be `my_param`.
|
|
511
|
+
"""
|
|
512
|
+
self.name = name
|
|
513
|
+
self.value = [
|
|
514
|
+
dbsql_parameter_from_primitive(item)
|
|
515
|
+
for key, val in value.items()
|
|
516
|
+
for item in (key, val)
|
|
517
|
+
]
|
|
518
|
+
|
|
519
|
+
def as_tspark_param(self, named: bool = False) -> TSparkParameter:
|
|
520
|
+
"""Returns a TSparkParameter object that can be passed to the DBR thrift server."""
|
|
521
|
+
|
|
522
|
+
tsp = TSparkParameter(type=self._cast_expr())
|
|
523
|
+
tsp.arguments = [val._tspark_value_arg() for val in self.value]
|
|
524
|
+
if named:
|
|
525
|
+
tsp.name = self.name
|
|
526
|
+
tsp.ordinal = False
|
|
527
|
+
elif not named:
|
|
528
|
+
tsp.ordinal = True
|
|
529
|
+
return tsp
|
|
530
|
+
|
|
531
|
+
def _tspark_value_arg(self):
|
|
532
|
+
"""Returns a TSparkParameterValueArg object that can be passed to the DBR thrift server."""
|
|
533
|
+
tva = TSparkParameterValueArg(type=self._cast_expr())
|
|
534
|
+
tva.arguments = [val._tspark_value_arg() for val in self.value]
|
|
535
|
+
return tva
|
|
536
|
+
|
|
537
|
+
CAST_EXPR = DatabricksSupportedType.MAP.name
|
|
538
|
+
|
|
539
|
+
|
|
431
540
|
class DecimalParameter(DbsqlParameterBase):
|
|
432
541
|
"""Wrap a Python `Decimal` that will be bound to a Databricks SQL DECIMAL type."""
|
|
433
542
|
|
|
@@ -543,23 +652,26 @@ def dbsql_parameter_from_primitive(
|
|
|
543
652
|
# havoc. We can't use TYPE_INFERRENCE_MAP because mypy doesn't trust
|
|
544
653
|
# its logic
|
|
545
654
|
|
|
546
|
-
if
|
|
655
|
+
if isinstance(value, bool):
|
|
656
|
+
return BooleanParameter(value=value, name=name)
|
|
657
|
+
elif isinstance(value, int):
|
|
547
658
|
return dbsql_parameter_from_int(value, name=name)
|
|
548
|
-
elif
|
|
659
|
+
elif isinstance(value, str):
|
|
549
660
|
return StringParameter(value=value, name=name)
|
|
550
|
-
elif
|
|
661
|
+
elif isinstance(value, float):
|
|
551
662
|
return FloatParameter(value=value, name=name)
|
|
552
|
-
elif
|
|
663
|
+
elif isinstance(value, datetime.datetime):
|
|
553
664
|
return TimestampParameter(value=value, name=name)
|
|
554
|
-
elif
|
|
665
|
+
elif isinstance(value, datetime.date):
|
|
555
666
|
return DateParameter(value=value, name=name)
|
|
556
|
-
elif
|
|
557
|
-
return BooleanParameter(value=value, name=name)
|
|
558
|
-
elif type(value) is decimal.Decimal:
|
|
667
|
+
elif isinstance(value, decimal.Decimal):
|
|
559
668
|
return DecimalParameter(value=value, name=name)
|
|
669
|
+
elif isinstance(value, dict):
|
|
670
|
+
return MapParameter(value=value, name=name)
|
|
671
|
+
elif isinstance(value, Sequence) and not isinstance(value, str):
|
|
672
|
+
return ArrayParameter(value=value, name=name)
|
|
560
673
|
elif value is None:
|
|
561
674
|
return VoidParameter(value=value, name=name)
|
|
562
|
-
|
|
563
675
|
else:
|
|
564
676
|
raise NotSupportedError(
|
|
565
677
|
f"Could not infer parameter type from value: {value} - {type(value)} \n"
|
|
@@ -581,6 +693,8 @@ TDbsqlParameter = Union[
|
|
|
581
693
|
TimestampNTZParameter,
|
|
582
694
|
TinyIntParameter,
|
|
583
695
|
DecimalParameter,
|
|
696
|
+
ArrayParameter,
|
|
697
|
+
MapParameter,
|
|
584
698
|
]
|
|
585
699
|
|
|
586
700
|
|