Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions DESCRIPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ https://docs.snowflake.com/
Source code is also available at: https://github.com/snowflakedb/snowflake-connector-python

# Release Notes
- v4.2.1(TBD)
- Fixed a memory leak in `SnowflakeRestful.fetch()`.

- v4.2.0(December 17,2025)
- Added `SnowflakeCursor.stats` property to expose granular DML statistics (rows inserted, deleted, updated, and duplicates) for operations like CTAS where `rowcount` is insufficient.
- Added support for injecting SPCS service identifier token (`SPCS_TOKEN`) into login requests when present in SPCS containers.
Expand Down
54 changes: 27 additions & 27 deletions src/snowflake/connector/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,33 @@ def default(self, o):
return super().default(o)


class RetryCtx(TimeoutBackoffCtx):
def __init__(
self,
_include_retry_params: bool = False,
_include_retry_reason: bool = False,
**kwargs,
) -> None:
super().__init__(**kwargs)
self.retry_reason = 0
self._include_retry_params = _include_retry_params
self._include_retry_reason = _include_retry_reason

def add_retry_params(self, full_url: str) -> str:
if self._include_retry_params and self.current_retry_count > 0:
retry_params = {
"clientStartTime": self._start_time_millis,
"retryCount": self.current_retry_count,
}
if self._include_retry_reason:
retry_params.update({"retryReason": self.retry_reason})
suffix = urlencode(retry_params)
sep = "&" if urlparse(full_url).query else "?"
return full_url + sep + suffix
else:
return full_url


class SnowflakeRestful:
"""Snowflake Restful class."""

Expand Down Expand Up @@ -828,33 +855,6 @@ def fetch(
**kwargs,
) -> dict[Any, Any]:
"""Carry out API request with session management."""

class RetryCtx(TimeoutBackoffCtx):
def __init__(
self,
_include_retry_params: bool = False,
_include_retry_reason: bool = False,
**kwargs,
) -> None:
super().__init__(**kwargs)
self.retry_reason = 0
self._include_retry_params = _include_retry_params
self._include_retry_reason = _include_retry_reason

def add_retry_params(self, full_url: str) -> str:
if self._include_retry_params and self.current_retry_count > 0:
retry_params = {
"clientStartTime": self._start_time_millis,
"retryCount": self.current_retry_count,
}
if self._include_retry_reason:
retry_params.update({"retryReason": self.retry_reason})
suffix = urlencode(retry_params)
sep = "&" if urlparse(full_url).query else "?"
return full_url + sep + suffix
else:
return full_url

include_retry_reason = self._connection._enable_retry_reason_in_query_response
include_retry_params = kwargs.pop("_include_retry_params", False)

Expand Down
Loading