snowflake-connector-python 5.2.0__cp315-cp315-win_amd64.whl

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.
Files changed (204) hide show
  1. snowflake/connector/__init__.py +148 -0
  2. snowflake/connector/_common/__init__.py +0 -0
  3. snowflake/connector/_common/extras.py +134 -0
  4. snowflake/connector/_common/telemetry.py +221 -0
  5. snowflake/connector/_common/wif_util.py +92 -0
  6. snowflake/connector/_core/sf_core_python.cp315-win_amd64.pyd +0 -0
  7. snowflake/connector/_core/sf_core_python.pyi +79 -0
  8. snowflake/connector/_internal/__init__.py +6 -0
  9. snowflake/connector/_internal/_private_key_helper.py +31 -0
  10. snowflake/connector/_internal/api_client/__init__.py +93 -0
  11. snowflake/connector/_internal/api_client/bridge.py +41 -0
  12. snowflake/connector/_internal/api_client/client_api.py +976 -0
  13. snowflake/connector/_internal/arrow.py +47 -0
  14. snowflake/connector/_internal/arrow_context.py +240 -0
  15. snowflake/connector/_internal/arrow_stream_async.py +266 -0
  16. snowflake/connector/_internal/arrow_stream_iterator.cp311-win_amd64.pyd +0 -0
  17. snowflake/connector/_internal/arrow_stream_iterator.cp312-win_amd64.pyd +0 -0
  18. snowflake/connector/_internal/arrow_stream_iterator.cp313-win_amd64.pyd +0 -0
  19. snowflake/connector/_internal/arrow_stream_iterator.cp314-win_amd64.pyd +0 -0
  20. snowflake/connector/_internal/arrow_stream_iterator.cp314t-win_amd64.pyd +0 -0
  21. snowflake/connector/_internal/arrow_stream_iterator.cp315-win_amd64.pyd +0 -0
  22. snowflake/connector/_internal/arrow_stream_iterator.pyi +42 -0
  23. snowflake/connector/_internal/arrow_stream_utils.py +171 -0
  24. snowflake/connector/_internal/authenticator_type.py +53 -0
  25. snowflake/connector/_internal/backward_compatibility.py +245 -0
  26. snowflake/connector/_internal/binding_converters.py +741 -0
  27. snowflake/connector/_internal/config_utils.py +71 -0
  28. snowflake/connector/_internal/connection/__init__.py +39 -0
  29. snowflake/connector/_internal/connection/connection.py +616 -0
  30. snowflake/connector/_internal/connection/connection_types.py +13 -0
  31. snowflake/connector/_internal/connection/constants.py +25 -0
  32. snowflake/connector/_internal/connection/decorators.py +31 -0
  33. snowflake/connector/_internal/connection/freezable_proxy.py +104 -0
  34. snowflake/connector/_internal/connection/queries.py +10 -0
  35. snowflake/connector/_internal/connection_config_mixin.py +755 -0
  36. snowflake/connector/_internal/cursor/__init__.py +25 -0
  37. snowflake/connector/_internal/cursor/base.py +732 -0
  38. snowflake/connector/_internal/cursor/cursor_types.py +13 -0
  39. snowflake/connector/_internal/cursor/decorators.py +56 -0
  40. snowflake/connector/_internal/cursor/query_result.py +202 -0
  41. snowflake/connector/_internal/cursor/query_result_waiter.py +98 -0
  42. snowflake/connector/_internal/cursor/result_metadata.py +255 -0
  43. snowflake/connector/_internal/cursor/result_set_wrapper.py +66 -0
  44. snowflake/connector/_internal/decorators.py +539 -0
  45. snowflake/connector/_internal/error_kinds.py +111 -0
  46. snowflake/connector/_internal/errorcode.py +35 -0
  47. snowflake/connector/_internal/errorhandler.py +278 -0
  48. snowflake/connector/_internal/fips.py +28 -0
  49. snowflake/connector/_internal/logging/__init__.py +52 -0
  50. snowflake/connector/_internal/logging/config.py +134 -0
  51. snowflake/connector/_internal/logging/core_logger.py +218 -0
  52. snowflake/connector/_internal/logging/native_extension_logger.py +144 -0
  53. snowflake/connector/_internal/logout_config_mapping.py +187 -0
  54. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +57 -0
  55. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +29 -0
  56. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrowTableConverter.cpp +943 -0
  57. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ArrowTableConverter.hpp +63 -0
  58. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +18 -0
  59. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +26 -0
  60. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +21 -0
  61. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +23 -0
  62. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +118 -0
  63. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +116 -0
  64. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamIterator.cpp +323 -0
  65. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamIterator.hpp +133 -0
  66. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamTableIterator.cpp +275 -0
  67. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/CArrowStreamTableIterator.hpp +168 -0
  68. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ConverterUtil.cpp +439 -0
  69. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ConverterUtil.hpp +30 -0
  70. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +48 -0
  71. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +46 -0
  72. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +76 -0
  73. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +35 -0
  74. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +90 -0
  75. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +63 -0
  76. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +62 -0
  77. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +28 -0
  78. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +29 -0
  79. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +35 -0
  80. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +17 -0
  81. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +23 -0
  82. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +41 -0
  83. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +65 -0
  84. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +54 -0
  85. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/LICENSE.txt +209 -0
  86. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +79 -0
  87. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +30 -0
  88. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +52 -0
  89. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +29 -0
  90. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +8 -0
  91. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +117 -0
  92. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +54 -0
  93. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +34 -0
  94. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +33 -0
  95. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +48 -0
  96. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +18 -0
  97. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +26 -0
  98. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +39 -0
  99. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +31 -0
  100. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +326 -0
  101. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +138 -0
  102. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +14 -0
  103. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Util/time.cpp +65 -0
  104. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/Util/time.hpp +68 -0
  105. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/arrow_stream_iterator.cpp +13278 -0
  106. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/arrow_stream_iterator.pyx +204 -0
  107. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +109 -0
  108. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +125 -0
  109. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +45 -0
  110. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +1914 -0
  111. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +208 -0
  112. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +128 -0
  113. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +7 -0
  114. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +58 -0
  115. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +144 -0
  116. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +31 -0
  117. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +8 -0
  118. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +144 -0
  119. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +160 -0
  120. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +98 -0
  121. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +243 -0
  122. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +14 -0
  123. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +207 -0
  124. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +80 -0
  125. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +83 -0
  126. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +20 -0
  127. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +51 -0
  128. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +201 -0
  129. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +108 -0
  130. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +19 -0
  131. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +52 -0
  132. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +2 -0
  133. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +25 -0
  134. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +67 -0
  135. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +164 -0
  136. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +926 -0
  137. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +182 -0
  138. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +6 -0
  139. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +52 -0
  140. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/flatcc.c +3052 -0
  141. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow.c +3019 -0
  142. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow.h +3354 -0
  143. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +344 -0
  144. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +29305 -0
  145. snowflake/connector/_internal/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +381 -0
  146. snowflake/connector/_internal/nanoarrow_cpp/Logging/logging.cpp +108 -0
  147. snowflake/connector/_internal/nanoarrow_cpp/Logging/logging.hpp +47 -0
  148. snowflake/connector/_internal/nanoarrow_cpp/scripts/.clang-format +8 -0
  149. snowflake/connector/_internal/nanoarrow_cpp/scripts/format.sh +8 -0
  150. snowflake/connector/_internal/protobuf_gen/__init__.py +0 -0
  151. snowflake/connector/_internal/protobuf_gen/database_driver_v1_pb2.py +408 -0
  152. snowflake/connector/_internal/protobuf_gen/database_driver_v1_pb2.pyi +4487 -0
  153. snowflake/connector/_internal/protobuf_gen/database_driver_v1_services.py +2088 -0
  154. snowflake/connector/_internal/protobuf_gen/proto_exception.py +17 -0
  155. snowflake/connector/_internal/result_batch.py +150 -0
  156. snowflake/connector/_internal/snowflake_restful.py +222 -0
  157. snowflake/connector/_internal/snowpark_backcompat_helpers.py +31 -0
  158. snowflake/connector/_internal/sqlstate.py +11 -0
  159. snowflake/connector/_internal/statement_utils.py +207 -0
  160. snowflake/connector/_internal/text_utils.py +112 -0
  161. snowflake/connector/_internal/type_codes.py +139 -0
  162. snowflake/connector/_internal/utils.py +65 -0
  163. snowflake/connector/_internal/write_pandas_operation.py +657 -0
  164. snowflake/connector/aio/README.md +168 -0
  165. snowflake/connector/aio/__init__.py +37 -0
  166. snowflake/connector/aio/connection/__init__.py +17 -0
  167. snowflake/connector/aio/connection/_connection.py +506 -0
  168. snowflake/connector/aio/cursor/__init__.py +35 -0
  169. snowflake/connector/aio/cursor/_base.py +1034 -0
  170. snowflake/connector/aio/cursor/_dict_cursor.py +78 -0
  171. snowflake/connector/aio/cursor/_result_set_wrapper.py +35 -0
  172. snowflake/connector/aio/cursor/_snowflake_cursor.py +72 -0
  173. snowflake/connector/aio/pandas_tools.py +279 -0
  174. snowflake/connector/aio/result_batch.py +165 -0
  175. snowflake/connector/auth/__init__.py +0 -0
  176. snowflake/connector/auth/workload_identity.py +5 -0
  177. snowflake/connector/compat.py +22 -0
  178. snowflake/connector/config_manager.py +392 -0
  179. snowflake/connector/connection/__init__.py +30 -0
  180. snowflake/connector/connection/_connection.py +641 -0
  181. snowflake/connector/connection_config.py +517 -0
  182. snowflake/connector/constants.py +52 -0
  183. snowflake/connector/cursor/__init__.py +37 -0
  184. snowflake/connector/cursor/_base.py +1169 -0
  185. snowflake/connector/cursor/_chunked_download_reader.py +75 -0
  186. snowflake/connector/cursor/_dict_cursor.py +78 -0
  187. snowflake/connector/cursor/_result_set_wrapper.py +35 -0
  188. snowflake/connector/cursor/_snowflake_cursor.py +72 -0
  189. snowflake/connector/description.py +7 -0
  190. snowflake/connector/errors.py +492 -0
  191. snowflake/connector/network.py +71 -0
  192. snowflake/connector/pandas_tools.py +191 -0
  193. snowflake/connector/py.typed +0 -0
  194. snowflake/connector/result_batch.py +216 -0
  195. snowflake/connector/telemetry.py +40 -0
  196. snowflake/connector/time_util.py +11 -0
  197. snowflake/connector/types.py +134 -0
  198. snowflake/connector/util_text.py +3 -0
  199. snowflake/connector/version.py +23 -0
  200. snowflake_connector_python-5.2.0.dist-info/DELVEWHEEL +2 -0
  201. snowflake_connector_python-5.2.0.dist-info/METADATA +190 -0
  202. snowflake_connector_python-5.2.0.dist-info/RECORD +204 -0
  203. snowflake_connector_python-5.2.0.dist-info/WHEEL +4 -0
  204. snowflake_connector_python.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
@@ -0,0 +1,17 @@
1
+ class ProtoException(Exception):
2
+ pass
3
+
4
+ class ProtoApplicationException(ProtoException):
5
+ def __init__(self, error, *args, **kwargs):
6
+ self.api_error_pb = error
7
+ super().__init__(error, *args, **kwargs)
8
+
9
+ def __getattr__(self, name):
10
+ try:
11
+ return getattr(self.api_error_pb, name)
12
+ except AttributeError:
13
+ raise AttributeError(f"'{type(self).__name__}' underlying protobuf object has no attribute '{name}'")
14
+
15
+
16
+ class ProtoTransportException(ProtoException):
17
+ pass
@@ -0,0 +1,150 @@
1
+ """Shared result-batch mixin for sync and async result batch implementations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from enum import Enum, unique
6
+ from typing import TYPE_CHECKING, Any, TypeVar
7
+
8
+ from .arrow_context import ArrowConverterContext
9
+ from .errorhandler import ErrorHandlerMixin
10
+ from .protobuf_gen.database_driver_v1_pb2 import ColumnMetadata, ResultChunk
11
+
12
+
13
+ if TYPE_CHECKING:
14
+ from ..aio.connection import Connection as AsyncConnection
15
+ from ..connection import Connection
16
+ from .cursor.result_metadata import ResultMetadata
17
+
18
+
19
+ _ResultBatchT = TypeVar("_ResultBatchT", bound="ResultBatchMixin")
20
+
21
+
22
+ @unique
23
+ class IterUnit(Enum):
24
+ """Controls what ``ResultBatch.create_iter`` yields."""
25
+
26
+ ROW_UNIT = "row"
27
+ TABLE_UNIT = "table"
28
+
29
+ @classmethod
30
+ def of(cls, value: IterUnit | str) -> IterUnit:
31
+ if isinstance(value, cls):
32
+ return value
33
+ return cls(value)
34
+
35
+
36
+ @unique
37
+ class IterTableStructure(Enum):
38
+ """Controls what table format ``TABLE_UNIT`` iteration produces."""
39
+
40
+ ARROW = "arrow"
41
+ PANDAS = "pandas"
42
+
43
+ @classmethod
44
+ def of(cls, value: IterTableStructure | str) -> IterTableStructure:
45
+ if isinstance(value, cls):
46
+ return value
47
+ return cls(value)
48
+
49
+
50
+ class ResultBatchMixin(ErrorHandlerMixin):
51
+ """Zero-I/O result-batch members shared by sync and async batch classes."""
52
+
53
+ _chunk: ResultChunk
54
+ _description: list[ResultMetadata]
55
+ _connection: Connection | AsyncConnection | None
56
+ _columns: list[ColumnMetadata]
57
+ _arrow_context: ArrowConverterContext
58
+ _numpy: bool
59
+ _use_core_arrow: bool
60
+ _arrow_stream_ptr: int | None
61
+
62
+ def __init__(
63
+ self,
64
+ chunk: ResultChunk,
65
+ description: list[ResultMetadata],
66
+ connection: Connection | AsyncConnection | None,
67
+ columns: list[ColumnMetadata] | None = None,
68
+ ) -> None:
69
+ self._chunk = chunk
70
+ self._description = description
71
+ self._connection = connection
72
+ self._columns = list(columns) if columns else []
73
+ self._arrow_context = (
74
+ ArrowConverterContext.create(connection) if connection is not None else ArrowConverterContext()
75
+ )
76
+ self._numpy = bool(connection.config.numpy) if connection is not None else False
77
+ self._use_core_arrow = bool(connection.config.use_core_arrow) if connection is not None else False
78
+ self._arrow_stream_ptr = None
79
+
80
+ @classmethod
81
+ def from_chunks(
82
+ cls: type[_ResultBatchT],
83
+ chunks: list[ResultChunk] | None,
84
+ description: list[ResultMetadata] | None,
85
+ connection: Connection | AsyncConnection | None,
86
+ columns: list[ColumnMetadata] | None = None,
87
+ ) -> list[_ResultBatchT] | None:
88
+ """Create a list of batches from raw result chunks, or ``None`` if unavailable."""
89
+ if chunks is None or description is None:
90
+ return None
91
+ return [cls(chunk=chunk, description=description, connection=connection, columns=columns) for chunk in chunks]
92
+
93
+ # ------------------------------------------------------------------
94
+ # Properties
95
+ # ------------------------------------------------------------------
96
+
97
+ @property
98
+ def rowcount(self) -> int:
99
+ return self._chunk.row_count
100
+
101
+ @property
102
+ def compressed_size(self) -> int | None:
103
+ if self._chunk.HasField("remote"):
104
+ return self._chunk.remote.compressed_size
105
+ return None
106
+
107
+ @property
108
+ def uncompressed_size(self) -> int | None:
109
+ if self._chunk.HasField("remote"):
110
+ return self._chunk.remote.uncompressed_size
111
+ return None
112
+
113
+ @property
114
+ def column_names(self) -> list[str]:
115
+ return [col.name for col in self._description]
116
+
117
+ @property
118
+ def _errorhandler_connection(self) -> Connection | AsyncConnection | None:
119
+ return self._connection
120
+
121
+ # ------------------------------------------------------------------
122
+ # Pickle support
123
+ # ------------------------------------------------------------------
124
+
125
+ def __getstate__(self) -> dict[str, Any]:
126
+ return {
127
+ "chunk_bytes": self._chunk.SerializeToString(),
128
+ "description": self._description,
129
+ "column_bytes": [c.SerializeToString() for c in self._columns],
130
+ "arrow_context": self._arrow_context,
131
+ "numpy": self._numpy,
132
+ "use_core_arrow": self._use_core_arrow,
133
+ }
134
+
135
+ def __setstate__(self, state: dict[str, Any]) -> None:
136
+ chunk = ResultChunk()
137
+ chunk.ParseFromString(state["chunk_bytes"])
138
+ self._chunk = chunk
139
+ self._description = state["description"]
140
+ columns: list[ColumnMetadata] = []
141
+ for raw in state.get("column_bytes", []):
142
+ col = ColumnMetadata()
143
+ col.ParseFromString(raw)
144
+ columns.append(col)
145
+ self._columns = columns
146
+ self._arrow_context = state.get("arrow_context", ArrowConverterContext())
147
+ self._numpy = state.get("numpy", False)
148
+ self._use_core_arrow = state.get("use_core_arrow", False)
149
+ self._connection = None
150
+ self._arrow_stream_ptr = None
@@ -0,0 +1,222 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+
5
+ from typing import TYPE_CHECKING
6
+ from urllib.parse import urlparse
7
+
8
+ from snowflake.connector._internal.api_client.client_api import core_driver
9
+ from snowflake.connector._internal.protobuf_gen.database_driver_v1_pb2 import (
10
+ TOKEN_REQUEST_TYPE_ISSUE,
11
+ TOKEN_REQUEST_TYPE_RENEW,
12
+ ConnectionGetInfoResponse,
13
+ )
14
+ from snowflake.connector.errors import OperationalError
15
+
16
+
17
+ if TYPE_CHECKING:
18
+ from ..connection import SnowflakeConnection
19
+
20
+ DEFAULT_PROTOCOL = "https"
21
+ DEFAULT_PORT = 443
22
+ APPLICATION_JSON = "application/json"
23
+
24
+ _TOKEN_REQUEST_TYPE_MAP = {
25
+ "ISSUE": TOKEN_REQUEST_TYPE_ISSUE,
26
+ "RENEW": TOKEN_REQUEST_TYPE_RENEW,
27
+ }
28
+
29
+
30
+ class SnowflakeRestful:
31
+ """Backward-compatible REST interface wrapping the driver's internal gRPC API.
32
+
33
+ Used by Snowflake CLI to issue Snowflake REST API calls (v1 and v2)
34
+ through the driver's TLS-configured HTTP client.
35
+ """
36
+
37
+ def __init__(self, connection: SnowflakeConnection) -> None:
38
+ self._connection = connection
39
+
40
+ @property
41
+ def _connection_info(self) -> ConnectionGetInfoResponse:
42
+ return self._connection._get_connection_info()
43
+
44
+ def get_user_agent(self) -> str | None:
45
+ """User-Agent string built by the driver core (None before connect).
46
+
47
+ The Rust core constructs the User-Agent from the client app id, version
48
+ and platform; consumers building REST requests should use this rather
49
+ than reconstructing the value themselves.
50
+ """
51
+ user_agent: str | None = self._connection_info.user_agent
52
+ return user_agent if user_agent else None
53
+
54
+ @property
55
+ def token(self) -> str | None:
56
+ """Required by Python API. Returns None after close (handle released)."""
57
+ if self._connection.is_closed():
58
+ return None
59
+ session_token: str | None = self._connection_info.session_token
60
+ return session_token if session_token else None
61
+
62
+ @property
63
+ def _host(self) -> str | None:
64
+ host: str | None = self._connection_info.host
65
+ return host
66
+
67
+ @property
68
+ def _protocol(self) -> str | None:
69
+ url = self._connection_info.server_url
70
+ if not url:
71
+ return DEFAULT_PROTOCOL
72
+ return urlparse(url).scheme or DEFAULT_PROTOCOL
73
+
74
+ @property
75
+ def _port(self) -> int | None:
76
+ info = self._connection_info
77
+ if info.port:
78
+ return info.port
79
+ url = info.server_url
80
+ if not url:
81
+ return DEFAULT_PORT
82
+ return urlparse(url).port or DEFAULT_PORT
83
+
84
+ @property
85
+ def server_url(self) -> str:
86
+ url = self._connection_info.server_url
87
+ if url:
88
+ url = url.rstrip("/")
89
+ parsed = urlparse(url)
90
+ if parsed.port is None:
91
+ port = self._port
92
+ return f"{parsed.scheme}://{parsed.hostname}:{port}{parsed.path}"
93
+ return url
94
+ host = self._host
95
+ if not host:
96
+ raise ValueError("server_url and host are both unavailable from connection info")
97
+ return f"{self._protocol}://{host}:{self._port}"
98
+
99
+ @property
100
+ def master_token(self) -> str | None:
101
+ """Returns None after close (handle released)."""
102
+ if self._connection.is_closed():
103
+ return None
104
+ info = self._connection._get_connection_info(include_master_token=True)
105
+ master_token: str = info.master_token
106
+ return master_token if master_token else None
107
+
108
+ def _send_http(
109
+ self,
110
+ method: str,
111
+ url: str,
112
+ headers: dict[str, str] | None = None,
113
+ body: dict | str | bytes | None = None,
114
+ ) -> tuple[int, dict[str, str], bytes]:
115
+ if url.startswith(("http://", "https://")):
116
+ parsed = urlparse(url)
117
+ server_parsed = urlparse(self.server_url)
118
+ if parsed.hostname and server_parsed.hostname and parsed.hostname != server_parsed.hostname:
119
+ raise ValueError(
120
+ f"Absolute URL host '{parsed.hostname}' does not match "
121
+ f"connection server host '{server_parsed.hostname}'. "
122
+ f"Pass a relative path instead."
123
+ )
124
+ relative_url = parsed.path
125
+ if parsed.query:
126
+ relative_url = f"{relative_url}?{parsed.query}"
127
+ url = relative_url
128
+
129
+ if body is not None:
130
+ if isinstance(body, dict):
131
+ encoded_body = json.dumps(body).encode("utf-8")
132
+ elif isinstance(body, str):
133
+ encoded_body = body.encode("utf-8")
134
+ else:
135
+ encoded_body = body
136
+ else:
137
+ encoded_body = None
138
+
139
+ response = core_driver.connection_send_http(
140
+ conn_handle=self._connection.conn_handle, # type: ignore[arg-type]
141
+ method=method,
142
+ url=url,
143
+ headers=headers or {},
144
+ body=encoded_body,
145
+ )
146
+ return response.status_code, dict(response.headers), response.body
147
+
148
+ _SUPPORTED_REQUEST_METHODS = {"get", "post"}
149
+
150
+ def request(
151
+ self,
152
+ url: str,
153
+ body: dict | None = None,
154
+ method: str = "post",
155
+ client: str = "sfsql",
156
+ timeout: int | None = None,
157
+ _no_results: bool = False,
158
+ _include_retry_params: bool = False,
159
+ _no_retry: bool = False,
160
+ ) -> dict:
161
+ if client == "sfsql":
162
+ raise NotImplementedError(
163
+ "request() with client='sfsql' is not supported. Use cursor.execute() for SQL queries."
164
+ )
165
+
166
+ if method.lower() not in self._SUPPORTED_REQUEST_METHODS:
167
+ raise ValueError(f"Unsupported HTTP method '{method}'. Only 'get' and 'post' are supported.")
168
+
169
+ headers = {
170
+ "Content-Type": APPLICATION_JSON,
171
+ "Accept": APPLICATION_JSON,
172
+ }
173
+
174
+ status_code, _, response_body = self._send_http(
175
+ method=method,
176
+ url=url,
177
+ headers=headers,
178
+ body=body,
179
+ )
180
+
181
+ if status_code >= 400:
182
+ raise OperationalError.from_http_response(status_code, response_body)
183
+
184
+ return json.loads(response_body) if response_body else {}
185
+
186
+ def fetch(
187
+ self,
188
+ method: str,
189
+ full_url: str,
190
+ headers: dict[str, str],
191
+ data: str | None = None,
192
+ timeout: int | None = None,
193
+ token: str | None = None,
194
+ no_retry: bool = False,
195
+ raise_raw_http_failure: bool = False,
196
+ **kwargs: object,
197
+ ) -> dict | list:
198
+ status_code, _, response_body = self._send_http(
199
+ method=method,
200
+ url=full_url,
201
+ headers=headers,
202
+ body=data,
203
+ )
204
+
205
+ if raise_raw_http_failure and status_code >= 400:
206
+ raise OperationalError.from_http_response(status_code, response_body)
207
+
208
+ return json.loads(response_body) if response_body else {}
209
+
210
+ def _token_request(self, request_type: str) -> dict:
211
+ proto_type = _TOKEN_REQUEST_TYPE_MAP.get(request_type.upper())
212
+ if proto_type is None:
213
+ raise ValueError(f"Unknown token request type: {request_type!r}. Must be 'ISSUE' or 'RENEW'.")
214
+
215
+ response = core_driver.connection_request_token(
216
+ conn_handle=self._connection.conn_handle, # type: ignore[arg-type]
217
+ request_type=proto_type,
218
+ )
219
+ data: dict = {"sessionToken": response.session_token}
220
+ if response.HasField("validity_in_seconds"):
221
+ data["validityInSecondsST"] = response.validity_in_seconds
222
+ return {"data": data, "success": True}
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+
6
+ _STAGE_PREFIXES = ("@", "snow://", "/")
7
+
8
+
9
+ def file_uri(path: str) -> str:
10
+ """Add a ``file://`` prefix unless *path* already has one or is quoted."""
11
+ stripped = path.strip()
12
+ return stripped if stripped.startswith(("'", "file://")) else f"file://{stripped}"
13
+
14
+
15
+ def stage_ref(path: str) -> str:
16
+ """Add an ``@`` prefix unless *path* already names a stage."""
17
+ stripped = path.strip()
18
+ return stripped if stripped.startswith(("'", *_STAGE_PREFIXES)) else f"@{stripped}"
19
+
20
+
21
+ def unquoted_stage_ref(path: str) -> str:
22
+ """Add an ``@`` prefix and strip quoting; the streaming RPC takes the stage name as a field, not SQL."""
23
+ stripped = path.strip()
24
+ if len(stripped) > 1 and stripped.startswith("'") and stripped.endswith("'"):
25
+ stripped = stripped[1:-1]
26
+ return stripped if stripped.startswith(_STAGE_PREFIXES) else f"@{stripped}"
27
+
28
+
29
+ def put_get_options(options: dict[str, Any] | None) -> str:
30
+ """Render an options mapping as trailing ``KEY=VALUE`` pairs, unquoted."""
31
+ return " ".join(f"{name}={value}" for name, value in (options or {}).items())
@@ -0,0 +1,11 @@
1
+ """
2
+ SQLSTATE codes.
3
+
4
+ It should be aligned with the reference snowflake-connector-python.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+
10
+ SQLSTATE_SUCCESS = "00000"
11
+ SQLSTATE_CONNECTION_NOT_EXISTS = "08003"
@@ -0,0 +1,207 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import AsyncGenerator, Generator
4
+ from contextlib import asynccontextmanager, contextmanager
5
+
6
+ from .api_client.client_api import async_core_driver, core_driver
7
+ from .protobuf_gen.database_driver_v1_pb2 import (
8
+ ConnectionHandle,
9
+ DatabaseFetchChunkResponse,
10
+ PrepareResult,
11
+ ResultSetDescriptor,
12
+ ResultSetGetStreamResponse,
13
+ StatementHandle,
14
+ )
15
+ from .sqlstate import SQLSTATE_SUCCESS
16
+
17
+
18
+ @contextmanager
19
+ def statement(conn_handle: ConnectionHandle, query: str) -> Generator[StatementHandle]:
20
+ """Context manager that owns the full lifecycle of a statement handle.
21
+
22
+ Allocates a new statement on the server, binds the given SQL query to it,
23
+ and yields the ``StatementHandle`` for execution. The statement is
24
+ guaranteed to be released when the context exits, even if an exception
25
+ is raised.
26
+
27
+ Args:
28
+ conn_handle: Active Snowflake conn_handle.
29
+ query: SQL text to bind to the newly created statement.
30
+
31
+ Yields:
32
+ StatementHandle: A handle that can be passed to ``statement_execute``
33
+ or other statement-level APIs.
34
+ """
35
+ stmt_handle = core_driver.statement_new(conn_handle=conn_handle).stmt_handle
36
+ try:
37
+ core_driver.statement_set_query(stmt_handle=stmt_handle, query=query)
38
+ yield stmt_handle
39
+ finally:
40
+ core_driver.statement_release(stmt_handle=stmt_handle)
41
+
42
+
43
+ @asynccontextmanager
44
+ async def async_statement(conn_handle: ConnectionHandle, query: str) -> AsyncGenerator[StatementHandle]:
45
+ stmt_handle = (await async_core_driver.statement_new(conn_handle=conn_handle)).stmt_handle
46
+ try:
47
+ await async_core_driver.statement_set_query(stmt_handle=stmt_handle, query=query)
48
+ yield stmt_handle
49
+ finally:
50
+ await async_core_driver.statement_release(stmt_handle=stmt_handle)
51
+
52
+
53
+ def get_stream_ptr(result: DatabaseFetchChunkResponse | PrepareResult | ResultSetGetStreamResponse | None) -> int:
54
+ """Extract a C ArrowArrayStream pointer from an execute result.
55
+
56
+ The pointer is stored as an 8-byte little-endian value inside
57
+ ``result.stream.value``. This function validates every step of
58
+ the extraction and raises descriptive errors on failure, so callers
59
+ can safely pass the returned integer to Arrow C Data Interface
60
+ consumers (e.g. PyArrow ``RecordBatchReader.from_stream``).
61
+
62
+ Args:
63
+ result: The protobuf response returned by ``statement_execute``.
64
+ Must not be ``None`` and must carry a populated ``stream``
65
+ field.
66
+
67
+ Returns:
68
+ A non-zero integer representing the memory address of the
69
+ ``ArrowArrayStream`` struct.
70
+
71
+ Raises:
72
+ RuntimeError: If *result* is ``None``, the stream or its value
73
+ is missing, the value has an unexpected length, or the
74
+ decoded pointer is null.
75
+ """
76
+ if result is None:
77
+ raise RuntimeError("No query has been executed")
78
+
79
+ if not hasattr(result, "stream") or result.stream is None:
80
+ raise RuntimeError("Execute result does not contain a valid stream")
81
+
82
+ if not hasattr(result.stream, "value") or result.stream.value is None:
83
+ raise RuntimeError("Stream does not contain a valid pointer value")
84
+
85
+ stream_value = result.stream.value
86
+ # 8 bytes = 64-bit pointer, the size of a C ArrowArrayStream* on a 64-bit platform
87
+ if len(stream_value) != 8:
88
+ raise RuntimeError(f"Stream pointer value has wrong length: {len(stream_value)} (expected 8)")
89
+
90
+ stream_ptr = int.from_bytes(stream_value, byteorder="little", signed=False)
91
+
92
+ if stream_ptr == 0:
93
+ raise RuntimeError("Stream pointer is null")
94
+
95
+ return stream_ptr
96
+
97
+
98
+ def extract_sqlstate(result: PrepareResult | ResultSetDescriptor | None) -> str | None:
99
+ """Return the SQLSTATE code from an execute result, if meaningful.
100
+
101
+ SQLSTATE ``"00000"`` (successful completion) is normalized to ``None``
102
+ for backwards compatibility with the legacy connector, which omits
103
+ the code on success.
104
+
105
+ Args:
106
+ result: A ``PrepareResult`` or ``ResultSetDescriptor``,
107
+ or ``None`` if no result is available.
108
+
109
+ Returns:
110
+ A five-character SQLSTATE string for warnings/errors, or ``None``
111
+ on success or when *result* is ``None``.
112
+ """
113
+ sql_state = result.sql_state if result else None
114
+ if sql_state and sql_state != SQLSTATE_SUCCESS:
115
+ return sql_state
116
+ return None
117
+
118
+
119
+ # Snowflake statement_type_id families/classes that produce a browsable result
120
+ # set or a real update count. When the server omits rows_affected for one of
121
+ # these, the row count is genuinely unknown (-1); for every other classified
122
+ # statement (DDL, session/transaction control, etc.) the legacy connector
123
+ # reported the generic success marker 1, which we reproduce for compatibility.
124
+ # Classification mirrors the core's mask-based taxonomy (level-3 0xF000 family,
125
+ # level-2 0xFF00 class) rather than exact ids, because the concrete ids the
126
+ # server returns (e.g. ALTER SESSION 0x4100, COMMIT 0x5100) do not match named
127
+ # constants but do classify correctly by family.
128
+ _CURSOR_OR_DML_FAMILIES = frozenset(
129
+ {
130
+ 0x1000, # SELECT
131
+ 0x2000, # EXPLAIN
132
+ 0x3000, # DML (INSERT/UPDATE/DELETE/MERGE/COPY/...)
133
+ 0x7000, # stage file operations (PUT/GET/LIST/REMOVE)
134
+ 0x9000, # CALL
135
+ }
136
+ )
137
+ _CURSOR_CLASSES = frozenset(
138
+ {
139
+ 0x4400, # SHOW
140
+ 0x4500, # DESCRIBE
141
+ 0x4700, # LIST_FILES
142
+ }
143
+ )
144
+ _CURSOR_EXACT_IDS = frozenset(
145
+ {
146
+ 0x6244, # MANAGE_PATS: DDL-family id that returns a browsable result set
147
+ }
148
+ )
149
+ # Level-3 (0xF000) families that produce no affected-row count but which the
150
+ # legacy connector reported as rowcount == 1. Restricting the compat fallback
151
+ # to these known families means an unrecognized/future id (e.g. 0xBEEF) is
152
+ # reported as unknown (-1) rather than a spurious success.
153
+ _NO_RESULT_FAMILIES = frozenset(
154
+ {
155
+ 0x4000, # SYSCMD (ALTER SESSION 0x4100, USE 0x4300, ...)
156
+ 0x5000, # TCL (BEGIN/COMMIT/ROLLBACK, e.g. 0x5100, 0x5400)
157
+ 0x6000, # DDL (CREATE/DROP/ALTER, e.g. 0x6100/0x6101/0x6300)
158
+ 0x8000, # MISC_QUERY_TYPES
159
+ }
160
+ )
161
+
162
+
163
+ def _produces_result_or_count(statement_type_id: int) -> bool:
164
+ """Whether the statement type produces a cursor or a real update count.
165
+
166
+ These are the statements for which an absent ``rows_affected`` means the
167
+ count is genuinely unknown; everything else classified is a no-result
168
+ statement that the legacy connector reported as ``1``.
169
+ """
170
+ if (statement_type_id & 0xF000) in _CURSOR_OR_DML_FAMILIES:
171
+ return True
172
+ if (statement_type_id & 0xFF00) in _CURSOR_CLASSES:
173
+ return True
174
+ return statement_type_id in _CURSOR_EXACT_IDS
175
+
176
+
177
+ def extract_rowcount(descriptor: ResultSetDescriptor | None) -> int:
178
+ """Return the number of rows affected from a ResultSetDescriptor.
179
+
180
+ Returns the server's ``rows_affected`` when present (SELECT/DML, including
181
+ ``0``). When it is absent the statement produced no affected-row count: for
182
+ a recognized no-result statement (DDL, session/transaction control, etc.)
183
+ this returns ``1`` to match the legacy connector, and ``-1`` for
184
+ cursor/DML statements with a missing count or an absent/unrecognized
185
+ statement type.
186
+
187
+ Args:
188
+ descriptor: The ResultSetDescriptor from a proto response.
189
+
190
+ Returns:
191
+ Row count from server, ``1`` for legacy no-result successes, or ``-1``
192
+ when unavailable.
193
+ """
194
+ if not descriptor:
195
+ return -1
196
+
197
+ if descriptor.HasField("rows_affected"):
198
+ return descriptor.rows_affected
199
+
200
+ if not descriptor.HasField("statement_type_id"):
201
+ return -1
202
+ statement_type_id = descriptor.statement_type_id
203
+ if _produces_result_or_count(statement_type_id):
204
+ return -1
205
+ if (statement_type_id & 0xF000) in _NO_RESULT_FAMILIES:
206
+ return 1
207
+ return -1