- Notifications
You must be signed in to change notification settings - Fork126
Add optional telemetry support to the python connector#628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
Uh oh!
There was an error while loading.Please reload this page.
Merged
Changes fromall commits
Commits
Show all changes
264 commits Select commitHold shift + click to select a range
5fd729a [PECO-197] Support Python 3.10 (#31)
dbaxa5612e5f Update changelog and bump to v2.0.4 (#34)
f1241ba Bump to 2.0.5-dev on main (#35)
6bafb9d On Pypi, display the "Project Links" sidebar. (#36)
afcb0f0 [ES-402013] Close cursors before closing connection (#38)
af945aa Bump version to 2.0.5 and improve CHANGELOG (#40)
441a6ae fix dco issue
moderakh29fe6b4 fix dco issue
moderakh06d9df8 Merge pull request #42 from moderakh/fix-dco-issue
moderakhcf3130e dco tunning
moderakh4387f93 dco tunning
moderakh285e516 Merge pull request #43 from moderakh/dco-tunning
moderakhea0f076 Github workflows: run checks on pull requests from forks (#47)
616a5c8 OAuth implementation (#15)
moderakhe39d294 Automate deploys to Pypi (#48)
1ea2fe0 [PECO-205] Add functional examples (#52)
3638fa2 Bump version to 2.1.0 (#54)
1a4cf4b [SC-110400] Enabling compression in Python SQL Connector (#49)
mohitsingla-db8d6d47f Add tests for parameter sanitisation / escaping (#46)
3d3c692 Bump thrift dependency to 0.16.0 (#65)
5cbfcac Bump version to 2.2.0 (#66)
c6e573c Support Python 3.11 (#60)
7c53b76 Bump version to 2.2.1 (#70)
4f221b3 Add none check on _oauth_persistence in DatabricksOAuthProvider (#71)
jackyhu-dbcfa38a1 Support custom oauth client id and redirect port (#75)
jackyhu-db2f2a761 Bump version to 2.2.2 (#76)
jackyhu-dbdef5e0e Merge staging ingestion into main (#78)
3cc9393 Bump version to 2.3.0 and update changelog (#80)
aa55a6e Add pkgutil-style for the package (#84)
lu-wang-dlce158cb Add SQLAlchemy Dialect (#57)
0ed7e53 Bump to version 2.4.0(#89)
9a06d6c Fix syntax in examples in root readme. (#92)
shea-parkes20e789f Less strict numpy and pyarrow dependencies (#90)
3a60599 Update example in docstring so query output is valid Spark SQL (#95)
e627649 Bump version to 2.4.1 (#96)
c43eaf8 Update CODEOWNERS (#97)
moderakhb0b6abd Add Andre to CODEOWNERS (#98)
yunbodeng-dbf440791 Add external auth provider + example (#101)
andrefurlan-db5f247e5 Retry on connection timeout (#103)
andrefurlan-dbc1d9510 [PECO-244] Make http proxies work (#81)
c5731d8 Bump to version 2.5.0 (#104)
7087236 Fix changelog release date for version 2.5.0
61b6911 Relax sqlalchemy requirement (#113)
b5ab608 Update to version 2.5.1 (#114)
ad6fbd9 Fix SQLAlchemy timestamp converter + docs (#117)
73108e2 Relax pandas and alembic requirements (#119)
7d85814 Bump to version 2.5.2 (#118)
4077c7f Use urllib3 for thrift transport + reuse http connections (#131)
cdf1857 Default socket timeout to 15 min (#137)
mattdeekay5539b26 Bump version to 2.6.0 (#139)
728e2b1 Fix: some thrift RPCs failed with BadStatusLine (#141)
eada549 Bump version to 2.6.1 (#142)
cdc50d2 [ES-706907] Retry GetOperationStatus for http errors (#145)
2904788 Bump version to 2.6.2 (#147)
782ebb6 [PECO-626] Support OAuth flow for Databricks Azure (#86)
jackyhu-dbb7ada62 Use a separate logger for unsafe thrift responses (#153)
c6cf88f Improve e2e test development ergonomics (#155)
95cf95b Don't raise exception when closing a stale Thrift session (#159)
3680a0f Bump to version 2.7.0 (#161)
ba2cd84 Cloud Fetch download handler (#127)
mattdeekay061c763 Cloud Fetch download manager (#146)
mattdeekaye8fc63b Cloud fetch queue and integration (#151)
mattdeekay813c73c Cloud Fetch e2e tests (#154)
mattdeekayd3f0513 Update changelog for cloudfetch (#172)
mattdeekay6786933 Improve sqlalchemy backward compatibility with 1.3.24 (#173)
203735f OAuth: don't override auth headers with contents of .netrc file (#122)
bd08f58 Fix proxy connection pool creation (#158)
sebbegg9508c4f Relax pandas dependency constraint to allow ^2.0.0 (#164)
itsdani8140be9 Use hex string version of operation ID instead of bytes (#170)
850235c SQLAlchemy: fix has_table so it honours schema= argument (#174)
4c766ef Fix socket timeout test (#144)
mattdeekay7fe5ddf Disable non_native_boolean_check_constraint (#120)
bkyryliuk50dfd93 Remove unused import for SQLAlchemy 2 compatibility (#128)
WilliamGentry4b0b8bd Bump version to 2.8.0 (#178)
f07df30 Fix typo in python README quick start example (#186)
dbarrundia-tiger683e03c Configure autospec for mocked Client objects (#188)
d168598 Use urllib3 for retries (#182)
fcfe8f4 Bump version to 2.9.0 (#189)
972f7cc Explicitly add urllib3 dependency (#191)
jacobus-herman1c3ce1e Bump to 2.9.1 (#195)
667f719 Make backwards compatible with urllib3~=1.0 (#197)
ddf8a5f Convenience improvements to v3 retry logic (#199)
56c7d41 Bump version to 2.9.2 (#201)
312c7b9 Github Actions Fix: poetry install fails for python 3.7 tests (#208)
9bc0d3e Make backwards compatible with urllib3~=1.0 [Follow up #197] (#206)
33390db Bump version to 2.9.3 (#209)
e176f65 Add note to sqlalchemy example: IDENTITY isn't supported yet (#212)
854c56f [PECO-1029] Updated thrift compiler version (#216)
nithinkdb0d1d7d8 [PECO-1055] Updated thrift defs to allow Tsparkparameters (#220)
nithinkdbc32b71a Update changelog to indicate that 2.9.1 and 2.9.2 have been yanked. (…
4588ff3 Fix changelog typo: _enable_v3_retries (#225)
b9bd2a1 Introduce SQLAlchemy reusable dialog tests (#125)
unj1m329b7ee [PECO-1026] Add Parameterized Query support to Python (#217)
nithinkdb9489087 Parameterized queries: Add e2e tests for inference (#227)
b94f59e [PECO-1109] Parameterized Query: add suport for inferring decimal typ…
9592098 SQLAlchemy 2: reorganise dialect files into a single directory (#231)
84a6cbc [PECO-1083] Updated thrift files and added check for protocol version…
nithinkdb9d93e1b [PECO-840] Port staging ingestion behaviour to new UC Volumes (#235)
ef5fbda Query parameters: implement support for binding NoneType parameters (…
f138703 SQLAlchemy 2: Bump dependency version and update e2e tests for existi…
04c99e4 Revert "[PECO-1083] Updated thrift files and added check for protocol…
cbe21e5 SQLAlchemy 2: add type compilation for all CamelCase types (#238)
77a8886 SQLAlchemy 2: add type compilation for uppercase types (#240)
4a70379 SQLAlchemy 2: Stop skipping all type tests (#242)
0e791ba [PECO-1134] v3 Retries: allow users to bound the number of redirects …
f198a25 Parameters: Add type inference for BIGINT and TINYINT types (#246)
d975611 SQLAlchemy 2: Stop skipping some non-type tests (#247)
a596776 SQLAlchemy 2: implement and refactor schema reflection methods (#249)
16a5106 Add GovCloud domain into AWS domains (#252)
jackyhu-dbca84f1a SQLAlchemy 2: Refactor __init__.py into base.py (#250)
45c6073 SQLAlchemy 2: Finish implementing all of ComponentReflectionTest (#251)
3a8b4ea SQLAlchemy 2: Finish marking all tests in the suite (#253)
8a0ec56 SQLAlchemy 2: Finish organising compliance test suite (#256)
4905952 SQLAlchemy 2: Fix failing mypy checks from development (#257)
7444425 Enable cloud fetch by default (#258)
9a8ac88 [PECO-1137] Reintroduce protocol checking to Python test fw (#248)
nithinkdb6bc7413 sqla2 clean-up: make sqlalchemy optional and don't mangle the user-ag…
95e5595 SQLAlchemy 2: Add support for TINYINT (#265)
c69d886 Add OAuth M2M example (#266)
jackyhu-db012f6ed Native Parameters: reintroduce INLINE approach with tests (#267)
b09ff05 Document behaviour of executemany (#213)
martinitusfd4336e SQLAlchemy 2: Expose TIMESTAMP and TIMESTAMP_NTZ types to users (#268)
f3081a5 Drop Python 3.7 as a supported version (#270)
ff51bfb GH Workflows: remove Python 3.7 from the matrix for _all_ workflows (…
ca000db Add README and updated example for SQLAlchemy usage (#273)
6aa7890 Rewrite native parameter implementation with docs and tests (#281)
bf084fe Enable v3 retries by default (#282)
23b51c9 security: bump pyarrow dependency to 14.0.1 (#284)
5a1acdc Bump package version to 3.0.0 (#285)
e768d48 Fix docstring about default parameter approach (#287)
Falydoor505a522 [PECO-1286] Add tests for complex types in query results (#293)
5c01874 sqlalchemy: fix deprecation warning for dbapi classmethod (#294)
2027145 [PECO-1297] sqlalchemy: fix: can't read columns for tables containing…
9e963a0 Prepared 3.0.1 release (#297)
f703d81 Make contents of `__init__.py` equal across projects (#304)
pieternbdd2cb6 Fix URI construction in ThriftBackend (#303)
NodeJSmith00b8d3e [sqlalchemy] Add table and column comment support (#329)
a6e81ed Pin pandas and urllib3 versions to fix runtime issues in dbt-databric…
benc-dbc89da23 SQLAlchemy: TINYINT types didn't reflect properly (#315)
TimTheinAtTabs6482c76 [PECO-1435] Restore `tests.py` to the test suite (#331)
d20d931 Bump to version 3.0.2 (#335)
e3e0f49 Update some outdated OAuth comments (#339)
jackyhu-db456fec5 Redact the URL query parameters from the urllib3.connectionpool logs …
mkazia-db01cfc66 Bump to version 3.0.3 (#344)
jackyhu-db9ff99b8 [PECO-1411] Support Databricks OAuth on GCP (#338)
jackyhu-db072ef2c [PECO-1414] Support Databricks native OAuth in Azure (#351)
jackyhu-dbf52c658 Prep for Test Automation (#352)
benc-dbb1bd792 Update code owners (#345)
yunbodeng-db70f3738 Reverting retry behavior on 429s/503s to how it worked in 2.9.3 (#349)
benc-db912127c Bump to version 3.1.0 (#358)
jackyhu-db1ed5c9d [PECO-1440] Expose current query id on cursor object (#364)
kravets-levko1577506 Add a default for retry after (#371)
benc-dbe01ef74 Fix boolean literals (#357)
aholyoke7cfd6f6 Don't retry network requests that fail with code 403 (#373)
6cf12fb Bump to 3.1.1 (#374)
benc-db02d08d6 Fix cookie setting (#379)
benc-db4122597 Fixing a couple type problems: how I would address most of #381 (#382)
wyattscarpenter3631e55 fix the return types of the classes' __enter__ functions (#384)
wyattscarpenter4b1b7ad Add Kravets Levko to codeowners (#386)
kravets-levkof2d927b Prepare for 3.1.2 (#387)
benc-db2d2f8f7 Update the proxy authentication (#354)
amir-haround9802a8 Fix failing tests (#392)
kravets-levko9c158d9 Relax `pyarrow` pin (#389)
dhirschfeld0400bdb Fix log error in oauth.py (#269)
susodapop683a033 Enable `delta.feature.allowColumnDefaults` for all tables (#343)
dhirschfeld3a68fa8 Fix SQLAlchemy tests (#393)
kravets-levko94a2597 Add more debug logging for CloudFetch (#395)
kravets-levko3a50d70 Update Thrift package (#397)
m1n037d8a7b Prepare release 3.2.0 (#396)
kravets-levko0017b0c move py.typed to correct places (#403)
wyattscarpenter2a1875a Upgrade mypy (#406)
wyattscarpenter9fd4a25 Do not retry failing requests with status code 401 (#408)
Hodnebo74bcc86 [PECO-1715] Remove username/password (BasicAuth) auth option (#409)
jackyhu-dbe7c0c06 [PECO-1751] Refactor CloudFetch downloader: handle files sequentially…
kravets-levko677483d Fix CloudFetch retry policy to be compatible with all `urllib3` versi…
kravets-levko512efca Disable SSL verification for CloudFetch links (#414)
kravets-levko1a1497b Prepare relese 3.3.0 (#415)
kravets-levkob751088 Fix pandas 2.2.2 support (#416)
kfollesdal4959197 [PECO-1801] Make OAuth as the default authenticator if no authenticat…
jackyhu-db7467860 [PECO-1857] Use SSL options with HTTPS connection pool (#425)
kravets-levko2de70ec Prepare release v3.4.0 (#430)
kravets-levko2675099 [PECO-1926] Create a non pyarrow flow to handle small results for the…
jprakash-dbc755ecc [PECO-1961] On non-retryable error, ensure PySQL includes useful info…
shivam26801a44d91 Reformatted all the files using black (#448)
jprakash-db92dff6c Prepare release v3.5.0 (#457)
jackyhu-dbb4bcf8a [PECO-2051] Add custom auth headers into cloud fetch request (#460)
jackyhu-db28a0fe6 Prepare release 3.6.0 (#461)
jackyhu-db82efe73 [ PECO - 1768 ] PySQL: adjust HTTP retry logic to align with Go and N…
jprakash-db5e11582 [ PECO-2065 ] Create the async execution flow for the PySQL Connector…
jprakash-dba9ae775 Fix for check_types github action failing (#472)
jprakash-dbc251d91 Remove upper caps on dependencies (#452)
arredond8a63786 Updated the doc to specify native parameters in PUT operation is not …
jprakash-db9d6813b Incorrect rows in inline fetch result (#479)
jprakash-db8468a2b Bumped up to version 3.7.0 (#482)
jprakash-dbaa673ac PySQL Connector split into connector and sqlalchemy (#444)
jprakash-dbfd7f85c Removed CI CD for python3.8 (#490)
jprakash-dbb20c55b Added CI CD upto python 3.12 (#491)
jprakash-dbd61a964 Merging changes from v3.7.1 release (#488)
jprakash-dbefd82fb Bumped up to version 4.0.0 (#493)
jprakash-dbed19388 Updated action's version (#455)
newwingbirdf8f9f4e Support Python 3.13 and update deps (#510)
dhirschfeld0e51281 Improve debugging + fix PR review template (#514)
samikshya-db9665a74 Forward porting all changes into 4.x.x. uptil v3.7.3 (#529)
jprakash-dbb24ddd7 Updated the CODEOWNERS (#531)
jprakash-db0013ba4 Add version check for urllib3 in backoff calculation (#526)
shivam2680851d23b [ES-1372353] make user_agent_header part of public API (#530)
shivam2680f321b49 Updates runner used to run DCO check to use databricks-protected-runn…
madhav-dbb000892 Support multiple timestamp formats in non arrow flow (#533)
jprakash-db2553bcf prepare release for v4.0.1 (#534)
shivam2680078f41b Relaxed bound for python-dateutil (#538)
jprakash-dbadc2c86 Bumped up the version for 4.0.2 (#539)
jprakash-dbf9fe172 Added example for async execute query (#537)
jprakash-db6f99449 Added urllib3 version check (#547)
jprakash-db6790dca Bump version to 4.0.3 (#549)
jprakash-db3a4d6d3 Cleanup fields as they might be deprecated/removed/change in the futu…
vikrantpuppala557bb68 Refactor decimal conversion in PyArrow tables to use direct casting (…
jayantsing-db9a3f946 [PECOBLR-361] convert column table to arrow if arrow present (#551)
shivam26807233e4e Update CODEOWNERS (#562)
jprakash-dbb88eba0 Enhance Cursor close handling and context manager exception managemen…
madhav-db14c8a7e PECOBLR-86 improve logging on python driver (#556)
saishreeeee8013a0d Update github actions run conditions (#569)
jprakash-dbfdd385f Added classes required for telemetry (#572)
saishreeeee9dc7d52 E2E POC for python telemetry for connect logs (#581)
saishreeeeece2cc1a Merge branch 'main' into HEAD
saishreeeee99ec875 Merge branch 'main' into telemetry
saishreeeeecf89ce3 Added functionality for export of failure logs (#591)
saishreeeee380b0b9 bugfix: stalling test issue (close in TelemetryClientFactory) (#609)
saishreeeee23d8881 Updated tests (#614)
jprakash-db350e745 Add test to check thrift field IDs (#602)
vikrantpuppala4a2356d Revert "Enhance Cursor close handling and context manager exception m…
madhav-db97df72e Bump version to 4.0.5 (#615)
madhav-db6748c2c Merge branch 'main' into telemetry
saishreeeee0dfe0f4 Add functionality for export of latency logs via telemetry (#608)
saishreeeee10375a8 Merge branch 'main' into telemetry
saishreeeee8c0f474 Revert "Merge branch 'main' into telemetry"
saishreeeee13ebfb4 Revert "Revert "Merge branch 'main' into telemetry""
saishreeeee79db09f workflows
saishreeeee5005561 -
saishreeeee96813ad changed enums to follow proto, get_extractor returns None if not Curs…
saishreeeee846e701 formatting
saishreeeeed939fe3 auth mech test fix
saishreeeeecac9c7a import logging
saishreeeee37a8803 logger.error to logger.debug
saishreeeee932ee0d logging, test fixture
saishreeeeeeb95bcc noop telemetry client lock
saishreeeee85bfe06 JsonSerializableMixin, TelemetryRequest
saishreeeeec74b0e5 timeout 900, TelemetryResponse, BaseTelemetryClient in utils
saishreeeee6afa037 TelemetryResponse, send_count
saishreeeee341991d get telemetry client
saishreeeeec9c8793 get telemetry client
saishreeeeeFile filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
151 changes: 124 additions & 27 deletionssrc/databricks/sql/client.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,5 @@ | ||
| import time | ||
| from typing import Dict, Tuple, List, Optional, Any, Union, Sequence | ||
| import pandas | ||
| try: | ||
| @@ -19,6 +18,9 @@ | ||
| OperationalError, | ||
| SessionAlreadyClosedError, | ||
| CursorAlreadyClosedError, | ||
| InterfaceError, | ||
| NotSupportedError, | ||
| ProgrammingError, | ||
| ) | ||
| from databricks.sql.thrift_api.TCLIService import ttypes | ||
| from databricks.sql.thrift_backend import ThriftBackend | ||
| @@ -50,7 +52,17 @@ | ||
| TSparkParameter, | ||
| TOperationState, | ||
| ) | ||
| from databricks.sql.telemetry.telemetry_client import ( | ||
| TelemetryHelper, | ||
| TelemetryClientFactory, | ||
| ) | ||
| from databricks.sql.telemetry.models.enums import DatabricksClientType | ||
| from databricks.sql.telemetry.models.event import ( | ||
| DriverConnectionParameters, | ||
| HostDetails, | ||
| ) | ||
| from databricks.sql.telemetry.latency_logger import log_latency | ||
| from databricks.sql.telemetry.models.enums import StatementType | ||
| logger = logging.getLogger(__name__) | ||
| @@ -234,6 +246,12 @@ def read(self) -> Optional[OAuthToken]: | ||
| server_hostname, **kwargs | ||
| ) | ||
| self.server_telemetry_enabled = True | ||
| self.client_telemetry_enabled = kwargs.get("enable_telemetry", False) | ||
saishreeeee marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| self.telemetry_enabled = ( | ||
| self.client_telemetry_enabled and self.server_telemetry_enabled | ||
| ) | ||
| user_agent_entry = kwargs.get("user_agent_entry") | ||
| if user_agent_entry is None: | ||
| user_agent_entry = kwargs.get("_user_agent_entry") | ||
| @@ -289,6 +307,31 @@ def read(self) -> Optional[OAuthToken]: | ||
| kwargs.get("use_inline_params", False) | ||
| ) | ||
| TelemetryClientFactory.initialize_telemetry_client( | ||
| telemetry_enabled=self.telemetry_enabled, | ||
| session_id_hex=self.get_session_id_hex(), | ||
| auth_provider=auth_provider, | ||
| host_url=self.host, | ||
| ) | ||
| self._telemetry_client = TelemetryClientFactory.get_telemetry_client( | ||
| session_id_hex=self.get_session_id_hex() | ||
| ) | ||
| driver_connection_params = DriverConnectionParameters( | ||
| http_path=http_path, | ||
| mode=DatabricksClientType.THRIFT, | ||
| host_info=HostDetails(host_url=server_hostname, port=self.port), | ||
| auth_mech=TelemetryHelper.get_auth_mechanism(auth_provider), | ||
| auth_flow=TelemetryHelper.get_auth_flow(auth_provider), | ||
| socket_timeout=kwargs.get("_socket_timeout", None), | ||
| ) | ||
| self._telemetry_client.export_initial_telemetry_log( | ||
| driver_connection_params=driver_connection_params, | ||
| user_agent=useragent_header, | ||
| ) | ||
| def _set_use_inline_params_with_warning(self, value: Union[bool, str]): | ||
| """Valid values are True, False, and "silent" | ||
| @@ -376,7 +419,10 @@ def cursor( | ||
| Will throw an Error if the connection has been closed. | ||
| """ | ||
| if not self.open: | ||
| raise InterfaceError( | ||
| "Cannot create cursor from closed connection", | ||
| session_id_hex=self.get_session_id_hex(), | ||
| ) | ||
| cursor = Cursor( | ||
| self, | ||
| @@ -419,12 +465,17 @@ def _close(self, close_cursors=True) -> None: | ||
| self.open = False | ||
| TelemetryClientFactory.close(self.get_session_id_hex()) | ||
| def commit(self): | ||
| """No-op because Databricks does not support transactions""" | ||
| pass | ||
| def rollback(self): | ||
| raise NotSupportedError( | ||
| "Transactions are not supported on Databricks", | ||
| session_id_hex=self.get_session_id_hex(), | ||
| ) | ||
| class Cursor: | ||
| @@ -469,7 +520,10 @@ def __iter__(self): | ||
| for row in self.active_result_set: | ||
| yield row | ||
| else: | ||
| raise ProgrammingError( | ||
| "There is no active result set", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| def _determine_parameter_approach( | ||
| self, params: Optional[TParameterCollection] | ||
| @@ -606,7 +660,10 @@ def _close_and_clear_active_result_set(self): | ||
| def _check_not_closed(self): | ||
| if not self.open: | ||
| raise InterfaceError( | ||
| "Attempting operation on closed cursor", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| def _handle_staging_operation( | ||
| self, staging_allowed_local_path: Union[None, str, List[str]] | ||
| @@ -623,8 +680,9 @@ def _handle_staging_operation( | ||
| elif isinstance(staging_allowed_local_path, type(list())): | ||
| _staging_allowed_local_paths = staging_allowed_local_path | ||
| else: | ||
| raise ProgrammingError( | ||
| "You must provide at least one staging_allowed_local_path when initialising a connection to perform ingestion commands", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| abs_staging_allowed_local_paths = [ | ||
| @@ -652,8 +710,9 @@ def _handle_staging_operation( | ||
| else: | ||
| continue | ||
| if not allow_operation: | ||
| raise ProgrammingError( | ||
| "Local file operations are restricted to paths within the configured staging_allowed_local_path", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| # May be real headers, or could be json string | ||
| @@ -681,11 +740,13 @@ def _handle_staging_operation( | ||
| handler_args.pop("local_file") | ||
| return self._handle_staging_remove(**handler_args) | ||
| else: | ||
| raiseProgrammingError( | ||
| f"Operation {row.operation} is not supported. " | ||
| + "Supported operations are GET, PUT, and REMOVE", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| @log_latency(StatementType.SQL) | ||
| def _handle_staging_put( | ||
| self, presigned_url: str, local_file: str, headers: Optional[dict] = None | ||
| ): | ||
| @@ -695,7 +756,10 @@ def _handle_staging_put( | ||
| """ | ||
| if local_file is None: | ||
| raise ProgrammingError( | ||
| "Cannot perform PUT without specifying a local_file", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| with open(local_file, "rb") as fh: | ||
| r = requests.put(url=presigned_url, data=fh, headers=headers) | ||
| @@ -711,8 +775,9 @@ def _handle_staging_put( | ||
| # fmt: on | ||
| if r.status_code not in [OK, CREATED, NO_CONTENT, ACCEPTED]: | ||
| raise OperationalError( | ||
| f"Staging operation over HTTP was unsuccessful: {r.status_code}-{r.text}", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| if r.status_code == ACCEPTED: | ||
| @@ -721,6 +786,7 @@ def _handle_staging_put( | ||
| + "but not yet applied on the server. It's possible this command may fail later." | ||
| ) | ||
| @log_latency(StatementType.SQL) | ||
| def _handle_staging_get( | ||
| self, local_file: str, presigned_url: str, headers: Optional[dict] = None | ||
| ): | ||
| @@ -730,20 +796,25 @@ def _handle_staging_get( | ||
| """ | ||
| if local_file is None: | ||
| raise ProgrammingError( | ||
| "Cannot perform GET without specifying a local_file", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| r = requests.get(url=presigned_url, headers=headers) | ||
| # response.ok verifies the status code is not between 400-600. | ||
| # Any 2xx or 3xx will evaluate r.ok == True | ||
| if not r.ok: | ||
| raise OperationalError( | ||
| f"Staging operation over HTTP was unsuccessful: {r.status_code}-{r.text}", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| with open(local_file, "wb") as fp: | ||
| fp.write(r.content) | ||
| @log_latency(StatementType.SQL) | ||
| def _handle_staging_remove( | ||
| self, presigned_url: str, headers: Optional[dict] = None | ||
| ): | ||
| @@ -752,10 +823,12 @@ def _handle_staging_remove( | ||
| r = requests.delete(url=presigned_url, headers=headers) | ||
| if not r.ok: | ||
| raise OperationalError( | ||
| f"Staging operation over HTTP was unsuccessful: {r.status_code}-{r.text}", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| @log_latency(StatementType.QUERY) | ||
| def execute( | ||
| self, | ||
| operation: str, | ||
| @@ -846,6 +919,7 @@ def execute( | ||
| return self | ||
| @log_latency(StatementType.QUERY) | ||
| def execute_async( | ||
| self, | ||
| operation: str, | ||
| @@ -951,8 +1025,9 @@ def get_async_execution_result(self): | ||
| return self | ||
| else: | ||
| raise OperationalError( | ||
| f"get_execution_result failed with Operation status {operation_state}", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| def executemany(self, operation, seq_of_parameters): | ||
| @@ -970,6 +1045,7 @@ def executemany(self, operation, seq_of_parameters): | ||
| self.execute(operation, parameters) | ||
| return self | ||
| @log_latency(StatementType.METADATA) | ||
| def catalogs(self) -> "Cursor": | ||
| """ | ||
| Get all available catalogs. | ||
| @@ -993,6 +1069,7 @@ def catalogs(self) -> "Cursor": | ||
| ) | ||
| return self | ||
| @log_latency(StatementType.METADATA) | ||
| def schemas( | ||
| self, catalog_name: Optional[str] = None, schema_name: Optional[str] = None | ||
| ) -> "Cursor": | ||
| @@ -1021,6 +1098,7 @@ def schemas( | ||
| ) | ||
| return self | ||
| @log_latency(StatementType.METADATA) | ||
| def tables( | ||
| self, | ||
| catalog_name: Optional[str] = None, | ||
| @@ -1056,6 +1134,7 @@ def tables( | ||
| ) | ||
| return self | ||
| @log_latency(StatementType.METADATA) | ||
| def columns( | ||
| self, | ||
| catalog_name: Optional[str] = None, | ||
| @@ -1102,7 +1181,10 @@ def fetchall(self) -> List[Row]: | ||
| if self.active_result_set: | ||
| return self.active_result_set.fetchall() | ||
| else: | ||
| raise ProgrammingError( | ||
| "There is no active result set", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| def fetchone(self) -> Optional[Row]: | ||
| """ | ||
| @@ -1116,7 +1198,10 @@ def fetchone(self) -> Optional[Row]: | ||
| if self.active_result_set: | ||
| return self.active_result_set.fetchone() | ||
| else: | ||
| raise ProgrammingError( | ||
| "There is no active result set", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| def fetchmany(self, size: int) -> List[Row]: | ||
| """ | ||
| @@ -1138,21 +1223,30 @@ def fetchmany(self, size: int) -> List[Row]: | ||
| if self.active_result_set: | ||
| return self.active_result_set.fetchmany(size) | ||
| else: | ||
| raise ProgrammingError( | ||
| "There is no active result set", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| def fetchall_arrow(self) -> "pyarrow.Table": | ||
| self._check_not_closed() | ||
| if self.active_result_set: | ||
| return self.active_result_set.fetchall_arrow() | ||
| else: | ||
| raise ProgrammingError( | ||
| "There is no active result set", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| def fetchmany_arrow(self, size) -> "pyarrow.Table": | ||
| self._check_not_closed() | ||
| if self.active_result_set: | ||
| return self.active_result_set.fetchmany_arrow(size) | ||
| else: | ||
| raise ProgrammingError( | ||
| "There is no active result set", | ||
| session_id_hex=self.connection.get_session_id_hex(), | ||
| ) | ||
| def cancel(self) -> None: | ||
| """ | ||
| @@ -1455,6 +1549,7 @@ def fetchall_columnar(self): | ||
| return results | ||
| @log_latency() | ||
| def fetchone(self) -> Optional[Row]: | ||
| """ | ||
| Fetch the next row of a query result set, returning a single sequence, | ||
| @@ -1471,6 +1566,7 @@ def fetchone(self) -> Optional[Row]: | ||
| else: | ||
| return None | ||
| @log_latency() | ||
| def fetchall(self) -> List[Row]: | ||
| """ | ||
| Fetch all (remaining) rows of a query result, returning them as a list of rows. | ||
| @@ -1480,6 +1576,7 @@ def fetchall(self) -> List[Row]: | ||
| else: | ||
| return self._convert_arrow_table(self.fetchall_arrow()) | ||
| @log_latency() | ||
| def fetchmany(self, size: int) -> List[Row]: | ||
| """ | ||
| Fetch the next set of rows of a query result, returning a list of rows. | ||
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.