databricks-sql-connector 3.1.2__tar.gz → 3.2.0__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-3.1.2 → databricks_sql_connector-3.2.0}/CHANGELOG.md +8 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/PKG-INFO +3 -3
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/pyproject.toml +3 -3
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/__init__.py +1 -1
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/oauth.py +1 -1
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/thrift_http_client.py +6 -7
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/cloudfetch/download_manager.py +49 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/utils.py +35 -2
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/_ddl.py +5 -3
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test_local/test_ddl.py +2 -1
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/LICENSE +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/README.md +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/__init__.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/py.typed +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/__init__.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/auth.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/authenticators.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/endpoint.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/oauth_http_handler.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/retry.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/client.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/cloudfetch/downloader.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/exc.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/experimental/__init__.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/experimental/oauth_persistence.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/parameters/__init__.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/parameters/native.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/parameters/py.typed +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/thrift_api/TCLIService/TCLIService-remote +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/thrift_api/TCLIService/TCLIService.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/thrift_api/TCLIService/__init__.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/thrift_api/TCLIService/constants.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/thrift_api/TCLIService/ttypes.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/thrift_api/__init__.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/thrift_backend.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/types.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/README.sqlalchemy.md +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/README.tests.md +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/__init__.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/_parse.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/_types.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/base.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/requirements.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/setup.cfg +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test/_extra.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test/_future.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test/_regression.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test/_unsupported.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test/conftest.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test/overrides/_componentreflectiontest.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test/overrides/_ctetest.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test/test_suite.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test_local/__init__.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test_local/conftest.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test_local/e2e/MOCK_DATA.xlsx +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test_local/e2e/test_basic.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test_local/test_parsing.py +0 -0
- {databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/test_local/test_types.py +0 -0
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
# 3.2.0 (2024-06-06)
|
|
4
|
+
|
|
5
|
+
- Update proxy authentication (databricks/databricks-sql-python#354 by @amir-haroun)
|
|
6
|
+
- Relax `pyarrow` pin (databricks/databricks-sql-python#389 by @dhirschfeld)
|
|
7
|
+
- Fix error logging in OAuth manager (databricks/databricks-sql-python#269 by @susodapop)
|
|
8
|
+
- SQLAlchemy: enable delta.feature.allowColumnDefaults for all tables (databricks/databricks-sql-python#343 by @dhirschfeld)
|
|
9
|
+
- Update `thrift` dependency (databricks/databricks-sql-python#397 by @m1n0)
|
|
10
|
+
|
|
3
11
|
# 3.1.2 (2024-04-18)
|
|
4
12
|
|
|
5
13
|
- Remove broken cookie code (#379)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: databricks-sql-connector
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.2.0
|
|
4
4
|
Summary: Databricks SQL Connector for Python
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Author: Databricks
|
|
@@ -22,10 +22,10 @@ Requires-Dist: numpy (>=1.23.4) ; python_version >= "3.11"
|
|
|
22
22
|
Requires-Dist: oauthlib (>=3.1.0,<4.0.0)
|
|
23
23
|
Requires-Dist: openpyxl (>=3.0.10,<4.0.0)
|
|
24
24
|
Requires-Dist: pandas (>=1.2.5,<2.2.0) ; python_version >= "3.8"
|
|
25
|
-
Requires-Dist: pyarrow (>=14.0.1,<
|
|
25
|
+
Requires-Dist: pyarrow (>=14.0.1,<17)
|
|
26
26
|
Requires-Dist: requests (>=2.18.1,<3.0.0)
|
|
27
27
|
Requires-Dist: sqlalchemy (>=2.0.21) ; extra == "sqlalchemy" or extra == "alembic"
|
|
28
|
-
Requires-Dist: thrift (>=0.16.0,<0.
|
|
28
|
+
Requires-Dist: thrift (>=0.16.0,<0.21.0)
|
|
29
29
|
Requires-Dist: urllib3 (>=1.26)
|
|
30
30
|
Project-URL: Bug Tracker, https://github.com/databricks/databricks-sql-python/issues
|
|
31
31
|
Project-URL: Homepage, https://github.com/databricks/databricks-sql-python
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "databricks-sql-connector"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.2.0"
|
|
4
4
|
description = "Databricks SQL Connector for Python"
|
|
5
5
|
authors = ["Databricks <databricks-sql-connector-maintainers@databricks.com>"]
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -10,11 +10,11 @@ include = ["CHANGELOG.md"]
|
|
|
10
10
|
|
|
11
11
|
[tool.poetry.dependencies]
|
|
12
12
|
python = "^3.8.0"
|
|
13
|
-
thrift = "
|
|
13
|
+
thrift = ">=0.16.0,<0.21.0"
|
|
14
14
|
pandas = [
|
|
15
15
|
{ version = ">=1.2.5,<2.2.0", python = ">=3.8" }
|
|
16
16
|
]
|
|
17
|
-
pyarrow = "
|
|
17
|
+
pyarrow = ">=14.0.1,<17"
|
|
18
18
|
|
|
19
19
|
lz4 = "^4.0.2"
|
|
20
20
|
requests = "^2.18.1"
|
{databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/oauth.py
RENAMED
|
@@ -125,7 +125,7 @@ class OAuthManager:
|
|
|
125
125
|
logger.info(f"Port {port} is in use")
|
|
126
126
|
last_error = e
|
|
127
127
|
except Exception as e:
|
|
128
|
-
logger.error("unexpected error", e)
|
|
128
|
+
logger.error("unexpected error: %s", e)
|
|
129
129
|
if self.redirect_port is None:
|
|
130
130
|
logger.error(
|
|
131
131
|
f"Tried all the ports {self.port_range} for oauth redirect, but can't find free port"
|
|
@@ -14,7 +14,7 @@ from http.client import HTTPResponse
|
|
|
14
14
|
from io import BytesIO
|
|
15
15
|
|
|
16
16
|
from urllib3 import HTTPConnectionPool, HTTPSConnectionPool, ProxyManager
|
|
17
|
-
|
|
17
|
+
from urllib3.util import make_headers
|
|
18
18
|
from databricks.sql.auth.retry import CommandType, DatabricksRetryPolicy
|
|
19
19
|
|
|
20
20
|
|
|
@@ -78,7 +78,7 @@ class THttpClient(thrift.transport.THttpClient.THttpClient):
|
|
|
78
78
|
self.proxy_uri: str = proxy
|
|
79
79
|
self.host = parsed.hostname
|
|
80
80
|
self.port = parsed.port
|
|
81
|
-
self.proxy_auth = self.
|
|
81
|
+
self.proxy_auth = self.basic_proxy_auth_headers(parsed)
|
|
82
82
|
else:
|
|
83
83
|
self.realhost = self.realport = self.proxy_auth = None
|
|
84
84
|
|
|
@@ -120,7 +120,7 @@ class THttpClient(thrift.transport.THttpClient.THttpClient):
|
|
|
120
120
|
proxy_manager = ProxyManager(
|
|
121
121
|
self.proxy_uri,
|
|
122
122
|
num_pools=1,
|
|
123
|
-
|
|
123
|
+
proxy_headers=self.proxy_auth,
|
|
124
124
|
)
|
|
125
125
|
self.__pool = proxy_manager.connection_from_host(
|
|
126
126
|
host=self.realhost,
|
|
@@ -167,7 +167,7 @@ class THttpClient(thrift.transport.THttpClient.THttpClient):
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
if self.using_proxy() and self.scheme == "http" and self.proxy_auth is not None:
|
|
170
|
-
headers
|
|
170
|
+
headers.update(self.proxy_auth)
|
|
171
171
|
|
|
172
172
|
if self.__custom_headers:
|
|
173
173
|
custom_headers = {key: val for key, val in self.__custom_headers.items()}
|
|
@@ -190,15 +190,14 @@ class THttpClient(thrift.transport.THttpClient.THttpClient):
|
|
|
190
190
|
self.headers = self.__resp.headers
|
|
191
191
|
|
|
192
192
|
@staticmethod
|
|
193
|
-
def
|
|
193
|
+
def basic_proxy_auth_headers(proxy):
|
|
194
194
|
if proxy is None or not proxy.username:
|
|
195
195
|
return None
|
|
196
196
|
ap = "%s:%s" % (
|
|
197
197
|
urllib.parse.unquote(proxy.username),
|
|
198
198
|
urllib.parse.unquote(proxy.password),
|
|
199
199
|
)
|
|
200
|
-
|
|
201
|
-
return "Basic " + six.ensure_str(cr)
|
|
200
|
+
return make_headers(proxy_basic_auth=ap)
|
|
202
201
|
|
|
203
202
|
def set_retry_command_type(self, value: CommandType):
|
|
204
203
|
"""Pass the provided CommandType to the retry policy"""
|
|
@@ -49,6 +49,11 @@ class ResultFileDownloadManager:
|
|
|
49
49
|
for link in t_spark_arrow_result_links:
|
|
50
50
|
if link.rowCount <= 0:
|
|
51
51
|
continue
|
|
52
|
+
logger.debug(
|
|
53
|
+
"ResultFileDownloadManager.add_file_links: start offset {}, row count: {}".format(
|
|
54
|
+
link.startRowOffset, link.rowCount
|
|
55
|
+
)
|
|
56
|
+
)
|
|
52
57
|
self.download_handlers.append(
|
|
53
58
|
ResultSetDownloadHandler(self.downloadable_result_settings, link)
|
|
54
59
|
)
|
|
@@ -88,6 +93,12 @@ class ResultFileDownloadManager:
|
|
|
88
93
|
|
|
89
94
|
# Check (and wait) for download status
|
|
90
95
|
if self._check_if_download_successful(handler):
|
|
96
|
+
link = handler.result_link
|
|
97
|
+
logger.debug(
|
|
98
|
+
"ResultFileDownloadManager: file found for row index {}: start {}, row count: {}".format(
|
|
99
|
+
next_row_offset, link.startRowOffset, link.rowCount
|
|
100
|
+
)
|
|
101
|
+
)
|
|
91
102
|
# Buffer should be empty so set buffer to new ArrowQueue with result_file
|
|
92
103
|
result = DownloadedFile(
|
|
93
104
|
handler.result_file,
|
|
@@ -97,15 +108,32 @@ class ResultFileDownloadManager:
|
|
|
97
108
|
self.download_handlers.pop(idx)
|
|
98
109
|
# Return True upon successful download to continue loop and not force a retry
|
|
99
110
|
return result
|
|
111
|
+
else:
|
|
112
|
+
logger.debug(
|
|
113
|
+
"ResultFileDownloadManager: cannot find file for row index {}".format(
|
|
114
|
+
next_row_offset
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
|
|
100
118
|
# Download was not successful for next download item, force a retry
|
|
101
119
|
self._shutdown_manager()
|
|
102
120
|
return None
|
|
103
121
|
|
|
104
122
|
def _remove_past_handlers(self, next_row_offset: int):
|
|
123
|
+
logger.debug(
|
|
124
|
+
"ResultFileDownloadManager: removing past handlers, current offset: {}".format(
|
|
125
|
+
next_row_offset
|
|
126
|
+
)
|
|
127
|
+
)
|
|
105
128
|
# Any link in which its start to end range doesn't include the next row to be fetched does not need downloading
|
|
106
129
|
i = 0
|
|
107
130
|
while i < len(self.download_handlers):
|
|
108
131
|
result_link = self.download_handlers[i].result_link
|
|
132
|
+
logger.debug(
|
|
133
|
+
"- checking result link: start {}, row count: {}, current offset: {}".format(
|
|
134
|
+
result_link.startRowOffset, result_link.rowCount, next_row_offset
|
|
135
|
+
)
|
|
136
|
+
)
|
|
109
137
|
if result_link.startRowOffset + result_link.rowCount > next_row_offset:
|
|
110
138
|
i += 1
|
|
111
139
|
continue
|
|
@@ -113,10 +141,16 @@ class ResultFileDownloadManager:
|
|
|
113
141
|
|
|
114
142
|
def _schedule_downloads(self):
|
|
115
143
|
# Schedule downloads for all download handlers if not already scheduled.
|
|
144
|
+
logger.debug("ResultFileDownloadManager: schedule downloads")
|
|
116
145
|
for handler in self.download_handlers:
|
|
117
146
|
if handler.is_download_scheduled:
|
|
118
147
|
continue
|
|
119
148
|
try:
|
|
149
|
+
logger.debug(
|
|
150
|
+
"- start: {}, row count: {}".format(
|
|
151
|
+
handler.result_link.startRowOffset, handler.result_link.rowCount
|
|
152
|
+
)
|
|
153
|
+
)
|
|
120
154
|
self.thread_pool.submit(handler.run)
|
|
121
155
|
except Exception as e:
|
|
122
156
|
logger.error(e)
|
|
@@ -124,13 +158,28 @@ class ResultFileDownloadManager:
|
|
|
124
158
|
handler.is_download_scheduled = True
|
|
125
159
|
|
|
126
160
|
def _find_next_file_index(self, next_row_offset: int):
|
|
161
|
+
logger.debug(
|
|
162
|
+
"ResultFileDownloadManager: trying to find file for row {}".format(
|
|
163
|
+
next_row_offset
|
|
164
|
+
)
|
|
165
|
+
)
|
|
127
166
|
# Get the handler index of the next file in order
|
|
128
167
|
next_indices = [
|
|
129
168
|
i
|
|
130
169
|
for i, handler in enumerate(self.download_handlers)
|
|
131
170
|
if handler.is_download_scheduled
|
|
171
|
+
# TODO: shouldn't `next_row_offset` be tested against the range, not just start row offset?
|
|
132
172
|
and handler.result_link.startRowOffset == next_row_offset
|
|
133
173
|
]
|
|
174
|
+
|
|
175
|
+
for i in next_indices:
|
|
176
|
+
link = self.download_handlers[i].result_link
|
|
177
|
+
logger.debug(
|
|
178
|
+
"- found file: start {}, row count {}".format(
|
|
179
|
+
link.startRowOffset, link.rowCount
|
|
180
|
+
)
|
|
181
|
+
)
|
|
182
|
+
|
|
134
183
|
return next_indices[0] if len(next_indices) > 0 else None
|
|
135
184
|
|
|
136
185
|
def _check_if_download_successful(self, handler: ResultSetDownloadHandler):
|
{databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/utils.py
RENAMED
|
@@ -156,6 +156,19 @@ class CloudFetchQueue(ResultSetQueue):
|
|
|
156
156
|
self.lz4_compressed = lz4_compressed
|
|
157
157
|
self.description = description
|
|
158
158
|
|
|
159
|
+
logger.debug(
|
|
160
|
+
"Initialize CloudFetch loader, row set start offset: {}, file list:".format(
|
|
161
|
+
start_row_offset
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
if result_links is not None:
|
|
165
|
+
for result_link in result_links:
|
|
166
|
+
logger.debug(
|
|
167
|
+
"- start row offset: {}, row count: {}".format(
|
|
168
|
+
result_link.startRowOffset, result_link.rowCount
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
|
|
159
172
|
self.download_manager = ResultFileDownloadManager(
|
|
160
173
|
self.max_download_threads, self.lz4_compressed
|
|
161
174
|
)
|
|
@@ -175,8 +188,10 @@ class CloudFetchQueue(ResultSetQueue):
|
|
|
175
188
|
pyarrow.Table
|
|
176
189
|
"""
|
|
177
190
|
if not self.table:
|
|
191
|
+
logger.debug("CloudFetchQueue: no more rows available")
|
|
178
192
|
# Return empty pyarrow table to cause retry of fetch
|
|
179
193
|
return self._create_empty_table()
|
|
194
|
+
logger.debug("CloudFetchQueue: trying to get {} next rows".format(num_rows))
|
|
180
195
|
results = self.table.slice(0, 0)
|
|
181
196
|
while num_rows > 0 and self.table:
|
|
182
197
|
# Get remaining of num_rows or the rest of the current table, whichever is smaller
|
|
@@ -190,6 +205,8 @@ class CloudFetchQueue(ResultSetQueue):
|
|
|
190
205
|
self.table = self._create_next_table()
|
|
191
206
|
self.table_row_index = 0
|
|
192
207
|
num_rows -= table_slice.num_rows
|
|
208
|
+
|
|
209
|
+
logger.debug("CloudFetchQueue: collected {} next rows".format(results.num_rows))
|
|
193
210
|
return results
|
|
194
211
|
|
|
195
212
|
def remaining_rows(self) -> pyarrow.Table:
|
|
@@ -214,11 +231,21 @@ class CloudFetchQueue(ResultSetQueue):
|
|
|
214
231
|
return results
|
|
215
232
|
|
|
216
233
|
def _create_next_table(self) -> Union[pyarrow.Table, None]:
|
|
234
|
+
logger.debug(
|
|
235
|
+
"CloudFetchQueue: Trying to get downloaded file for row {}".format(
|
|
236
|
+
self.start_row_index
|
|
237
|
+
)
|
|
238
|
+
)
|
|
217
239
|
# Create next table by retrieving the logical next downloaded file, or return None to signal end of queue
|
|
218
240
|
downloaded_file = self.download_manager.get_next_downloaded_file(
|
|
219
241
|
self.start_row_index
|
|
220
242
|
)
|
|
221
243
|
if not downloaded_file:
|
|
244
|
+
logger.debug(
|
|
245
|
+
"CloudFetchQueue: Cannot find downloaded file for row {}".format(
|
|
246
|
+
self.start_row_index
|
|
247
|
+
)
|
|
248
|
+
)
|
|
222
249
|
# None signals no more Arrow tables can be built from the remaining handlers if any remain
|
|
223
250
|
return None
|
|
224
251
|
arrow_table = create_arrow_table_from_arrow_file(
|
|
@@ -228,12 +255,18 @@ class CloudFetchQueue(ResultSetQueue):
|
|
|
228
255
|
# The server rarely prepares the exact number of rows requested by the client in cloud fetch.
|
|
229
256
|
# Subsequently, we drop the extraneous rows in the last file if more rows are retrieved than requested
|
|
230
257
|
if arrow_table.num_rows > downloaded_file.row_count:
|
|
231
|
-
|
|
232
|
-
return arrow_table.slice(0, downloaded_file.row_count)
|
|
258
|
+
arrow_table = arrow_table.slice(0, downloaded_file.row_count)
|
|
233
259
|
|
|
234
260
|
# At this point, whether the file has extraneous rows or not, the arrow table should have the correct num rows
|
|
235
261
|
assert downloaded_file.row_count == arrow_table.num_rows
|
|
236
262
|
self.start_row_index += arrow_table.num_rows
|
|
263
|
+
|
|
264
|
+
logger.debug(
|
|
265
|
+
"CloudFetchQueue: Found downloaded file, row count: {}, new start offset: {}".format(
|
|
266
|
+
arrow_table.num_rows, self.start_row_index
|
|
267
|
+
)
|
|
268
|
+
)
|
|
269
|
+
|
|
237
270
|
return arrow_table
|
|
238
271
|
|
|
239
272
|
def _create_empty_table(self) -> pyarrow.Table:
|
{databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/_ddl.py
RENAMED
|
@@ -16,13 +16,15 @@ class DatabricksIdentifierPreparer(compiler.IdentifierPreparer):
|
|
|
16
16
|
|
|
17
17
|
class DatabricksDDLCompiler(compiler.DDLCompiler):
|
|
18
18
|
def post_create_table(self, table):
|
|
19
|
-
post = " USING DELTA"
|
|
19
|
+
post = [" USING DELTA"]
|
|
20
20
|
if table.comment:
|
|
21
21
|
comment = self.sql_compiler.render_literal_value(
|
|
22
22
|
table.comment, sqltypes.String()
|
|
23
23
|
)
|
|
24
|
-
post
|
|
25
|
-
|
|
24
|
+
post.append("COMMENT " + comment)
|
|
25
|
+
|
|
26
|
+
post.append("TBLPROPERTIES('delta.feature.allowColumnDefaults' = 'enabled')")
|
|
27
|
+
return "\n".join(post)
|
|
26
28
|
|
|
27
29
|
def visit_unique_constraint(self, constraint, **kw):
|
|
28
30
|
logger.warning("Databricks does not support unique constraints")
|
|
@@ -79,7 +79,8 @@ class TestTableCommentDDL(DDLTestBase):
|
|
|
79
79
|
def test_create_table_with_comment(self, table_with_comment):
|
|
80
80
|
stmt = CreateTable(table_with_comment)
|
|
81
81
|
output = self.compile(stmt)
|
|
82
|
-
assert "USING DELTA
|
|
82
|
+
assert "USING DELTA" in output
|
|
83
|
+
assert "COMMENT 'foobar'" in output
|
|
83
84
|
|
|
84
85
|
def test_alter_table_add_comment(self, table_without_comment: Table):
|
|
85
86
|
table_without_comment.comment = "wireless mechanical keyboard"
|
|
File without changes
|
|
File without changes
|
{databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/auth/retry.py
RENAMED
|
File without changes
|
{databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/client.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sql/types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{databricks_sql_connector-3.1.2 → databricks_sql_connector-3.2.0}/src/databricks/sqlalchemy/base.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
|
|
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
|