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,275 @@
1
+ #include "CArrowStreamTableIterator.hpp"
2
+
3
+ #include <exception>
4
+ #include <memory>
5
+ #include <string>
6
+
7
+ #include "Python/Common.hpp"
8
+
9
+ namespace sf {
10
+
11
+ Logger* CArrowStreamTableIterator::logger =
12
+ new Logger("snowflake.connector.CArrowStreamTableIterator");
13
+
14
+ namespace {
15
+ void releaseStream(ArrowArrayStream* s) {
16
+ if (s && s->release) s->release(s);
17
+ }
18
+
19
+ /**
20
+ * Invokes @p convert, translating any C++ exception into a Python
21
+ * exception. The Cython declarations of the methods below carry no
22
+ * `except +`, so an escaping C++ exception reaches a caller that cannot
23
+ * handle it and terminates the process. py::setPyError() acquires the GIL
24
+ * on its own, so this is usable inside a Py_BEGIN_ALLOW_THREADS block.
25
+ */
26
+ template <typename Fn>
27
+ void runTranslatingCxxExceptions(Fn&& convert) {
28
+ try {
29
+ convert();
30
+ } catch (const std::exception& e) {
31
+ py::setPyError(PyExc_Exception, e.what());
32
+ } catch (...) {
33
+ py::setPyError(PyExc_Exception,
34
+ "[Snowflake Exception] unknown error while converting Arrow columns");
35
+ }
36
+ }
37
+ } // namespace
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Factory / constructor
41
+ // ---------------------------------------------------------------------------
42
+
43
+ std::unique_ptr<CArrowStreamTableIterator> CArrowStreamTableIterator::from_stream(int64_t stream_ptr, PyObject* context, bool number_to_decimal, bool force_microsecond_precision) {
44
+ auto* stream = reinterpret_cast<ArrowArrayStream*>(stream_ptr);
45
+ if (!stream || !stream->release) {
46
+ PyErr_SetString(PyExc_Exception, "[Snowflake Exception] Invalid ArrowArrayStream pointer");
47
+ return nullptr;
48
+ }
49
+
50
+ ArrowSchema schema{};
51
+ int rc = stream->get_schema(stream, &schema);
52
+ if (rc != 0) {
53
+ const char* msg = stream->get_last_error(stream);
54
+ std::string err = Logger::formatString(
55
+ "[Snowflake Exception] error getting schema: %s, error code: %d", msg ? msg : "unknown", rc);
56
+ logger->error(__FILE__, __func__, __LINE__, err.c_str());
57
+ PyErr_SetString(PyExc_Exception, err.c_str());
58
+ return nullptr;
59
+ }
60
+
61
+ return std::unique_ptr<CArrowStreamTableIterator>(
62
+ new CArrowStreamTableIterator(stream, &schema, context, number_to_decimal, force_microsecond_precision));
63
+ }
64
+
65
+ CArrowStreamTableIterator::CArrowStreamTableIterator(ArrowArrayStream* stream, ArrowSchema* schema, PyObject* context, bool number_to_decimal, bool force_microsecond_precision)
66
+ : m_stream(stream, releaseStream),
67
+ m_columnCount(schema->n_children),
68
+ m_context(context) {
69
+ ArrowSchemaMove(schema, m_schema.get());
70
+
71
+ char* timezone = nullptr;
72
+ py::UniqueRef tz(PyObject_GetAttrString(m_context, "_timezone"));
73
+ PyArg_Parse(tz.get(), "z", &timezone);
74
+
75
+ m_converter = std::unique_ptr<ArrowTableConverter>(
76
+ new ArrowTableConverter(number_to_decimal, force_microsecond_precision, timezone ? std::string(timezone) : std::string()));
77
+ }
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // Export accessors
81
+ // ---------------------------------------------------------------------------
82
+
83
+ uintptr_t CArrowStreamTableIterator::getArrowArrayPtr() {
84
+ return reinterpret_cast<uintptr_t>(m_exportArray.get());
85
+ }
86
+
87
+ uintptr_t CArrowStreamTableIterator::getArrowSchemaPtr() {
88
+ return reinterpret_cast<uintptr_t>(m_exportSchema.get());
89
+ }
90
+
91
+ uintptr_t CArrowStreamTableIterator::getConvertedSchemaPtr() {
92
+ m_streamSchemaExport.reset();
93
+ int rc = ArrowSchemaDeepCopy(m_schema.get(), m_streamSchemaExport.get());
94
+ if (rc != NANOARROW_OK) {
95
+ std::string err = Logger::formatString(
96
+ "[Snowflake Exception] error deep-copying stream schema, error code: %d", rc);
97
+ logger->error(__FILE__, __func__, __LINE__, err.c_str());
98
+ PyErr_SetString(PyExc_RuntimeError, err.c_str());
99
+ return 0;
100
+ }
101
+
102
+ ArrowError error;
103
+
104
+ nanoarrow::UniqueArray emptyArray;
105
+ rc = ArrowArrayInitFromSchema(emptyArray.get(), m_schema.get(), &error);
106
+ if (rc != NANOARROW_OK) {
107
+ std::string err = Logger::formatString(
108
+ "[Snowflake Exception] error initializing empty array for schema conversion: %s, error code: %d",
109
+ ArrowErrorMessage(&error), rc);
110
+ logger->error(__FILE__, __func__, __LINE__, err.c_str());
111
+ PyErr_SetString(PyExc_RuntimeError, err.c_str());
112
+ return 0;
113
+ }
114
+ rc = ArrowArrayFinishBuildingDefault(emptyArray.get(), &error);
115
+ if (rc != NANOARROW_OK) {
116
+ std::string err = Logger::formatString(
117
+ "[Snowflake Exception] error finishing empty array: %s, error code: %d",
118
+ ArrowErrorMessage(&error), rc);
119
+ logger->error(__FILE__, __func__, __LINE__, err.c_str());
120
+ PyErr_SetString(PyExc_RuntimeError, err.c_str());
121
+ return 0;
122
+ }
123
+
124
+ nanoarrow::UniqueArrayView emptyView;
125
+ rc = ArrowArrayViewInitFromSchema(emptyView.get(), m_schema.get(), &error);
126
+ if (rc != NANOARROW_OK) {
127
+ std::string err = Logger::formatString(
128
+ "[Snowflake Exception] error initializing empty array view: %s, error code: %d",
129
+ ArrowErrorMessage(&error), rc);
130
+ logger->error(__FILE__, __func__, __LINE__, err.c_str());
131
+ PyErr_SetString(PyExc_RuntimeError, err.c_str());
132
+ return 0;
133
+ }
134
+ rc = ArrowArrayViewSetArray(emptyView.get(), emptyArray.get(), &error);
135
+ if (rc != NANOARROW_OK) {
136
+ std::string err = Logger::formatString(
137
+ "[Snowflake Exception] error setting empty array view: %s, error code: %d",
138
+ ArrowErrorMessage(&error), rc);
139
+ logger->error(__FILE__, __func__, __LINE__, err.c_str());
140
+ PyErr_SetString(PyExc_RuntimeError, err.c_str());
141
+ return 0;
142
+ }
143
+
144
+ runTranslatingCxxExceptions([this, &emptyView] {
145
+ for (int64_t col = 0; col < m_columnCount; col++) {
146
+ m_converter->convertIfNeeded(m_streamSchemaExport->children[col], emptyView->children[col]);
147
+ if (py::checkPyError()) return;
148
+ }
149
+ });
150
+ if (py::checkPyError()) return 0;
151
+
152
+ return reinterpret_cast<uintptr_t>(m_streamSchemaExport.get());
153
+ }
154
+
155
+ // ---------------------------------------------------------------------------
156
+ // Stream loading
157
+ // ---------------------------------------------------------------------------
158
+
159
+ bool CArrowStreamTableIterator::loadNextBatch() {
160
+ if (m_streamExhausted) return false;
161
+
162
+ m_currentArray.reset();
163
+ m_currentArrayView.reset();
164
+
165
+ int returnCode;
166
+ ArrowArrayStream* stream = m_stream.get();
167
+ {
168
+ Py_BEGIN_ALLOW_THREADS
169
+ returnCode = stream->get_next(stream, m_currentArray.get());
170
+ Py_END_ALLOW_THREADS
171
+ }
172
+
173
+ if (returnCode != NANOARROW_OK) {
174
+ const char* msg = stream->get_last_error(stream);
175
+ std::string err = Logger::formatString(
176
+ "[Snowflake Exception] error getting next batch: %s, error code: %d", msg ? msg : "unknown", returnCode);
177
+ logger->error(__FILE__, __func__, __LINE__, err.c_str());
178
+ PyErr_SetString(PyExc_Exception, err.c_str());
179
+ return false;
180
+ }
181
+
182
+ if (m_currentArray->release == nullptr) {
183
+ m_streamExhausted = true;
184
+ return false;
185
+ }
186
+
187
+ if (m_currentArray->length == 0) {
188
+ return loadNextBatch();
189
+ }
190
+
191
+ ArrowError error;
192
+ returnCode = ArrowArrayViewInitFromSchema(m_currentArrayView.get(), m_schema.get(), &error);
193
+ if (returnCode != NANOARROW_OK) {
194
+ std::string err = Logger::formatString(
195
+ "[Snowflake Exception] error initializing ArrowArrayView: %s, error code: %d",
196
+ ArrowErrorMessage(&error), returnCode);
197
+ logger->error(__FILE__, __func__, __LINE__, err.c_str());
198
+ PyErr_SetString(PyExc_Exception, err.c_str());
199
+ return false;
200
+ }
201
+
202
+ returnCode = ArrowArrayViewSetArray(m_currentArrayView.get(), m_currentArray.get(), &error);
203
+ if (returnCode != NANOARROW_OK) {
204
+ std::string err = Logger::formatString(
205
+ "[Snowflake Exception] error setting ArrowArrayView: %s, error code: %d",
206
+ ArrowErrorMessage(&error), returnCode);
207
+ logger->error(__FILE__, __func__, __LINE__, err.c_str());
208
+ PyErr_SetString(PyExc_Exception, err.c_str());
209
+ return false;
210
+ }
211
+
212
+ return true;
213
+ }
214
+
215
+ // ---------------------------------------------------------------------------
216
+ // convertBatch()
217
+ // ---------------------------------------------------------------------------
218
+
219
+ void CArrowStreamTableIterator::convertBatch() {
220
+ m_exportArray.reset();
221
+ m_exportSchema.reset();
222
+
223
+ int rc = ArrowSchemaDeepCopy(m_schema.get(), m_exportSchema.get());
224
+ SF_CHECK_ARROW_RC(rc, "[Snowflake Exception] error deep-copying schema, error code: %d", rc);
225
+
226
+ {
227
+ Py_BEGIN_ALLOW_THREADS
228
+ runTranslatingCxxExceptions([this] {
229
+ for (int64_t col = 0; col < m_columnCount; col++) {
230
+ m_converter->convertIfNeeded(m_exportSchema->children[col],
231
+ m_currentArrayView->children[col]);
232
+ }
233
+ });
234
+ Py_END_ALLOW_THREADS
235
+ }
236
+ // GIL is held again - surface any error set via py::setPyError
237
+ if (py::checkPyError()) return;
238
+
239
+ ArrowArrayMove(m_currentArray.get(), m_exportArray.get());
240
+ }
241
+
242
+ // ---------------------------------------------------------------------------
243
+ // next()
244
+ // ---------------------------------------------------------------------------
245
+
246
+ ReturnVal CArrowStreamTableIterator::next() {
247
+ if (!loadNextBatch()) {
248
+ if (py::checkPyError()) {
249
+ PyObject *type, *val, *traceback;
250
+ PyErr_Fetch(&type, &val, &traceback);
251
+ PyErr_Clear();
252
+ m_currentPyException.reset(val);
253
+ Py_XDECREF(type);
254
+ Py_XDECREF(traceback);
255
+ return ReturnVal(nullptr, m_currentPyException.get());
256
+ }
257
+ return ReturnVal(Py_None, nullptr);
258
+ }
259
+
260
+ convertBatch();
261
+
262
+ if (py::checkPyError()) {
263
+ PyObject *type, *val, *traceback;
264
+ PyErr_Fetch(&type, &val, &traceback);
265
+ PyErr_Clear();
266
+ m_currentPyException.reset(val);
267
+ Py_XDECREF(type);
268
+ Py_XDECREF(traceback);
269
+ return ReturnVal(nullptr, m_currentPyException.get());
270
+ }
271
+
272
+ return ReturnVal(Py_True, nullptr);
273
+ }
274
+
275
+ } // namespace sf
@@ -0,0 +1,168 @@
1
+ #ifndef PC_CARROWSTREAMTABLEITERATOR_HPP
2
+ #define PC_CARROWSTREAMTABLEITERATOR_HPP
3
+
4
+ #include <memory>
5
+
6
+ #include "ArrowTableConverter.hpp"
7
+ #include "CArrowIterator.hpp"
8
+ #include "Python/Common.hpp"
9
+ #include "logging.hpp"
10
+ #include "nanoarrow.h"
11
+ #include "nanoarrow.hpp"
12
+
13
+ namespace sf {
14
+
15
+ /**
16
+ * Stream-based Arrow iterator that reads batches from an ArrowArrayStream
17
+ * and exposes each batch as a (ArrowArray, ArrowSchema) pair suitable for
18
+ * import into PyArrow via RecordBatch._import_from_c().
19
+ *
20
+ * Snowflake-specific type conversions (e.g. scaled NUMBER -> float64,
21
+ * struct-encoded TIMESTAMP -> Arrow timestamp) are applied to every batch
22
+ * through the shared ArrowTableConverter.
23
+ *
24
+ * Lifecycle (driven from the Cython wrapper ArrowDummyIterator):
25
+ * 1. from_stream() – validate stream, read schema, construct instance
26
+ * 2. next() – load next batch, convert, expose via export slots
27
+ * 3. getArrowArrayPtr() / getArrowSchemaPtr()
28
+ * – caller passes these to _import_from_c() which
29
+ * consumes them (sets release to nullptr)
30
+ * 4. repeat 2-3 until next() signals exhaustion (Py_None)
31
+ */
32
+ class CArrowStreamTableIterator {
33
+ public:
34
+ /**
35
+ * Factory method. Validates the stream pointer, reads the schema, and
36
+ * returns a ready-to-iterate instance.
37
+ *
38
+ * @param stream_ptr Pointer to ArrowArrayStream as int64 (FFI from Python)
39
+ * @param context Python ArrowConverterContext carrying session timezone
40
+ * @param number_to_decimal
41
+ * If true, scaled FIXED columns become Decimal128; otherwise float64
42
+ * @param force_microsecond_precision
43
+ * If true, all TIMESTAMP columns are forced to microsecond precision,
44
+ * ensuring consistent schema across batches whose data may span
45
+ * outside the nanosecond-representable range (1677-2262)
46
+ * @return Unique pointer to the iterator, or nullptr with a Python
47
+ * exception set on failure
48
+ */
49
+ static std::unique_ptr<CArrowStreamTableIterator> from_stream(
50
+ int64_t stream_ptr, PyObject* context, bool number_to_decimal,
51
+ bool force_microsecond_precision);
52
+
53
+ /**
54
+ * Advance to the next batch.
55
+ *
56
+ * @return ReturnVal with:
57
+ * - successObj = Py_True, exception = nullptr → batch ready; call
58
+ * getArrowArrayPtr() / getArrowSchemaPtr() to retrieve it
59
+ * - successObj = Py_None, exception = nullptr → stream exhausted
60
+ * - successObj = nullptr, exception != nullptr → error occurred
61
+ */
62
+ ReturnVal next();
63
+
64
+ /**
65
+ * Raw pointer (as uintptr_t) to the converted ArrowArray for the
66
+ * current batch. Valid only immediately after next() returns Py_True.
67
+ * Ownership transfers to the caller via _import_from_c().
68
+ */
69
+ uintptr_t getArrowArrayPtr();
70
+
71
+ /**
72
+ * Raw pointer (as uintptr_t) to the deep-copied ArrowSchema for the
73
+ * current batch. Same ownership semantics as getArrowArrayPtr().
74
+ */
75
+ uintptr_t getArrowSchemaPtr();
76
+
77
+ /**
78
+ * Raw pointer (as uintptr_t) to the stream schema after applying
79
+ * Snowflake type conversions (e.g. struct → timestamp, int → float64).
80
+ * Unlike getArrowSchemaPtr(), this is always valid—even when no batch
81
+ * has been loaded—making it safe to call for empty result sets
82
+ * (e.g. to build an empty PyArrow table with the correct column types).
83
+ *
84
+ * Internally synthesises a zero-row batch and runs it through
85
+ * ArrowTableConverter so the schema matches what non-empty results
86
+ * would produce.
87
+ *
88
+ * Ownership transfers to the caller via _import_from_c().
89
+ */
90
+ uintptr_t getConvertedSchemaPtr();
91
+
92
+ private:
93
+ CArrowStreamTableIterator(ArrowArrayStream* stream, ArrowSchema* schema,
94
+ PyObject* context, bool number_to_decimal,
95
+ bool force_microsecond_precision);
96
+
97
+ /**
98
+ * Pull the next non-empty batch from the stream into m_currentArray.
99
+ * Releases the GIL during stream->get_next() so concurrent chunk
100
+ * downloads (e.g. from S3) are not blocked by the Python interpreter.
101
+ * Also initialises m_currentArrayView for the conversion step.
102
+ *
103
+ * @return true if a batch was loaded; false if exhausted or error
104
+ */
105
+ bool loadNextBatch();
106
+
107
+ /**
108
+ * Apply Snowflake type conversions to the current batch via
109
+ * m_converter, then move the result into the export slots
110
+ * (m_exportArray / m_exportSchema).
111
+ * Releases the GIL during the per-column conversion loop, since it is
112
+ * pure nanoarrow buffer work; any Python exception raised inside the
113
+ * loop is signalled through py::setPyError(), which re-acquires the GIL
114
+ * only for the duration of the call. Errors are checked once after the
115
+ * loop when the GIL is held again.
116
+ * Sets a Python exception on failure (check py::checkPyError()).
117
+ */
118
+ void convertBatch();
119
+
120
+ /** Owned handle to the ArrowArrayStream; released on destruction. */
121
+ std::unique_ptr<ArrowArrayStream, void (*)(ArrowArrayStream*)> m_stream;
122
+
123
+ /** Stream schema, read once at construction; immutable across batches. */
124
+ nanoarrow::UniqueSchema m_schema;
125
+
126
+ /** Raw batch from the most recent stream->get_next() call. */
127
+ nanoarrow::UniqueArray m_currentArray;
128
+
129
+ /** View over m_currentArray; rebuilt each loadNextBatch() for the
130
+ * converter to read column data through. */
131
+ nanoarrow::UniqueArrayView m_currentArrayView;
132
+
133
+ /** Converted batch ready for PyArrow import. Populated by
134
+ * convertBatch(); consumed by _import_from_c() via getArrowArrayPtr(). */
135
+ nanoarrow::UniqueArray m_exportArray;
136
+
137
+ /** Deep-copied and possibly rewritten schema for the current batch.
138
+ * Each batch gets its own copy because conversion may alter child
139
+ * schemas (e.g. struct → timestamp). Consumed via getArrowSchemaPtr(). */
140
+ nanoarrow::UniqueSchema m_exportSchema;
141
+
142
+ /** Deep copy of m_schema used by getStreamSchemaPtr(). Separate from
143
+ * m_exportSchema so it can be produced independently of batch iteration. */
144
+ nanoarrow::UniqueSchema m_streamSchemaExport;
145
+
146
+ /** Set to true once stream->get_next() returns an empty release sentinel. */
147
+ bool m_streamExhausted = false;
148
+
149
+ /** Number of top-level columns, cached from schema.n_children. */
150
+ int64_t m_columnCount = 0;
151
+
152
+ /** Python ArrowConverterContext; borrowed reference kept alive by the
153
+ * Cython wrapper which stores it as `self.arrow_context`. */
154
+ PyObject* m_context;
155
+
156
+ /** Applies Snowflake-specific type conversions per column. */
157
+ std::unique_ptr<ArrowTableConverter> m_converter;
158
+
159
+ /** Holds the most recent Python exception so the pointer remains valid
160
+ * until the next call into the iterator. */
161
+ py::UniqueRef m_currentPyException;
162
+
163
+ static Logger* logger;
164
+ };
165
+
166
+ } // namespace sf
167
+
168
+ #endif // PC_CARROWSTREAMTABLEITERATOR_HPP