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,976 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import threading
5
+
6
+ from typing import Any
7
+
8
+ from snowflake.connector._internal.error_kinds import (
9
+ ERROR_KIND_AUTHENTICATION_ERROR,
10
+ ERROR_KIND_LABELS,
11
+ ERROR_KIND_LOGIN_ERROR,
12
+ ERROR_KIND_TIMEOUT,
13
+ KIND_TO_ERRNO,
14
+ KIND_TO_EXCEPTION,
15
+ VENDOR_CODE_TO_EXCEPTION,
16
+ )
17
+ from snowflake.connector.errors import DatabaseError, Error, OperationalError, ReauthenticationRequest
18
+
19
+ from ..protobuf_gen.database_driver_v1_pb2 import (
20
+ ColumnMetadata,
21
+ ConfigGetPathsRequest,
22
+ ConfigGetPathsResponse,
23
+ ConfigLoadAllSectionsRequest,
24
+ ConfigLoadAllSectionsResponse,
25
+ ConfigSetting,
26
+ ConnectionAbortQueryRequest,
27
+ ConnectionAbortQueryResponse,
28
+ ConnectionCloseRequest,
29
+ ConnectionCloseResponse,
30
+ ConnectionDownloadStreamBeginRequest,
31
+ ConnectionDownloadStreamBeginResponse,
32
+ ConnectionDownloadStreamChunkRequest,
33
+ ConnectionDownloadStreamChunkResponse,
34
+ ConnectionDownloadStreamCloseRequest,
35
+ ConnectionDownloadStreamCloseResponse,
36
+ ConnectionGetAllParametersRequest,
37
+ ConnectionGetAllParametersResponse,
38
+ ConnectionGetInfoRequest,
39
+ ConnectionGetInfoResponse,
40
+ ConnectionGetParameterRequest,
41
+ ConnectionGetParameterResponse,
42
+ ConnectionGetQueryResultRequest,
43
+ ConnectionGetQueryStatusRequest,
44
+ ConnectionGetQueryStatusResponse,
45
+ ConnectionGetResultSetRequest,
46
+ ConnectionHandle,
47
+ ConnectionHeartbeatRequest,
48
+ ConnectionHeartbeatResponse,
49
+ ConnectionInitRequest,
50
+ ConnectionInitResponse,
51
+ ConnectionIsClosedRequest,
52
+ ConnectionIsClosedResponse,
53
+ ConnectionIsExpiredRequest,
54
+ ConnectionIsExpiredResponse,
55
+ ConnectionNewRequest,
56
+ ConnectionNewResponse,
57
+ ConnectionReleaseRequest,
58
+ ConnectionReleaseResponse,
59
+ ConnectionSendHttpRequest,
60
+ ConnectionSendHttpResponse,
61
+ ConnectionSetOptionsRequest,
62
+ ConnectionSetOptionsResponse,
63
+ ConnectionSetSessionParametersRequest,
64
+ ConnectionSetSessionParametersResponse,
65
+ ConnectionTokenRequest,
66
+ ConnectionTokenResponse,
67
+ ConnectionUploadStreamAbortRequest,
68
+ ConnectionUploadStreamAbortResponse,
69
+ ConnectionUploadStreamBeginRequest,
70
+ ConnectionUploadStreamBeginResponse,
71
+ ConnectionUploadStreamChunkRequest,
72
+ ConnectionUploadStreamChunkResponse,
73
+ ConnectionUploadStreamFinishRequest,
74
+ ConnectionUploadStreamFinishResponse,
75
+ DatabaseFetchChunkRequest,
76
+ DatabaseFetchChunkResponse,
77
+ DatabaseHandle,
78
+ DatabaseInitRequest,
79
+ DatabaseInitResponse,
80
+ DatabaseNewRequest,
81
+ DatabaseNewResponse,
82
+ DatabaseReleaseRequest,
83
+ DatabaseReleaseResponse,
84
+ DownloadStreamHandle,
85
+ DriverGetFipsStatusRequest,
86
+ DriverGetFipsStatusResponse,
87
+ ExecuteQueryResponse,
88
+ QueryBindings,
89
+ ResultChunk,
90
+ ResultSetGetChunksRequest,
91
+ ResultSetGetChunksResponse,
92
+ ResultSetGetStreamRequest,
93
+ ResultSetGetStreamResponse,
94
+ ResultSetHandle,
95
+ ResultSetReleaseRequest,
96
+ ResultSetReleaseResponse,
97
+ ResultSetResponse,
98
+ StatementExecuteAsyncRequest,
99
+ StatementExecuteAsyncResponse,
100
+ StatementExecuteQueryRequest,
101
+ StatementHandle,
102
+ StatementNewRequest,
103
+ StatementNewResponse,
104
+ StatementPrepareRequest,
105
+ StatementPrepareResponse,
106
+ StatementReleaseRequest,
107
+ StatementReleaseResponse,
108
+ StatementSetOptionsRequest,
109
+ StatementSetOptionsResponse,
110
+ StatementSetSqlQueryRequest,
111
+ StatementSetSqlQueryResponse,
112
+ TelemetrySendApiUsageRequest,
113
+ TelemetrySendLogRequest,
114
+ TelemetrySendResponse,
115
+ TelemetrySendWrapperErrorRequest,
116
+ TokenRequestType,
117
+ UploadStreamHandle,
118
+ WifCreateAttestationRequest,
119
+ WifCreateAttestationResponse,
120
+ WrapperIdentity,
121
+ )
122
+ from ..protobuf_gen.database_driver_v1_services import AsyncDatabaseDriverClient, DatabaseDriverClient
123
+ from ..protobuf_gen.proto_exception import (
124
+ ProtoApplicationException,
125
+ ProtoTransportException,
126
+ )
127
+ from .bridge import ProtoTransport
128
+
129
+
130
+ # Chunk size for ConnectionUploadStreamChunk; bounds wrapper memory to ~one
131
+ # chunk. Matches JDBC's chunked upload default.
132
+ CHUNK_SIZE = 8 * 1024 * 1024
133
+
134
+
135
+ # ---------------------------------------------------------------------------
136
+ # Proto-to-PEP-249 error conversion (kept here, at the transport boundary)
137
+ # ---------------------------------------------------------------------------
138
+
139
+
140
+ def _stringify_session_parameters(parameters: dict[str, Any]) -> dict[str, str]:
141
+ """Coerce session parameter values to ``str`` for the string-only protobuf map.
142
+
143
+ Legacy ``snowflake-connector-python`` forwards ``session_parameters`` values
144
+ as-is (bool/int/str/float), but ``ConnectionSetSessionParametersRequest.parameters``
145
+ is a ``map<string, string>``, so non-string values must be coerced here.
146
+ ``str`` values pass through unchanged; everything else goes through
147
+ ``json.dumps`` so it round-trips (``bool`` -> lowercase ``"true"``/``"false"``,
148
+ ``None`` -> ``"null"``, etc.) rather than serializing as a Python repr.
149
+ """
150
+ return {key: (value if isinstance(value, str) else json.dumps(value)) for key, value in parameters.items()}
151
+
152
+
153
+ def _is_reauthentication_required(driver_exception: Any) -> bool:
154
+ """Return whether *driver_exception* is a reauth-shaped error.
155
+
156
+ ``reauthentication_required`` is a plain bool on ``DriverException`` after
157
+ the DriverError flatten. The GS code, when there is one, travels on
158
+ ``vendor_code``.
159
+ """
160
+ return bool(getattr(driver_exception, "reauthentication_required", False))
161
+
162
+
163
+ def _append_detail(base: str, detail: str) -> str:
164
+ """Append *detail* to *base* with `. ` separator, avoiding double punctuation."""
165
+ if not base:
166
+ return detail
167
+ base = base.rstrip(".")
168
+ return f"{base}. {detail}"
169
+
170
+
171
+ def _proto_to_public_error(proto_exc: Exception) -> Error:
172
+ """Convert a proto-layer exception into a PEP 249 ``Error`` subclass.
173
+
174
+ This function **returns** the converted exception; it does not raise it.
175
+ The caller (``_raise_error`` in the generated client) is responsible for
176
+ raising the returned value.
177
+ """
178
+ if isinstance(proto_exc, ProtoApplicationException):
179
+ return _convert_application_error(proto_exc)
180
+ if isinstance(proto_exc, ProtoTransportException):
181
+ return OperationalError(f"Driver communication error: {proto_exc}")
182
+ return DatabaseError(str(proto_exc))
183
+
184
+
185
+ def _resolve_exception_class(kind: int, vendor_code: int | None, reauthentication_required: bool) -> type[Error]:
186
+ """Pick the PEP 249 exception class for a proto error.
187
+
188
+ Resolution order:
189
+ 1. ``reauthentication_required`` — the session can never be renewed
190
+ regardless of what ErrorKind/vendor_code the Rust core also
191
+ reported, so this wins unconditionally.
192
+ 2. VENDOR_CODE_TO_EXCEPTION — Snowflake-specific vendor_code overrides (e.g. 100072 → IntegrityError).
193
+ 3. KIND_TO_EXCEPTION — default mapping from the proto ErrorKind.
194
+ 4. DatabaseError — catch-all when the kind is unrecognized.
195
+ """
196
+ if reauthentication_required:
197
+ return ReauthenticationRequest
198
+ if vendor_code is not None:
199
+ cls = VENDOR_CODE_TO_EXCEPTION.get(vendor_code)
200
+ if cls is not None:
201
+ return cls
202
+ return KIND_TO_EXCEPTION.get(kind, DatabaseError)
203
+
204
+
205
+ def _convert_application_error(proto_exc: ProtoApplicationException) -> Error:
206
+ driver_exc = getattr(proto_exc, "api_error_pb", None)
207
+ if driver_exc is None:
208
+ return DatabaseError(str(proto_exc))
209
+
210
+ kind = getattr(driver_exc, "kind", 0)
211
+ message = getattr(driver_exc, "message", "") or ""
212
+
213
+ # The root_cause field carries the deepest error in the chain from the
214
+ # Rust core, which is typically the most informative for end users.
215
+ root_cause = _get_optional_str(driver_exc, "root_cause")
216
+ if root_cause and root_cause not in message:
217
+ message = _append_detail(message, root_cause)
218
+
219
+ if not message:
220
+ message = ERROR_KIND_LABELS.get(kind, "Unknown error")
221
+
222
+ # Prefer the Snowflake server vendor_code when the core driver provides it
223
+ # (e.g. 1003 for syntax error, 904 for invalid identifier).
224
+ # Fall back to the old-driver-compatible errno mapping, then to the raw
225
+ # proto ErrorKind.
226
+ vendor_code = _get_optional_int(driver_exc, "vendor_code")
227
+
228
+ exc_class = _resolve_exception_class(kind, vendor_code, _is_reauthentication_required(driver_exc))
229
+ errno = vendor_code if vendor_code is not None else KIND_TO_ERRNO.get(kind, kind)
230
+
231
+ # Prefer the server-provided sql_state; fall back to a type-derived value.
232
+ sqlstate = _get_optional_str(driver_exc, "sql_state") or _derive_sqlstate(driver_exc)
233
+
234
+ sfqid = _get_optional_str(driver_exc, "query_id")
235
+
236
+ # Client-generated requestId used for the query submission, when the error
237
+ # originated from a query execution attempt.
238
+ request_id = _get_optional_str(driver_exc, "request_id")
239
+
240
+ # Structured extras for parameter errors (e.g. connection-config validation),
241
+ # so callers can discriminate without matching message text.
242
+ parameter = _get_optional_str(driver_exc, "parameter")
243
+ validation_code = _get_optional_int(driver_exc, "validation_code")
244
+
245
+ return exc_class(
246
+ message,
247
+ errno=errno,
248
+ sqlstate=sqlstate,
249
+ sfqid=sfqid,
250
+ request_id=request_id,
251
+ parameter=parameter,
252
+ validation_code=validation_code,
253
+ )
254
+
255
+
256
+ def _get_optional_int(msg: Any, field: str) -> int | None:
257
+ """Read an optional int32 proto field, returning None if not set."""
258
+ try:
259
+ if msg.HasField(field):
260
+ return int(getattr(msg, field))
261
+ except (ValueError, TypeError, AttributeError):
262
+ # Field missing from the proto schema or cannot be coerced to int; treat as unset.
263
+ pass
264
+ return None
265
+
266
+
267
+ def _get_optional_str(msg: Any, field: str) -> str | None:
268
+ """Read an optional string proto field, returning None if not set."""
269
+ try:
270
+ if msg.HasField(field):
271
+ return str(getattr(msg, field)) or None
272
+ except (ValueError, TypeError, AttributeError):
273
+ # Field missing from the proto schema or cannot be coerced to string; treat as unset.
274
+ pass
275
+ return None
276
+
277
+
278
+ def _derive_sqlstate(driver_exception: Any) -> str | None:
279
+ """Derive sqlstate from ErrorKind when the proto does not carry it."""
280
+ kind = getattr(driver_exception, "kind", 0)
281
+ if kind in (ERROR_KIND_LOGIN_ERROR, ERROR_KIND_AUTHENTICATION_ERROR):
282
+ return "08001" # SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED
283
+ if kind == ERROR_KIND_TIMEOUT:
284
+ return "HYT00"
285
+ return None
286
+
287
+
288
+ # ---------------------------------------------------------------------------
289
+ # CoreDriver facade (process-wide singleton)
290
+ # ---------------------------------------------------------------------------
291
+
292
+
293
+ class CoreDriver:
294
+ """Process-wide facade over ``DatabaseDriverClient``.
295
+
296
+ Lazily initializes the underlying protobuf client on first access
297
+ (thread-safe, double-checked lock) and exposes domain-level methods that
298
+ encapsulate all protobuf request construction so that callers never touch
299
+ ``*Request`` objects directly.
300
+ """
301
+
302
+ def __init__(self) -> None:
303
+ self._client: DatabaseDriverClient | None = None
304
+ self._lock = threading.Lock()
305
+
306
+ @property
307
+ def client(self) -> DatabaseDriverClient:
308
+ if self._client is not None:
309
+ return self._client
310
+
311
+ with self._lock:
312
+ if self._client is None:
313
+ self._client = DatabaseDriverClient(ProtoTransport(), error_handler=_proto_to_public_error)
314
+
315
+ return self._client
316
+
317
+ @client.setter
318
+ def client(self, client: DatabaseDriverClient | None) -> None:
319
+ self._client = client
320
+
321
+ # =====================================================================
322
+ # Driver status
323
+ # =====================================================================
324
+
325
+ def driver_get_fips_status(self) -> DriverGetFipsStatusResponse:
326
+ return self.client.driver_get_fips_status(DriverGetFipsStatusRequest())
327
+
328
+ # =====================================================================
329
+ # Database lifecycle
330
+ # =====================================================================
331
+
332
+ def database_new(self) -> DatabaseNewResponse:
333
+ request = DatabaseNewRequest()
334
+ return self.client.database_new(request)
335
+
336
+ def database_init(self, db_handle: DatabaseHandle) -> DatabaseInitResponse:
337
+ request = DatabaseInitRequest(db_handle=db_handle)
338
+ return self.client.database_init(request)
339
+
340
+ def database_release(self, db_handle: DatabaseHandle) -> DatabaseReleaseResponse:
341
+ request = DatabaseReleaseRequest(db_handle=db_handle)
342
+ return self.client.database_release(request)
343
+
344
+ # =====================================================================
345
+ # Connection lifecycle
346
+ # =====================================================================
347
+
348
+ def connection_new(self) -> ConnectionNewResponse:
349
+ request = ConnectionNewRequest()
350
+ return self.client.connection_new(request)
351
+
352
+ def connection_init(
353
+ self,
354
+ conn_handle: ConnectionHandle,
355
+ db_handle: DatabaseHandle,
356
+ wrapper_identity: WrapperIdentity,
357
+ ) -> ConnectionInitResponse:
358
+ request = ConnectionInitRequest(
359
+ conn_handle=conn_handle,
360
+ db_handle=db_handle,
361
+ wrapper_identity=wrapper_identity,
362
+ )
363
+ return self.client.connection_init(request)
364
+
365
+ def connection_set_options(
366
+ self,
367
+ conn_handle: ConnectionHandle,
368
+ options: dict[str, ConfigSetting],
369
+ no_connection_details: bool = False,
370
+ connections_file_path: str | None = None,
371
+ ) -> ConnectionSetOptionsResponse:
372
+ request = ConnectionSetOptionsRequest(
373
+ conn_handle=conn_handle,
374
+ options=options,
375
+ no_connection_details=no_connection_details,
376
+ connections_file_path=connections_file_path,
377
+ )
378
+ return self.client.connection_set_options(request)
379
+
380
+ def connection_set_session_parameters(
381
+ self, conn_handle: ConnectionHandle, parameters: dict[str, Any]
382
+ ) -> ConnectionSetSessionParametersResponse:
383
+ request = ConnectionSetSessionParametersRequest(
384
+ conn_handle=conn_handle, parameters=_stringify_session_parameters(parameters)
385
+ )
386
+ return self.client.connection_set_session_parameters(request)
387
+
388
+ def connection_close(self, conn_handle: ConnectionHandle) -> ConnectionCloseResponse:
389
+ request = ConnectionCloseRequest(conn_handle=conn_handle)
390
+ return self.client.connection_close(request)
391
+
392
+ def connection_release(self, conn_handle: ConnectionHandle) -> ConnectionReleaseResponse:
393
+ request = ConnectionReleaseRequest(conn_handle=conn_handle)
394
+ return self.client.connection_release(request)
395
+
396
+ def connection_is_closed(self, conn_handle: ConnectionHandle) -> ConnectionIsClosedResponse:
397
+ request = ConnectionIsClosedRequest(conn_handle=conn_handle)
398
+ return self.client.connection_is_closed(request)
399
+
400
+ def connection_is_expired(self, conn_handle: ConnectionHandle) -> ConnectionIsExpiredResponse:
401
+ request = ConnectionIsExpiredRequest(conn_handle=conn_handle)
402
+ return self.client.connection_is_expired(request)
403
+
404
+ def connection_heartbeat(self, conn_handle: ConnectionHandle) -> ConnectionHeartbeatResponse:
405
+ request = ConnectionHeartbeatRequest(conn_handle=conn_handle)
406
+ return self.client.connection_heartbeat(request)
407
+
408
+ def connection_get_info(
409
+ self,
410
+ conn_handle: ConnectionHandle,
411
+ include_master_token: bool = False,
412
+ ) -> ConnectionGetInfoResponse:
413
+ request = ConnectionGetInfoRequest(conn_handle=conn_handle, include_master_token=include_master_token)
414
+ return self.client.connection_get_info(request)
415
+
416
+ def connection_get_query_status(
417
+ self, conn_handle: ConnectionHandle, query_id: str
418
+ ) -> ConnectionGetQueryStatusResponse:
419
+ request = ConnectionGetQueryStatusRequest(conn_handle=conn_handle, query_id=query_id)
420
+ return self.client.connection_get_query_status(request)
421
+
422
+ # =====================================================================
423
+ # Connection data
424
+ # =====================================================================
425
+
426
+ def connection_get_result_set(self, conn_handle: ConnectionHandle, query_id: str) -> ResultSetResponse:
427
+ request = ConnectionGetResultSetRequest(conn_handle=conn_handle, query_id=query_id)
428
+ return self.client.connection_get_result_set(request)
429
+
430
+ def connection_get_query_result(self, conn_handle: ConnectionHandle, query_id: str) -> ExecuteQueryResponse:
431
+ request = ConnectionGetQueryResultRequest(conn_handle=conn_handle, query_id=query_id)
432
+ return self.client.connection_get_query_result(request)
433
+
434
+ def connection_abort_query(self, conn_handle: ConnectionHandle, query_id: str) -> ConnectionAbortQueryResponse:
435
+ request = ConnectionAbortQueryRequest(conn_handle=conn_handle, query_id=query_id)
436
+ return self.client.connection_abort_query(request)
437
+
438
+ def connection_send_http(
439
+ self,
440
+ conn_handle: ConnectionHandle,
441
+ method: str,
442
+ url: str,
443
+ headers: dict[str, str],
444
+ body: bytes | None = None,
445
+ ) -> ConnectionSendHttpResponse:
446
+ request = ConnectionSendHttpRequest(
447
+ conn_handle=conn_handle,
448
+ method=method,
449
+ url=url,
450
+ headers=headers,
451
+ body=body,
452
+ )
453
+ return self.client.connection_send_http(request)
454
+
455
+ # =====================================================================
456
+ # Connection chunked upload streaming (PUT)
457
+ # =====================================================================
458
+
459
+ def upload_stream_begin(self, conn_handle: ConnectionHandle, sql: str) -> ConnectionUploadStreamBeginResponse:
460
+ request = ConnectionUploadStreamBeginRequest(conn_handle=conn_handle, sql=sql)
461
+ return self.client.connection_upload_stream_begin(request)
462
+
463
+ def upload_stream_chunk(
464
+ self, upload_handle: UploadStreamHandle, data: bytes
465
+ ) -> ConnectionUploadStreamChunkResponse:
466
+ request = ConnectionUploadStreamChunkRequest(upload_handle=upload_handle, data=data)
467
+ return self.client.connection_upload_stream_chunk(request)
468
+
469
+ def upload_stream_finish(self, upload_handle: UploadStreamHandle) -> ConnectionUploadStreamFinishResponse:
470
+ request = ConnectionUploadStreamFinishRequest(upload_handle=upload_handle)
471
+ return self.client.connection_upload_stream_finish(request)
472
+
473
+ def upload_stream_abort(self, upload_handle: UploadStreamHandle) -> ConnectionUploadStreamAbortResponse:
474
+ request = ConnectionUploadStreamAbortRequest(upload_handle=upload_handle)
475
+ return self.client.connection_upload_stream_abort(request)
476
+
477
+ def download_stream_begin(
478
+ self, conn_handle: ConnectionHandle, stage_name: str, source_filename: str, decompress: bool
479
+ ) -> ConnectionDownloadStreamBeginResponse:
480
+ request = ConnectionDownloadStreamBeginRequest(
481
+ conn_handle=conn_handle,
482
+ stage_name=stage_name,
483
+ source_filename=source_filename,
484
+ decompress=decompress,
485
+ )
486
+ return self.client.connection_download_stream_begin(request)
487
+
488
+ def download_stream_chunk(
489
+ self, download_handle: DownloadStreamHandle, max_len: int
490
+ ) -> ConnectionDownloadStreamChunkResponse:
491
+ request = ConnectionDownloadStreamChunkRequest(download_handle=download_handle, max_len=max_len)
492
+ return self.client.connection_download_stream_chunk(request)
493
+
494
+ def download_stream_close(self, download_handle: DownloadStreamHandle) -> ConnectionDownloadStreamCloseResponse:
495
+ request = ConnectionDownloadStreamCloseRequest(download_handle=download_handle)
496
+ return self.client.connection_download_stream_close(request)
497
+
498
+ # =====================================================================
499
+ # Connection tokens/params
500
+ # =====================================================================
501
+
502
+ def connection_request_token(
503
+ self, conn_handle: ConnectionHandle, request_type: TokenRequestType.ValueType
504
+ ) -> ConnectionTokenResponse:
505
+ request = ConnectionTokenRequest(conn_handle=conn_handle, request_type=request_type)
506
+ return self.client.connection_request_token(request)
507
+
508
+ def connection_get_parameter(self, conn_handle: ConnectionHandle, key: str) -> ConnectionGetParameterResponse:
509
+ request = ConnectionGetParameterRequest(conn_handle=conn_handle, key=key)
510
+ return self.client.connection_get_parameter(request)
511
+
512
+ def connection_get_all_parameters(self, conn_handle: ConnectionHandle) -> ConnectionGetAllParametersResponse:
513
+ request = ConnectionGetAllParametersRequest(conn_handle=conn_handle)
514
+ return self.client.connection_get_all_parameters(request)
515
+
516
+ # =====================================================================
517
+ # Statement lifecycle
518
+ # =====================================================================
519
+
520
+ def statement_new(self, conn_handle: ConnectionHandle) -> StatementNewResponse:
521
+ request = StatementNewRequest(conn_handle=conn_handle)
522
+ return self.client.statement_new(request)
523
+
524
+ def statement_set_query(self, stmt_handle: StatementHandle, query: str) -> StatementSetSqlQueryResponse:
525
+ request = StatementSetSqlQueryRequest(stmt_handle=stmt_handle, query=query)
526
+ return self.client.statement_set_sql_query(request)
527
+
528
+ def statement_release(self, stmt_handle: StatementHandle) -> StatementReleaseResponse:
529
+ request = StatementReleaseRequest(stmt_handle=stmt_handle)
530
+ return self.client.statement_release(request)
531
+
532
+ def statement_set_options(
533
+ self, stmt_handle: StatementHandle, options: dict[str, ConfigSetting]
534
+ ) -> StatementSetOptionsResponse:
535
+ request = StatementSetOptionsRequest(stmt_handle=stmt_handle, options=options)
536
+ return self.client.statement_set_options(request)
537
+
538
+ def statement_execute_query(
539
+ self, stmt_handle: StatementHandle, bindings: QueryBindings | None = None
540
+ ) -> ExecuteQueryResponse:
541
+ request = StatementExecuteQueryRequest(stmt_handle=stmt_handle, bindings=bindings)
542
+ return self.client.statement_execute_query(request)
543
+
544
+ def statement_execute_async(
545
+ self, stmt_handle: StatementHandle, bindings: QueryBindings | None = None
546
+ ) -> StatementExecuteAsyncResponse:
547
+ request = StatementExecuteAsyncRequest(stmt_handle=stmt_handle, bindings=bindings)
548
+ return self.client.statement_execute_async(request)
549
+
550
+ def statement_prepare(
551
+ self, stmt_handle: StatementHandle, bindings: QueryBindings | None = None
552
+ ) -> StatementPrepareResponse:
553
+ request = StatementPrepareRequest(stmt_handle=stmt_handle, bindings=bindings)
554
+ return self.client.statement_prepare(request)
555
+
556
+ # =====================================================================
557
+ # Result set
558
+ # =====================================================================
559
+
560
+ def result_set_release(self, result_set_handle: ResultSetHandle) -> ResultSetReleaseResponse:
561
+ request = ResultSetReleaseRequest(result_set_handle=result_set_handle)
562
+ return self.client.result_set_release(request)
563
+
564
+ def result_set_get_stream(self, result_set_handle: ResultSetHandle) -> ResultSetGetStreamResponse:
565
+ request = ResultSetGetStreamRequest(result_set_handle=result_set_handle)
566
+ return self.client.result_set_get_stream(request)
567
+
568
+ def result_set_get_chunks(self, result_set_handle: ResultSetHandle) -> ResultSetGetChunksResponse:
569
+ request = ResultSetGetChunksRequest(result_set_handle=result_set_handle)
570
+ return self.client.result_set_get_chunks(request)
571
+
572
+ # =====================================================================
573
+ # Database fetch
574
+ # =====================================================================
575
+
576
+ def database_fetch_chunk(
577
+ self,
578
+ conn_handle: ConnectionHandle | None,
579
+ chunk: ResultChunk,
580
+ columns: list[ColumnMetadata],
581
+ ) -> DatabaseFetchChunkResponse:
582
+ request = DatabaseFetchChunkRequest(conn_handle=conn_handle, chunks=[chunk], columns=columns)
583
+ return self.client.database_fetch_chunk(request)
584
+
585
+ # =====================================================================
586
+ # Telemetry
587
+ # =====================================================================
588
+
589
+ def telemetry_send_api_usage(
590
+ self, conn_handle: ConnectionHandle, api_method: str, passed_arguments: list[str] | None = None
591
+ ) -> TelemetrySendResponse:
592
+ request = TelemetrySendApiUsageRequest(
593
+ conn_handle=conn_handle, api_method=api_method, passed_arguments=passed_arguments or []
594
+ )
595
+ return self.client.telemetry_send_api_usage(request)
596
+
597
+ def telemetry_send_wrapper_error(
598
+ self, conn_handle: ConnectionHandle, exception_type: str, error_source: str
599
+ ) -> TelemetrySendResponse:
600
+ request = TelemetrySendWrapperErrorRequest(
601
+ conn_handle=conn_handle,
602
+ exception_type=exception_type,
603
+ error_source=error_source,
604
+ )
605
+ return self.client.telemetry_send_wrapper_error(request)
606
+
607
+ def telemetry_send_log(
608
+ self, conn_handle: ConnectionHandle, message_json: str, timestamp_ms: int
609
+ ) -> TelemetrySendResponse:
610
+ request = TelemetrySendLogRequest(conn_handle=conn_handle, message_json=message_json, timestamp_ms=timestamp_ms)
611
+ return self.client.telemetry_send_log(request)
612
+
613
+ # =====================================================================
614
+ # Config
615
+ # =====================================================================
616
+
617
+ def config_load_all_sections(
618
+ self,
619
+ config_file: str,
620
+ connections_file: str | None = None,
621
+ skip_permissions: bool = False,
622
+ ) -> ConfigLoadAllSectionsResponse:
623
+ request = ConfigLoadAllSectionsRequest(
624
+ config_file=config_file,
625
+ connections_file=connections_file,
626
+ skip_permissions=skip_permissions,
627
+ )
628
+ return self.client.config_load_all_sections(request)
629
+
630
+ def config_get_paths(self) -> ConfigGetPathsResponse:
631
+ request = ConfigGetPathsRequest()
632
+ return self.client.config_get_paths(request)
633
+
634
+ # =====================================================================
635
+ # Workload Identity Federation (WIF)
636
+ # =====================================================================
637
+
638
+ def wif_create_attestation(
639
+ self,
640
+ provider: str,
641
+ entra_resource: str | None = None,
642
+ token: str | None = None,
643
+ impersonation_path: list[str] | None = None,
644
+ aws_use_outbound_token: bool | None = None,
645
+ wif_host: str | None = None,
646
+ ) -> WifCreateAttestationResponse:
647
+ request = WifCreateAttestationRequest(
648
+ provider=provider,
649
+ entra_resource=entra_resource,
650
+ token=token,
651
+ impersonation_path=impersonation_path or [],
652
+ aws_use_outbound_token=aws_use_outbound_token,
653
+ wif_host=wif_host,
654
+ )
655
+ return self.client.wif_create_attestation(request)
656
+
657
+
658
+ core_driver: CoreDriver = CoreDriver()
659
+
660
+
661
+ # ---------------------------------------------------------------------------
662
+ # async CoreDriver facade (process-wide singleton)
663
+ # ---------------------------------------------------------------------------
664
+
665
+
666
+ class AsyncCoreDriver:
667
+ """Async-native facade over :class:`DatabaseDriverClient`.
668
+
669
+ Mirrors :class:`CoreDriver` but exposes ``async def`` methods. Will
670
+ eventually replace ``CoreDriver`` once the codebase is fully async-first;
671
+ for now both coexist — sync callers go through ``core_driver``,
672
+ async-native callers go through ``async_core_driver``.
673
+
674
+ Both facades share the process-wide :data:`_proto_transport`.
675
+
676
+ Lazily initializes its underlying :class:`DatabaseDriverClient` on first
677
+ access (thread-safe, double-checked lock). Tests can inject a mock by
678
+ assigning to the ``client`` setter.
679
+
680
+ Exposes the async methods needed by the async cursor and connection layers;
681
+ extend as new async callers appear.
682
+ """
683
+
684
+ def __init__(self) -> None:
685
+ self._client: AsyncDatabaseDriverClient | None = None
686
+ self._lock = threading.Lock()
687
+
688
+ @property
689
+ def client(self) -> AsyncDatabaseDriverClient:
690
+ if self._client is not None:
691
+ return self._client
692
+ with self._lock:
693
+ if self._client is None:
694
+ self._client = AsyncDatabaseDriverClient(
695
+ ProtoTransport(),
696
+ error_handler=_proto_to_public_error,
697
+ )
698
+ return self._client
699
+
700
+ @client.setter
701
+ def client(self, client: AsyncDatabaseDriverClient | None) -> None:
702
+ self._client = client
703
+
704
+ # =====================================================================
705
+ # Database lifecycle
706
+ # =====================================================================
707
+
708
+ async def database_new(self) -> DatabaseNewResponse:
709
+ return await self.client.database_new(DatabaseNewRequest())
710
+
711
+ async def database_init(self, db_handle: DatabaseHandle) -> DatabaseInitResponse:
712
+ return await self.client.database_init(DatabaseInitRequest(db_handle=db_handle))
713
+
714
+ async def database_release(self, db_handle: DatabaseHandle) -> DatabaseReleaseResponse:
715
+ return await self.client.database_release(DatabaseReleaseRequest(db_handle=db_handle))
716
+
717
+ # =====================================================================
718
+ # Connection lifecycle
719
+ # =====================================================================
720
+
721
+ async def connection_new(self) -> ConnectionNewResponse:
722
+ return await self.client.connection_new(ConnectionNewRequest())
723
+
724
+ async def connection_init(
725
+ self,
726
+ conn_handle: ConnectionHandle,
727
+ db_handle: DatabaseHandle,
728
+ wrapper_identity: WrapperIdentity,
729
+ ) -> ConnectionInitResponse:
730
+ return await self.client.connection_init(
731
+ ConnectionInitRequest(
732
+ conn_handle=conn_handle,
733
+ db_handle=db_handle,
734
+ wrapper_identity=wrapper_identity,
735
+ )
736
+ )
737
+
738
+ async def connection_set_options(
739
+ self,
740
+ conn_handle: ConnectionHandle,
741
+ options: dict[str, ConfigSetting],
742
+ no_connection_details: bool = False,
743
+ connections_file_path: str | None = None,
744
+ ) -> ConnectionSetOptionsResponse:
745
+ return await self.client.connection_set_options(
746
+ ConnectionSetOptionsRequest(
747
+ conn_handle=conn_handle,
748
+ options=options,
749
+ no_connection_details=no_connection_details,
750
+ connections_file_path=connections_file_path,
751
+ )
752
+ )
753
+
754
+ async def connection_set_session_parameters(
755
+ self, conn_handle: ConnectionHandle, parameters: dict[str, Any]
756
+ ) -> ConnectionSetSessionParametersResponse:
757
+ return await self.client.connection_set_session_parameters(
758
+ ConnectionSetSessionParametersRequest(
759
+ conn_handle=conn_handle, parameters=_stringify_session_parameters(parameters)
760
+ )
761
+ )
762
+
763
+ async def connection_close(self, conn_handle: ConnectionHandle) -> ConnectionCloseResponse:
764
+ return await self.client.connection_close(ConnectionCloseRequest(conn_handle=conn_handle))
765
+
766
+ async def connection_release(self, conn_handle: ConnectionHandle) -> ConnectionReleaseResponse:
767
+ return await self.client.connection_release(ConnectionReleaseRequest(conn_handle=conn_handle))
768
+
769
+ async def connection_is_closed(self, conn_handle: ConnectionHandle) -> ConnectionIsClosedResponse:
770
+ return await self.client.connection_is_closed(ConnectionIsClosedRequest(conn_handle=conn_handle))
771
+
772
+ async def connection_is_expired(self, conn_handle: ConnectionHandle) -> ConnectionIsExpiredResponse:
773
+ return await self.client.connection_is_expired(ConnectionIsExpiredRequest(conn_handle=conn_handle))
774
+
775
+ async def connection_heartbeat(self, conn_handle: ConnectionHandle) -> ConnectionHeartbeatResponse:
776
+ return await self.client.connection_heartbeat(ConnectionHeartbeatRequest(conn_handle=conn_handle))
777
+
778
+ async def connection_get_query_status(
779
+ self, conn_handle: ConnectionHandle, query_id: str
780
+ ) -> ConnectionGetQueryStatusResponse:
781
+ return await self.client.connection_get_query_status(
782
+ ConnectionGetQueryStatusRequest(conn_handle=conn_handle, query_id=query_id)
783
+ )
784
+
785
+ async def connection_send_http(
786
+ self,
787
+ conn_handle: ConnectionHandle,
788
+ method: str,
789
+ url: str,
790
+ headers: dict[str, str],
791
+ body: bytes | None = None,
792
+ ) -> ConnectionSendHttpResponse:
793
+ return await self.client.connection_send_http(
794
+ ConnectionSendHttpRequest(
795
+ conn_handle=conn_handle,
796
+ method=method,
797
+ url=url,
798
+ headers=headers,
799
+ body=body,
800
+ )
801
+ )
802
+
803
+ async def connection_request_token(
804
+ self, conn_handle: ConnectionHandle, request_type: TokenRequestType.ValueType
805
+ ) -> ConnectionTokenResponse:
806
+ return await self.client.connection_request_token(
807
+ ConnectionTokenRequest(conn_handle=conn_handle, request_type=request_type)
808
+ )
809
+
810
+ # =====================================================================
811
+ # Connection chunked upload streaming (PUT)
812
+ # =====================================================================
813
+
814
+ async def upload_stream_begin(self, conn_handle: ConnectionHandle, sql: str) -> ConnectionUploadStreamBeginResponse:
815
+ return await self.client.connection_upload_stream_begin(
816
+ ConnectionUploadStreamBeginRequest(conn_handle=conn_handle, sql=sql)
817
+ )
818
+
819
+ async def upload_stream_chunk(
820
+ self, upload_handle: UploadStreamHandle, data: bytes
821
+ ) -> ConnectionUploadStreamChunkResponse:
822
+ return await self.client.connection_upload_stream_chunk(
823
+ ConnectionUploadStreamChunkRequest(upload_handle=upload_handle, data=data)
824
+ )
825
+
826
+ async def upload_stream_finish(self, upload_handle: UploadStreamHandle) -> ConnectionUploadStreamFinishResponse:
827
+ return await self.client.connection_upload_stream_finish(
828
+ ConnectionUploadStreamFinishRequest(upload_handle=upload_handle)
829
+ )
830
+
831
+ async def upload_stream_abort(self, upload_handle: UploadStreamHandle) -> ConnectionUploadStreamAbortResponse:
832
+ return await self.client.connection_upload_stream_abort(
833
+ ConnectionUploadStreamAbortRequest(upload_handle=upload_handle)
834
+ )
835
+
836
+ # =====================================================================
837
+ # Telemetry
838
+ # =====================================================================
839
+
840
+ async def telemetry_send_api_usage(
841
+ self, conn_handle: ConnectionHandle, api_method: str, passed_arguments: list[str] | None = None
842
+ ) -> TelemetrySendResponse:
843
+ return await self.client.telemetry_send_api_usage(
844
+ TelemetrySendApiUsageRequest(
845
+ conn_handle=conn_handle, api_method=api_method, passed_arguments=passed_arguments or []
846
+ )
847
+ )
848
+
849
+ async def telemetry_send_wrapper_error(
850
+ self, conn_handle: ConnectionHandle, exception_type: str, error_source: str
851
+ ) -> TelemetrySendResponse:
852
+ return await self.client.telemetry_send_wrapper_error(
853
+ TelemetrySendWrapperErrorRequest(
854
+ conn_handle=conn_handle,
855
+ exception_type=exception_type,
856
+ error_source=error_source,
857
+ )
858
+ )
859
+
860
+ async def telemetry_send_log(
861
+ self, conn_handle: ConnectionHandle, message_json: str, timestamp_ms: int
862
+ ) -> TelemetrySendResponse:
863
+ return await self.client.telemetry_send_log(
864
+ TelemetrySendLogRequest(
865
+ conn_handle=conn_handle,
866
+ message_json=message_json,
867
+ timestamp_ms=timestamp_ms,
868
+ )
869
+ )
870
+
871
+ # =====================================================================
872
+ # Statement lifecycle (cursor execute path)
873
+ # =====================================================================
874
+
875
+ async def statement_new(self, conn_handle: ConnectionHandle) -> StatementNewResponse:
876
+ return await self.client.statement_new(StatementNewRequest(conn_handle=conn_handle))
877
+
878
+ async def statement_set_query(self, stmt_handle: StatementHandle, query: str) -> StatementSetSqlQueryResponse:
879
+ return await self.client.statement_set_sql_query(
880
+ StatementSetSqlQueryRequest(stmt_handle=stmt_handle, query=query)
881
+ )
882
+
883
+ async def statement_release(self, stmt_handle: StatementHandle) -> StatementReleaseResponse:
884
+ return await self.client.statement_release(StatementReleaseRequest(stmt_handle=stmt_handle))
885
+
886
+ async def statement_set_options(
887
+ self, stmt_handle: StatementHandle, options: dict[str, ConfigSetting]
888
+ ) -> StatementSetOptionsResponse:
889
+ return await self.client.statement_set_options(
890
+ StatementSetOptionsRequest(stmt_handle=stmt_handle, options=options)
891
+ )
892
+
893
+ async def statement_execute_query(
894
+ self, stmt_handle: StatementHandle, bindings: QueryBindings | None = None
895
+ ) -> ExecuteQueryResponse:
896
+ return await self.client.statement_execute_query(
897
+ StatementExecuteQueryRequest(stmt_handle=stmt_handle, bindings=bindings)
898
+ )
899
+
900
+ async def statement_execute_async(
901
+ self, stmt_handle: StatementHandle, bindings: QueryBindings | None = None
902
+ ) -> StatementExecuteAsyncResponse:
903
+ return await self.client.statement_execute_async(
904
+ StatementExecuteAsyncRequest(stmt_handle=stmt_handle, bindings=bindings)
905
+ )
906
+
907
+ async def statement_prepare(
908
+ self, stmt_handle: StatementHandle, bindings: QueryBindings | None = None
909
+ ) -> StatementPrepareResponse:
910
+ return await self.client.statement_prepare(StatementPrepareRequest(stmt_handle=stmt_handle, bindings=bindings))
911
+
912
+ # =====================================================================
913
+ # Connection result-set access (multi-statement / async-query paths)
914
+ # =====================================================================
915
+
916
+ async def connection_get_result_set(self, conn_handle: ConnectionHandle, query_id: str) -> ResultSetResponse:
917
+ return await self.client.connection_get_result_set(
918
+ ConnectionGetResultSetRequest(conn_handle=conn_handle, query_id=query_id)
919
+ )
920
+
921
+ async def connection_get_query_result(self, conn_handle: ConnectionHandle, query_id: str) -> ExecuteQueryResponse:
922
+ return await self.client.connection_get_query_result(
923
+ ConnectionGetQueryResultRequest(conn_handle=conn_handle, query_id=query_id)
924
+ )
925
+
926
+ async def connection_abort_query(
927
+ self, conn_handle: ConnectionHandle, query_id: str
928
+ ) -> ConnectionAbortQueryResponse:
929
+ return await self.client.connection_abort_query(
930
+ ConnectionAbortQueryRequest(conn_handle=conn_handle, query_id=query_id)
931
+ )
932
+
933
+ async def connection_get_info(
934
+ self,
935
+ conn_handle: ConnectionHandle,
936
+ include_master_token: bool = False,
937
+ ) -> ConnectionGetInfoResponse:
938
+ return await self.client.connection_get_info(
939
+ ConnectionGetInfoRequest(conn_handle=conn_handle, include_master_token=include_master_token)
940
+ )
941
+
942
+ async def connection_get_parameter(self, conn_handle: ConnectionHandle, key: str) -> ConnectionGetParameterResponse:
943
+ return await self.client.connection_get_parameter(
944
+ ConnectionGetParameterRequest(conn_handle=conn_handle, key=key)
945
+ )
946
+
947
+ async def connection_get_all_parameters(self, conn_handle: ConnectionHandle) -> ConnectionGetAllParametersResponse:
948
+ return await self.client.connection_get_all_parameters(
949
+ ConnectionGetAllParametersRequest(conn_handle=conn_handle)
950
+ )
951
+
952
+ # =====================================================================
953
+ # Result-set streaming
954
+ # =====================================================================
955
+
956
+ async def result_set_get_stream(self, result_set_handle: ResultSetHandle) -> ResultSetGetStreamResponse:
957
+ return await self.client.result_set_get_stream(ResultSetGetStreamRequest(result_set_handle=result_set_handle))
958
+
959
+ async def result_set_get_chunks(self, result_set_handle: ResultSetHandle) -> ResultSetGetChunksResponse:
960
+ return await self.client.result_set_get_chunks(ResultSetGetChunksRequest(result_set_handle=result_set_handle))
961
+
962
+ async def result_set_release(self, result_set_handle: ResultSetHandle) -> ResultSetReleaseResponse:
963
+ return await self.client.result_set_release(ResultSetReleaseRequest(result_set_handle=result_set_handle))
964
+
965
+ async def database_fetch_chunk(
966
+ self,
967
+ conn_handle: ConnectionHandle | None,
968
+ chunk: ResultChunk,
969
+ columns: list[ColumnMetadata],
970
+ ) -> DatabaseFetchChunkResponse:
971
+ return await self.client.database_fetch_chunk(
972
+ DatabaseFetchChunkRequest(conn_handle=conn_handle, chunks=[chunk], columns=columns)
973
+ )
974
+
975
+
976
+ async_core_driver: AsyncCoreDriver = AsyncCoreDriver()