snowflake-connector-python 3.16.0__cp313-cp313-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 (246) hide show
  1. snowflake/connector/__init__.py +96 -0
  2. snowflake/connector/_query_context_cache.py +276 -0
  3. snowflake/connector/_sql_util.py +48 -0
  4. snowflake/connector/_utils.py +70 -0
  5. snowflake/connector/arrow_context.py +203 -0
  6. snowflake/connector/auth/__init__.py +53 -0
  7. snowflake/connector/auth/_auth.py +586 -0
  8. snowflake/connector/auth/_http_server.py +220 -0
  9. snowflake/connector/auth/_oauth_base.py +400 -0
  10. snowflake/connector/auth/by_plugin.py +219 -0
  11. snowflake/connector/auth/default.py +36 -0
  12. snowflake/connector/auth/idtoken.py +72 -0
  13. snowflake/connector/auth/keypair.py +222 -0
  14. snowflake/connector/auth/no_auth.py +39 -0
  15. snowflake/connector/auth/oauth.py +49 -0
  16. snowflake/connector/auth/oauth_code.py +479 -0
  17. snowflake/connector/auth/oauth_credentials.py +66 -0
  18. snowflake/connector/auth/okta.py +335 -0
  19. snowflake/connector/auth/pat.py +39 -0
  20. snowflake/connector/auth/usrpwdmfa.py +69 -0
  21. snowflake/connector/auth/webbrowser.py +502 -0
  22. snowflake/connector/auth/workload_identity.py +94 -0
  23. snowflake/connector/azure_storage_client.py +276 -0
  24. snowflake/connector/backoff_policies.py +141 -0
  25. snowflake/connector/bind_upload_agent.py +89 -0
  26. snowflake/connector/cache.py +696 -0
  27. snowflake/connector/compat.py +127 -0
  28. snowflake/connector/config_manager.py +496 -0
  29. snowflake/connector/connection.py +2273 -0
  30. snowflake/connector/connection_diagnostic.py +776 -0
  31. snowflake/connector/constants.py +442 -0
  32. snowflake/connector/converter.py +785 -0
  33. snowflake/connector/converter_issue23517.py +87 -0
  34. snowflake/connector/converter_null.py +14 -0
  35. snowflake/connector/converter_snowsql.py +205 -0
  36. snowflake/connector/cursor.py +1951 -0
  37. snowflake/connector/dbapi.py +53 -0
  38. snowflake/connector/description.py +19 -0
  39. snowflake/connector/direct_file_operation_utils.py +88 -0
  40. snowflake/connector/encryption_util.py +220 -0
  41. snowflake/connector/errorcode.py +91 -0
  42. snowflake/connector/errors.py +615 -0
  43. snowflake/connector/externals_utils/__init__.py +0 -0
  44. snowflake/connector/externals_utils/externals_setup.py +27 -0
  45. snowflake/connector/feature.py +4 -0
  46. snowflake/connector/file_compression_type.py +118 -0
  47. snowflake/connector/file_lock.py +72 -0
  48. snowflake/connector/file_transfer_agent.py +1215 -0
  49. snowflake/connector/file_util.py +153 -0
  50. snowflake/connector/gcs_storage_client.py +474 -0
  51. snowflake/connector/gzip_decoder.py +85 -0
  52. snowflake/connector/local_storage_client.py +90 -0
  53. snowflake/connector/log_configuration.py +60 -0
  54. snowflake/connector/logging_utils/__init__.py +0 -0
  55. snowflake/connector/logging_utils/filters.py +72 -0
  56. snowflake/connector/nanoarrow_arrow_iterator.cp313-win_amd64.pyd +0 -0
  57. snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +60 -0
  58. snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +29 -0
  59. snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +19 -0
  60. snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +26 -0
  61. snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +21 -0
  62. snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +23 -0
  63. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +557 -0
  64. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +98 -0
  65. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +125 -0
  66. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +115 -0
  67. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +1005 -0
  68. snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +127 -0
  69. snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +47 -0
  70. snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +46 -0
  71. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +83 -0
  72. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +35 -0
  73. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +97 -0
  74. snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +72 -0
  75. snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +73 -0
  76. snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +28 -0
  77. snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +30 -0
  78. snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +35 -0
  79. snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +17 -0
  80. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +23 -0
  81. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +45 -0
  82. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +71 -0
  83. snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +56 -0
  84. snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +209 -0
  85. snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +75 -0
  86. snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +30 -0
  87. snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +46 -0
  88. snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +29 -0
  89. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +8 -0
  90. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +95 -0
  91. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +57 -0
  92. snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +36 -0
  93. snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +34 -0
  94. snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +48 -0
  95. snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +19 -0
  96. snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +26 -0
  97. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +36 -0
  98. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +31 -0
  99. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +346 -0
  100. snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +145 -0
  101. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +14 -0
  102. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +65 -0
  103. snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +68 -0
  104. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +101 -0
  105. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +127 -0
  106. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +45 -0
  107. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +1908 -0
  108. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +215 -0
  109. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +125 -0
  110. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +7 -0
  111. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +55 -0
  112. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +148 -0
  113. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +31 -0
  114. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +8 -0
  115. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +144 -0
  116. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +162 -0
  117. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +97 -0
  118. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +239 -0
  119. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +14 -0
  120. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +210 -0
  121. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +84 -0
  122. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +84 -0
  123. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +20 -0
  124. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +51 -0
  125. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +206 -0
  126. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +118 -0
  127. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +19 -0
  128. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +52 -0
  129. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +2 -0
  130. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +25 -0
  131. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +67 -0
  132. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +162 -0
  133. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +898 -0
  134. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +190 -0
  135. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +6 -0
  136. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +52 -0
  137. snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +3204 -0
  138. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +3217 -0
  139. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +3618 -0
  140. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +379 -0
  141. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +256 -0
  142. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +512 -0
  143. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +350 -0
  144. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +33273 -0
  145. snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +397 -0
  146. snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +100 -0
  147. snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +49 -0
  148. snowflake/connector/network.py +1297 -0
  149. snowflake/connector/ocsp_asn1crypto.py +447 -0
  150. snowflake/connector/ocsp_snowflake.py +1883 -0
  151. snowflake/connector/options.py +131 -0
  152. snowflake/connector/pandas_tools.py +732 -0
  153. snowflake/connector/proxy.py +43 -0
  154. snowflake/connector/py.typed +0 -0
  155. snowflake/connector/result_batch.py +786 -0
  156. snowflake/connector/result_set.py +319 -0
  157. snowflake/connector/s3_storage_client.py +605 -0
  158. snowflake/connector/secret_detector.py +181 -0
  159. snowflake/connector/sf_dirs.py +64 -0
  160. snowflake/connector/sfbinaryformat.py +35 -0
  161. snowflake/connector/sfdatetime.py +345 -0
  162. snowflake/connector/snow_logging.py +144 -0
  163. snowflake/connector/sqlstate.py +9 -0
  164. snowflake/connector/ssd_internal_keys.py +30 -0
  165. snowflake/connector/ssl_wrap_socket.py +134 -0
  166. snowflake/connector/storage_client.py +478 -0
  167. snowflake/connector/telemetry.py +249 -0
  168. snowflake/connector/telemetry_oob.py +543 -0
  169. snowflake/connector/test_util.py +30 -0
  170. snowflake/connector/time_util.py +159 -0
  171. snowflake/connector/token_cache.py +402 -0
  172. snowflake/connector/tool/__init__.py +0 -0
  173. snowflake/connector/tool/dump_certs.py +57 -0
  174. snowflake/connector/tool/dump_ocsp_response.py +139 -0
  175. snowflake/connector/tool/dump_ocsp_response_cache.py +194 -0
  176. snowflake/connector/tool/probe_connection.py +69 -0
  177. snowflake/connector/url_util.py +49 -0
  178. snowflake/connector/util_text.py +301 -0
  179. snowflake/connector/vendored/__init__.py +3 -0
  180. snowflake/connector/vendored/requests/LICENSE +175 -0
  181. snowflake/connector/vendored/requests/__init__.py +169 -0
  182. snowflake/connector/vendored/requests/__version__.py +14 -0
  183. snowflake/connector/vendored/requests/_internal_utils.py +50 -0
  184. snowflake/connector/vendored/requests/adapters.py +537 -0
  185. snowflake/connector/vendored/requests/api.py +157 -0
  186. snowflake/connector/vendored/requests/auth.py +315 -0
  187. snowflake/connector/vendored/requests/certs.py +17 -0
  188. snowflake/connector/vendored/requests/compat.py +79 -0
  189. snowflake/connector/vendored/requests/cookies.py +561 -0
  190. snowflake/connector/vendored/requests/exceptions.py +140 -0
  191. snowflake/connector/vendored/requests/help.py +134 -0
  192. snowflake/connector/vendored/requests/hooks.py +33 -0
  193. snowflake/connector/vendored/requests/models.py +1033 -0
  194. snowflake/connector/vendored/requests/sessions.py +833 -0
  195. snowflake/connector/vendored/requests/status_codes.py +128 -0
  196. snowflake/connector/vendored/requests/structures.py +99 -0
  197. snowflake/connector/vendored/requests/utils.py +1093 -0
  198. snowflake/connector/vendored/urllib3/LICENSE.txt +21 -0
  199. snowflake/connector/vendored/urllib3/__init__.py +85 -0
  200. snowflake/connector/vendored/urllib3/_collections.py +355 -0
  201. snowflake/connector/vendored/urllib3/_version.py +2 -0
  202. snowflake/connector/vendored/urllib3/connection.py +572 -0
  203. snowflake/connector/vendored/urllib3/connectionpool.py +1137 -0
  204. snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
  205. snowflake/connector/vendored/urllib3/contrib/_appengine_environ.py +36 -0
  206. snowflake/connector/vendored/urllib3/contrib/_securetransport/__init__.py +0 -0
  207. snowflake/connector/vendored/urllib3/contrib/_securetransport/bindings.py +519 -0
  208. snowflake/connector/vendored/urllib3/contrib/_securetransport/low_level.py +397 -0
  209. snowflake/connector/vendored/urllib3/contrib/appengine.py +314 -0
  210. snowflake/connector/vendored/urllib3/contrib/ntlmpool.py +130 -0
  211. snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +509 -0
  212. snowflake/connector/vendored/urllib3/contrib/securetransport.py +920 -0
  213. snowflake/connector/vendored/urllib3/contrib/socks.py +216 -0
  214. snowflake/connector/vendored/urllib3/exceptions.py +323 -0
  215. snowflake/connector/vendored/urllib3/fields.py +274 -0
  216. snowflake/connector/vendored/urllib3/filepost.py +98 -0
  217. snowflake/connector/vendored/urllib3/packages/__init__.py +0 -0
  218. snowflake/connector/vendored/urllib3/packages/backports/__init__.py +0 -0
  219. snowflake/connector/vendored/urllib3/packages/backports/makefile.py +51 -0
  220. snowflake/connector/vendored/urllib3/packages/backports/weakref_finalize.py +155 -0
  221. snowflake/connector/vendored/urllib3/packages/six.py +1076 -0
  222. snowflake/connector/vendored/urllib3/poolmanager.py +540 -0
  223. snowflake/connector/vendored/urllib3/request.py +191 -0
  224. snowflake/connector/vendored/urllib3/response.py +885 -0
  225. snowflake/connector/vendored/urllib3/util/__init__.py +49 -0
  226. snowflake/connector/vendored/urllib3/util/connection.py +156 -0
  227. snowflake/connector/vendored/urllib3/util/proxy.py +57 -0
  228. snowflake/connector/vendored/urllib3/util/queue.py +22 -0
  229. snowflake/connector/vendored/urllib3/util/request.py +146 -0
  230. snowflake/connector/vendored/urllib3/util/response.py +107 -0
  231. snowflake/connector/vendored/urllib3/util/retry.py +620 -0
  232. snowflake/connector/vendored/urllib3/util/ssl_.py +495 -0
  233. snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +159 -0
  234. snowflake/connector/vendored/urllib3/util/ssltransport.py +221 -0
  235. snowflake/connector/vendored/urllib3/util/timeout.py +271 -0
  236. snowflake/connector/vendored/urllib3/util/url.py +435 -0
  237. snowflake/connector/vendored/urllib3/util/wait.py +152 -0
  238. snowflake/connector/version.py +3 -0
  239. snowflake/connector/wif_util.py +407 -0
  240. snowflake_connector_python-3.16.0.dist-info/METADATA +1475 -0
  241. snowflake_connector_python-3.16.0.dist-info/RECORD +246 -0
  242. snowflake_connector_python-3.16.0.dist-info/WHEEL +5 -0
  243. snowflake_connector_python-3.16.0.dist-info/entry_points.txt +4 -0
  244. snowflake_connector_python-3.16.0.dist-info/licenses/LICENSE.txt +202 -0
  245. snowflake_connector_python-3.16.0.dist-info/licenses/NOTICE +8 -0
  246. snowflake_connector_python-3.16.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,319 @@
1
+ from __future__ import annotations
2
+
3
+ import inspect
4
+ from collections import deque
5
+ from concurrent.futures import ALL_COMPLETED, Future, ProcessPoolExecutor, wait
6
+ from concurrent.futures.thread import ThreadPoolExecutor
7
+ from logging import getLogger
8
+ from typing import (
9
+ TYPE_CHECKING,
10
+ Any,
11
+ Callable,
12
+ Deque,
13
+ Iterable,
14
+ Iterator,
15
+ Literal,
16
+ overload,
17
+ )
18
+
19
+ from .constants import IterUnit
20
+ from .errors import NotSupportedError
21
+ from .options import pandas
22
+ from .options import pyarrow as pa
23
+ from .result_batch import (
24
+ ArrowResultBatch,
25
+ DownloadMetrics,
26
+ JSONResultBatch,
27
+ ResultBatch,
28
+ )
29
+ from .telemetry import TelemetryField
30
+ from .time_util import get_time_millis
31
+
32
+ if TYPE_CHECKING: # pragma: no cover
33
+ from pandas import DataFrame
34
+ from pyarrow import Table
35
+
36
+ from snowflake.connector.cursor import SnowflakeCursor
37
+
38
+ logger = getLogger(__name__)
39
+
40
+
41
+ def result_set_iterator(
42
+ first_batch_iter: Iterator[tuple],
43
+ unconsumed_batches: Deque[Future[Iterator[tuple]]],
44
+ unfetched_batches: Deque[ResultBatch],
45
+ final: Callable[[], None],
46
+ prefetch_thread_num: int,
47
+ use_mp: bool,
48
+ **kw: Any,
49
+ ) -> Iterator[dict | Exception] | Iterator[tuple | Exception] | Iterator[Table]:
50
+ """Creates an iterator over some other iterators.
51
+
52
+ Very similar to itertools.chain but we need some keywords to be propagated to
53
+ ``_download`` functions later.
54
+
55
+ We need this to have ResultChunks fall out of usage so that they can be garbage
56
+ collected.
57
+
58
+ Just like ``ResultBatch`` iterator, this might yield an ``Exception`` to allow users
59
+ to continue iterating through the rest of the ``ResultBatch``.
60
+ """
61
+ is_fetch_all = kw.pop("is_fetch_all", False)
62
+
63
+ if use_mp:
64
+
65
+ def create_pool_executor() -> ProcessPoolExecutor:
66
+ return ProcessPoolExecutor(prefetch_thread_num)
67
+
68
+ def create_fetch_task(batch: ResultBatch):
69
+ return batch.populate_data
70
+
71
+ def get_fetch_result(future_result: ResultBatch):
72
+ return future_result.create_iter(**kw)
73
+
74
+ kw["connection"] = None
75
+ else:
76
+
77
+ def create_pool_executor() -> ThreadPoolExecutor:
78
+ return ThreadPoolExecutor(prefetch_thread_num)
79
+
80
+ def create_fetch_task(batch: ResultBatch):
81
+ return batch.create_iter
82
+
83
+ def get_fetch_result(future_result: Iterator):
84
+ return future_result
85
+
86
+ if is_fetch_all:
87
+ with create_pool_executor() as pool:
88
+ logger.debug("beginning to schedule result batch downloads")
89
+ yield from first_batch_iter
90
+ while unfetched_batches:
91
+ logger.debug(
92
+ f"queuing download of result batch id: {unfetched_batches[0].id}"
93
+ )
94
+ future = pool.submit(
95
+ create_fetch_task(unfetched_batches.popleft()), **kw
96
+ )
97
+ unconsumed_batches.append(future)
98
+ _, _ = wait(unconsumed_batches, return_when=ALL_COMPLETED)
99
+ i = 1
100
+ while unconsumed_batches:
101
+ logger.debug(f"user began consuming result batch {i}")
102
+ yield from get_fetch_result(unconsumed_batches.popleft().result())
103
+ logger.debug(f"user began consuming result batch {i}")
104
+ i += 1
105
+ final()
106
+ else:
107
+ with create_pool_executor() as pool:
108
+ # Fill up window
109
+
110
+ logger.debug("beginning to schedule result batch downloads")
111
+
112
+ for _ in range(min(prefetch_thread_num, len(unfetched_batches))):
113
+ logger.debug(
114
+ f"queuing download of result batch id: {unfetched_batches[0].id}"
115
+ )
116
+ unconsumed_batches.append(
117
+ pool.submit(create_fetch_task(unfetched_batches.popleft()), **kw)
118
+ )
119
+
120
+ yield from first_batch_iter
121
+
122
+ i = 1
123
+ while unconsumed_batches:
124
+ logger.debug(f"user requesting to consume result batch {i}")
125
+
126
+ # Submit the next un-fetched batch to the pool
127
+ if unfetched_batches:
128
+ logger.debug(
129
+ f"queuing download of result batch id: {unfetched_batches[0].id}"
130
+ )
131
+ future = pool.submit(
132
+ create_fetch_task(unfetched_batches.popleft()), **kw
133
+ )
134
+ unconsumed_batches.append(future)
135
+
136
+ future = unconsumed_batches.popleft()
137
+
138
+ # this will raise an exception if one has occurred
139
+ batch_iterator = get_fetch_result(future.result())
140
+
141
+ logger.debug(f"user began consuming result batch {i}")
142
+ yield from batch_iterator
143
+ logger.debug(f"user finished consuming result batch {i}")
144
+
145
+ i += 1
146
+ final()
147
+
148
+
149
+ class ResultSet(Iterable[list]):
150
+ """This class retrieves the results of a query with the historical strategy.
151
+
152
+ It pre-downloads the first up to 4 ResultChunks (this doesn't include the 1st chunk
153
+ as that is embedded in the response JSON from Snowflake) upon creating an Iterator
154
+ on it.
155
+
156
+ It also reports telemetry data about its ``ResultBatch``es once it's done iterating
157
+ through them.
158
+
159
+ Currently we do not support mixing multiple ``ResultBatch`` types and having
160
+ different column definitions types per ``ResultBatch``.
161
+ """
162
+
163
+ def __init__(
164
+ self,
165
+ cursor: SnowflakeCursor,
166
+ result_chunks: list[JSONResultBatch] | list[ArrowResultBatch],
167
+ prefetch_thread_num: int,
168
+ use_mp: bool,
169
+ ) -> None:
170
+ self.batches = result_chunks
171
+ self._cursor = cursor
172
+ self.prefetch_thread_num = prefetch_thread_num
173
+ self._use_mp = use_mp
174
+
175
+ def _report_metrics(self) -> None:
176
+ """Report all metrics totalled up.
177
+
178
+ This includes TIME_CONSUME_LAST_RESULT, TIME_DOWNLOADING_CHUNKS and
179
+ TIME_PARSING_CHUNKS in that order.
180
+ """
181
+ if self._cursor._first_chunk_time is not None:
182
+ time_consume_last_result = (
183
+ get_time_millis() - self._cursor._first_chunk_time
184
+ )
185
+ self._cursor._log_telemetry_job_data(
186
+ TelemetryField.TIME_CONSUME_LAST_RESULT, time_consume_last_result
187
+ )
188
+ metrics = self._get_metrics()
189
+ if DownloadMetrics.download.value in metrics:
190
+ self._cursor._log_telemetry_job_data(
191
+ TelemetryField.TIME_DOWNLOADING_CHUNKS,
192
+ metrics.get(DownloadMetrics.download.value),
193
+ )
194
+ if DownloadMetrics.parse.value in metrics:
195
+ self._cursor._log_telemetry_job_data(
196
+ TelemetryField.TIME_PARSING_CHUNKS,
197
+ metrics.get(DownloadMetrics.parse.value),
198
+ )
199
+
200
+ def _finish_iterating(self) -> None:
201
+ """Used for any cleanup after the result set iterator is done."""
202
+
203
+ self._report_metrics()
204
+
205
+ def _can_create_arrow_iter(self) -> None:
206
+ # For now we don't support mixed ResultSets, so assume first partition's type
207
+ # represents them all
208
+ head_type = type(self.batches[0])
209
+ if head_type != ArrowResultBatch:
210
+ raise NotSupportedError(
211
+ f"Trying to use arrow fetching on {head_type} which "
212
+ f"is not ArrowResultChunk"
213
+ )
214
+
215
+ def _fetch_arrow_batches(
216
+ self,
217
+ ) -> Iterator[Table]:
218
+ """Fetches all the results as Arrow Tables, chunked by Snowflake back-end."""
219
+ self._can_create_arrow_iter()
220
+ return self._create_iter(iter_unit=IterUnit.TABLE_UNIT, structure="arrow")
221
+
222
+ @overload
223
+ def _fetch_arrow_all(self, force_return_table: Literal[False]) -> Table | None: ...
224
+
225
+ @overload
226
+ def _fetch_arrow_all(self, force_return_table: Literal[True]) -> Table: ...
227
+
228
+ def _fetch_arrow_all(self, force_return_table: bool = False) -> Table | None:
229
+ """Fetches a single Arrow Table from all of the ``ResultBatch``."""
230
+ tables = list(self._fetch_arrow_batches())
231
+ if tables:
232
+ return pa.concat_tables(tables)
233
+ else:
234
+ return self.batches[0].to_arrow() if force_return_table else None
235
+
236
+ def _fetch_pandas_batches(self, **kwargs) -> Iterator[DataFrame]:
237
+ """Fetches Pandas dataframes in batches, where batch refers to Snowflake Chunk.
238
+
239
+ Thus, the batch size (the number of rows in dataframe) is determined by
240
+ Snowflake's back-end.
241
+ """
242
+ self._can_create_arrow_iter()
243
+ return self._create_iter(
244
+ iter_unit=IterUnit.TABLE_UNIT, structure="pandas", **kwargs
245
+ )
246
+
247
+ def _fetch_pandas_all(self, **kwargs) -> DataFrame:
248
+ """Fetches a single Pandas dataframe."""
249
+ concat_args = list(inspect.signature(pandas.concat).parameters)
250
+ concat_kwargs = {k: kwargs.pop(k) for k in dict(kwargs) if k in concat_args}
251
+ dataframes = list(self._fetch_pandas_batches(is_fetch_all=True, **kwargs))
252
+ if dataframes:
253
+ return pandas.concat(
254
+ dataframes,
255
+ ignore_index=True, # Don't keep in result batch indexes
256
+ **concat_kwargs,
257
+ )
258
+ # Empty dataframe
259
+ return self.batches[0].to_pandas(**kwargs)
260
+
261
+ def _get_metrics(self) -> dict[str, int]:
262
+ """Sum up all the chunks' metrics and show them together."""
263
+ overall_metrics: dict[str, int] = {}
264
+ for c in self.batches:
265
+ for n, v in c._metrics.items():
266
+ overall_metrics[n] = overall_metrics.get(n, 0) + v
267
+ return overall_metrics
268
+
269
+ def __iter__(self) -> Iterator[tuple]:
270
+ """Returns a new iterator through all batches with default values."""
271
+ return self._create_iter()
272
+
273
+ def _create_iter(
274
+ self,
275
+ **kwargs,
276
+ ) -> (
277
+ Iterator[dict | Exception]
278
+ | Iterator[tuple | Exception]
279
+ | Iterator[Table]
280
+ | Iterator[DataFrame]
281
+ ):
282
+ """Set up a new iterator through all batches with first 5 chunks downloaded.
283
+
284
+ This function is a helper function to ``__iter__`` and it was introduced for the
285
+ cases where we need to propagate some values to later ``_download`` calls.
286
+ """
287
+ # pop is_fetch_all and pass it to result_set_iterator
288
+ is_fetch_all = kwargs.pop("is_fetch_all", False)
289
+
290
+ # add connection so that result batches can use sessions
291
+ kwargs["connection"] = self._cursor.connection
292
+
293
+ first_batch_iter = self.batches[0].create_iter(**kwargs)
294
+
295
+ # Iterator[Tuple] Futures that have not been consumed by the user
296
+ unconsumed_batches: Deque[Future[Iterator[tuple]]] = deque()
297
+
298
+ # batches that have not been fetched
299
+ unfetched_batches = deque(self.batches[1:])
300
+ for num, batch in enumerate(unfetched_batches):
301
+ logger.debug(f"result batch {num + 1} has id: {batch.id}")
302
+
303
+ return result_set_iterator(
304
+ first_batch_iter,
305
+ unconsumed_batches,
306
+ unfetched_batches,
307
+ self._finish_iterating,
308
+ self.prefetch_thread_num,
309
+ is_fetch_all=is_fetch_all,
310
+ use_mp=self._use_mp,
311
+ **kwargs,
312
+ )
313
+
314
+ def total_row_index(self) -> int:
315
+ """Returns the total rowcount of the ``ResultSet`` ."""
316
+ total = 0
317
+ for p in self.batches:
318
+ total += p.rowcount
319
+ return total