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,943 @@
1
+ #include "ArrowTableConverter.hpp"
2
+
3
+ #include <cstring>
4
+ #include <string>
5
+
6
+ #include "Python/Common.hpp"
7
+ #include "SnowflakeType.hpp"
8
+ #include "Util/time.hpp"
9
+
10
+ namespace sf {
11
+
12
+ Logger* ArrowTableConverter::logger = new Logger("snowflake.connector.ArrowTableConverter");
13
+
14
+ ArrowTableConverter::ArrowTableConverter(bool number_to_decimal, bool force_microsecond_precision, const std::string& timezone)
15
+ : m_convert_number_to_decimal(number_to_decimal),
16
+ m_force_microsecond_precision(force_microsecond_precision),
17
+ m_timezone(timezone) {}
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // convertIfNeeded – top-level dispatch on Snowflake logical type
21
+ // ---------------------------------------------------------------------------
22
+
23
+ void ArrowTableConverter::convertIfNeeded(ArrowSchema* columnSchema,
24
+ ArrowArrayView* columnArray) {
25
+ ArrowSchemaView columnSchemaView;
26
+ ArrowError error;
27
+ int returnCode;
28
+
29
+ returnCode = ArrowSchemaViewInit(&columnSchemaView, columnSchema, &error);
30
+ SF_CHECK_ARROW_RC(returnCode,
31
+ "[Snowflake Exception] error initializing "
32
+ "ArrowSchemaView: %s, error code: %d",
33
+ ArrowErrorMessage(&error), returnCode);
34
+
35
+ ArrowStringView snowflakeLogicalType;
36
+ const char* metadata = columnSchema->metadata;
37
+ returnCode = ArrowMetadataGetValue(metadata, ArrowCharView("logicalType"),
38
+ &snowflakeLogicalType);
39
+ SF_CHECK_ARROW_RC(returnCode,
40
+ "[Snowflake Exception] error getting 'logicalType' "
41
+ "from Arrow metadata, error code: %d",
42
+ returnCode);
43
+
44
+ SnowflakeType::Type st = SnowflakeType::snowflakeTypeFromString(
45
+ std::string(snowflakeLogicalType.data, snowflakeLogicalType.size_bytes));
46
+
47
+ switch (st) {
48
+ case SnowflakeType::Type::FIXED: {
49
+ int scale = 0;
50
+ ArrowStringView scaleString = ArrowCharView(nullptr);
51
+ if (metadata != nullptr) {
52
+ returnCode = ArrowMetadataGetValue(metadata, ArrowCharView("scale"),
53
+ &scaleString);
54
+ SF_CHECK_ARROW_RC(returnCode,
55
+ "[Snowflake Exception] error getting 'scale' "
56
+ "from Arrow metadata, error code: %d",
57
+ returnCode);
58
+ scale = std::stoi(
59
+ std::string(scaleString.data, scaleString.size_bytes));
60
+ }
61
+ if (scale > 0 &&
62
+ columnSchemaView.type != NANOARROW_TYPE_DECIMAL128) {
63
+ convertScaledFixedNumberColumn_nanoarrow(&columnSchemaView,
64
+ columnArray, scale);
65
+ }
66
+ break;
67
+ }
68
+
69
+ case SnowflakeType::Type::ANY:
70
+ case SnowflakeType::Type::BINARY:
71
+ case SnowflakeType::Type::BOOLEAN:
72
+ case SnowflakeType::Type::CHAR:
73
+ case SnowflakeType::Type::DATE:
74
+ case SnowflakeType::Type::REAL:
75
+ case SnowflakeType::Type::TEXT:
76
+ case SnowflakeType::Type::INTERVAL_YEAR_MONTH:
77
+ case SnowflakeType::Type::VARIANT:
78
+ case SnowflakeType::Type::VECTOR:
79
+ break;
80
+
81
+ case SnowflakeType::Type::ARRAY: {
82
+ switch (columnSchemaView.type) {
83
+ case NANOARROW_TYPE_STRING:
84
+ break;
85
+ case NANOARROW_TYPE_LIST: {
86
+ if (columnSchemaView.schema->n_children != 1) {
87
+ py::setPyError(
88
+ PyExc_Exception,
89
+ Logger::formatString(
90
+ "[Snowflake Exception] invalid arrow schema for array "
91
+ "items: expected 1 child, got %d",
92
+ columnSchemaView.schema->n_children).c_str());
93
+ break;
94
+ }
95
+ convertIfNeeded(columnSchemaView.schema->children[0],
96
+ columnArray->children[0]);
97
+ break;
98
+ }
99
+ default:
100
+ py::setPyError(
101
+ PyExc_Exception,
102
+ Logger::formatString(
103
+ "[Snowflake Exception] unknown arrow type(%s) "
104
+ "for ARRAY data in %s",
105
+ NANOARROW_TYPE_ENUM_STRING[columnSchemaView.type],
106
+ columnSchemaView.schema->name).c_str());
107
+ }
108
+ break;
109
+ }
110
+
111
+ case SnowflakeType::Type::MAP: {
112
+ switch (columnSchemaView.type) {
113
+ case NANOARROW_TYPE_STRING:
114
+ break;
115
+ case NANOARROW_TYPE_MAP: {
116
+ if (columnSchemaView.schema->n_children != 1) {
117
+ py::setPyError(
118
+ PyExc_Exception,
119
+ Logger::formatString(
120
+ "[Snowflake Exception] invalid arrow schema for map "
121
+ "entries: expected 1 child, got %d",
122
+ columnSchemaView.schema->n_children).c_str());
123
+ break;
124
+ }
125
+ ArrowSchema* entries = columnSchemaView.schema->children[0];
126
+ if (entries->n_children != 2) {
127
+ py::setPyError(
128
+ PyExc_Exception,
129
+ Logger::formatString(
130
+ "[Snowflake Exception] invalid arrow schema for map "
131
+ "key/value: expected 2 entries, got %d",
132
+ entries->n_children).c_str());
133
+ break;
134
+ }
135
+ convertIfNeeded(entries->children[0],
136
+ columnArray->children[0]->children[0]);
137
+ convertIfNeeded(entries->children[1],
138
+ columnArray->children[0]->children[1]);
139
+ break;
140
+ }
141
+ default:
142
+ py::setPyError(
143
+ PyExc_Exception,
144
+ Logger::formatString(
145
+ "[Snowflake Exception] unknown arrow type(%s) "
146
+ "for MAP data in %s",
147
+ NANOARROW_TYPE_ENUM_STRING[columnSchemaView.type],
148
+ columnSchemaView.schema->name).c_str());
149
+ }
150
+ break;
151
+ }
152
+
153
+ case SnowflakeType::Type::OBJECT: {
154
+ switch (columnSchemaView.type) {
155
+ case NANOARROW_TYPE_STRING:
156
+ break;
157
+ case NANOARROW_TYPE_STRUCT:
158
+ for (int i = 0; i < columnSchemaView.schema->n_children; i++) {
159
+ convertIfNeeded(columnSchemaView.schema->children[i],
160
+ columnArray->children[i]);
161
+ }
162
+ break;
163
+ default:
164
+ py::setPyError(
165
+ PyExc_Exception,
166
+ Logger::formatString(
167
+ "[Snowflake Exception] unknown arrow type(%s) "
168
+ "for OBJECT data in %s",
169
+ NANOARROW_TYPE_ENUM_STRING[columnSchemaView.type],
170
+ columnSchemaView.schema->name).c_str());
171
+ }
172
+ break;
173
+ }
174
+
175
+ case SnowflakeType::Type::INTERVAL_DAY_TIME: {
176
+ int scale = 9;
177
+ if (metadata != nullptr) {
178
+ ArrowStringView scaleString = ArrowCharView(nullptr);
179
+ returnCode = ArrowMetadataGetValue(metadata, ArrowCharView("scale"),
180
+ &scaleString);
181
+ SF_CHECK_ARROW_RC(returnCode,
182
+ "[Snowflake Exception] error getting 'scale', "
183
+ "error code: %d",
184
+ returnCode);
185
+ scale = std::stoi(
186
+ std::string(scaleString.data, scaleString.size_bytes));
187
+ }
188
+ convertIntervalDayTimeColumn_nanoarrow(&columnSchemaView, columnArray,
189
+ scale);
190
+ break;
191
+ }
192
+
193
+ case SnowflakeType::Type::TIME: {
194
+ int scale = 9;
195
+ if (metadata != nullptr) {
196
+ ArrowStringView scaleString = ArrowCharView(nullptr);
197
+ returnCode = ArrowMetadataGetValue(metadata, ArrowCharView("scale"),
198
+ &scaleString);
199
+ SF_CHECK_ARROW_RC(returnCode,
200
+ "[Snowflake Exception] error getting 'scale', "
201
+ "error code: %d",
202
+ returnCode);
203
+ scale = std::stoi(
204
+ std::string(scaleString.data, scaleString.size_bytes));
205
+ }
206
+ if (scale < 0 || scale > 9) {
207
+ py::setPyError(
208
+ PyExc_Exception,
209
+ Logger::formatString(
210
+ "[Snowflake Exception] invalid scale value %d for TIME "
211
+ "column (expected 0-9)",
212
+ scale).c_str());
213
+ break;
214
+ }
215
+ convertTimeColumn_nanoarrow(&columnSchemaView, columnArray, scale);
216
+ break;
217
+ }
218
+
219
+ case SnowflakeType::Type::TIMESTAMP_NTZ: {
220
+ int scale = 9;
221
+ if (metadata != nullptr) {
222
+ ArrowStringView scaleString = ArrowCharView(nullptr);
223
+ returnCode = ArrowMetadataGetValue(metadata, ArrowCharView("scale"),
224
+ &scaleString);
225
+ SF_CHECK_ARROW_RC(returnCode,
226
+ "[Snowflake Exception] error getting 'scale', "
227
+ "error code: %d",
228
+ returnCode);
229
+ scale = std::stoi(
230
+ std::string(scaleString.data, scaleString.size_bytes));
231
+ }
232
+ if (scale < 0 || scale > 9) {
233
+ py::setPyError(
234
+ PyExc_Exception,
235
+ Logger::formatString(
236
+ "[Snowflake Exception] invalid scale value %d for "
237
+ "TIMESTAMP_NTZ column (expected 0-9)",
238
+ scale).c_str());
239
+ break;
240
+ }
241
+ convertTimestampColumn_nanoarrow(&columnSchemaView, columnArray, scale);
242
+ break;
243
+ }
244
+
245
+ case SnowflakeType::Type::TIMESTAMP_LTZ: {
246
+ int scale = 9;
247
+ if (metadata != nullptr) {
248
+ ArrowStringView scaleString = ArrowCharView(nullptr);
249
+ returnCode = ArrowMetadataGetValue(metadata, ArrowCharView("scale"),
250
+ &scaleString);
251
+ SF_CHECK_ARROW_RC(returnCode,
252
+ "[Snowflake Exception] error getting 'scale', "
253
+ "error code: %d",
254
+ returnCode);
255
+ scale = std::stoi(
256
+ std::string(scaleString.data, scaleString.size_bytes));
257
+ }
258
+ if (scale < 0 || scale > 9) {
259
+ py::setPyError(
260
+ PyExc_Exception,
261
+ Logger::formatString(
262
+ "[Snowflake Exception] invalid scale value %d for "
263
+ "TIMESTAMP_LTZ column (expected 0-9)",
264
+ scale).c_str());
265
+ break;
266
+ }
267
+ convertTimestampColumn_nanoarrow(&columnSchemaView, columnArray, scale,
268
+ m_timezone);
269
+ break;
270
+ }
271
+
272
+ case SnowflakeType::Type::TIMESTAMP_TZ: {
273
+ int scale = 9;
274
+ int byteLength = 16;
275
+ if (metadata != nullptr) {
276
+ ArrowStringView scaleString = ArrowCharView(nullptr);
277
+ ArrowStringView byteLengthString = ArrowCharView(nullptr);
278
+ returnCode = ArrowMetadataGetValue(metadata, ArrowCharView("scale"),
279
+ &scaleString);
280
+ SF_CHECK_ARROW_RC(returnCode,
281
+ "[Snowflake Exception] error getting 'scale', "
282
+ "error code: %d",
283
+ returnCode);
284
+ returnCode = ArrowMetadataGetValue(metadata,
285
+ ArrowCharView("byteLength"),
286
+ &byteLengthString);
287
+ SF_CHECK_ARROW_RC(returnCode,
288
+ "[Snowflake Exception] error getting 'byteLength', "
289
+ "error code: %d",
290
+ returnCode);
291
+ scale = std::stoi(
292
+ std::string(scaleString.data, scaleString.size_bytes));
293
+ if (byteLengthString.data != nullptr) {
294
+ byteLength = std::stoi(
295
+ std::string(byteLengthString.data,
296
+ byteLengthString.size_bytes));
297
+ }
298
+ }
299
+ if (scale < 0 || scale > 9) {
300
+ py::setPyError(
301
+ PyExc_Exception,
302
+ Logger::formatString(
303
+ "[Snowflake Exception] invalid scale value %d for "
304
+ "TIMESTAMP_TZ column (expected 0-9)",
305
+ scale).c_str());
306
+ break;
307
+ }
308
+ convertTimestampTZColumn_nanoarrow(&columnSchemaView, columnArray,
309
+ scale, byteLength, m_timezone);
310
+ break;
311
+ }
312
+
313
+ default:
314
+ py::setPyError(
315
+ PyExc_Exception,
316
+ Logger::formatString(
317
+ "[Snowflake Exception] unknown Snowflake type: %s",
318
+ snowflakeLogicalType.data).c_str());
319
+ }
320
+ }
321
+
322
+ // ---------------------------------------------------------------------------
323
+ // Scaled fixed-number conversion
324
+ // ---------------------------------------------------------------------------
325
+
326
+ template <typename T>
327
+ double ArrowTableConverter::convertScaledFixedNumberToDouble(
328
+ unsigned int scale, T originalValue) {
329
+ if (scale < 9) {
330
+ return static_cast<double>(originalValue) /
331
+ sf::internal::powTenSB4[scale];
332
+ }
333
+ std::string valStr = std::to_string(originalValue);
334
+ int negative = valStr.at(0) == '-' ? 1 : 0;
335
+ unsigned int digits = valStr.length() - negative;
336
+ if (digits <= scale) {
337
+ int numZeroes = scale - digits + 1;
338
+ valStr.insert(negative, std::string(numZeroes, '0'));
339
+ }
340
+ valStr.insert(valStr.length() - scale, ".");
341
+ std::size_t offset = 0;
342
+ return std::stod(valStr, &offset);
343
+ }
344
+
345
+ void ArrowTableConverter::convertScaledFixedNumberColumn_nanoarrow(
346
+ ArrowSchemaView* field, ArrowArrayView* columnArray,
347
+ unsigned int scale) {
348
+ if (m_convert_number_to_decimal) {
349
+ convertScaledFixedNumberColumnToDecimalColumn_nanoarrow(field, columnArray,
350
+ scale);
351
+ } else {
352
+ convertScaledFixedNumberColumnToDoubleColumn_nanoarrow(field, columnArray,
353
+ scale);
354
+ }
355
+ }
356
+
357
+ void ArrowTableConverter::convertScaledFixedNumberColumnToDecimalColumn_nanoarrow(
358
+ ArrowSchemaView* field, ArrowArrayView* columnArray,
359
+ unsigned int scale) {
360
+ int returnCode = 0;
361
+ nanoarrow::UniqueSchema newUniqueField;
362
+ nanoarrow::UniqueArray newUniqueArray;
363
+ ArrowSchema* newSchema = newUniqueField.get();
364
+ ArrowArray* newArray = newUniqueArray.get();
365
+ ArrowError error;
366
+
367
+ ArrowSchemaInit(newSchema);
368
+ newSchema->flags &= (field->schema->flags & ARROW_FLAG_NULLABLE);
369
+ returnCode = ArrowSchemaSetTypeDecimal(newSchema, NANOARROW_TYPE_DECIMAL128,
370
+ 38, scale);
371
+ SF_CHECK_ARROW_RC(returnCode,
372
+ "[Snowflake Exception] error setting schema type "
373
+ "decimal, error code: %d",
374
+ returnCode);
375
+ returnCode = ArrowSchemaSetName(newSchema, field->schema->name);
376
+ SF_CHECK_ARROW_RC(returnCode,
377
+ "[Snowflake Exception] error setting schema name, "
378
+ "error code: %d",
379
+ returnCode);
380
+
381
+ returnCode = ArrowArrayInitFromSchema(newArray, newSchema, &error);
382
+ SF_CHECK_ARROW_RC(returnCode,
383
+ "[Snowflake Exception] error initializing array from "
384
+ "schema: %s, error code: %d",
385
+ ArrowErrorMessage(&error), returnCode);
386
+ returnCode = ArrowArrayStartAppending(newArray);
387
+ SF_CHECK_ARROW_RC(returnCode,
388
+ "[Snowflake Exception] error starting array appending, "
389
+ "error code: %d",
390
+ returnCode);
391
+
392
+ for (int64_t rowIdx = 0; rowIdx < columnArray->array->length; rowIdx++) {
393
+ if (ArrowArrayViewIsNull(columnArray, rowIdx)) {
394
+ returnCode = ArrowArrayAppendNull(newArray, 1);
395
+ } else {
396
+ auto originalVal = ArrowArrayViewGetIntUnsafe(columnArray, rowIdx);
397
+ ArrowDecimal arrowDecimal;
398
+ ArrowDecimalInit(&arrowDecimal, 128, 38, scale);
399
+ ArrowDecimalSetInt(&arrowDecimal, originalVal);
400
+ returnCode = ArrowArrayAppendDecimal(newArray, &arrowDecimal);
401
+ }
402
+ SF_CHECK_ARROW_RC(returnCode,
403
+ "[Snowflake Exception] error appending decimal value, "
404
+ "error code: %d",
405
+ returnCode);
406
+ }
407
+
408
+ returnCode = ArrowArrayFinishBuildingDefault(newArray, &error);
409
+ SF_CHECK_ARROW_RC(returnCode,
410
+ "[Snowflake Exception] error finishing array: %s, "
411
+ "error code: %d",
412
+ ArrowErrorMessage(&error), returnCode);
413
+ field->schema->release(field->schema);
414
+ ArrowSchemaMove(newSchema, field->schema);
415
+ columnArray->array->release(columnArray->array);
416
+ ArrowArrayMove(newArray, columnArray->array);
417
+ }
418
+
419
+ void ArrowTableConverter::convertScaledFixedNumberColumnToDoubleColumn_nanoarrow(
420
+ ArrowSchemaView* field, ArrowArrayView* columnArray,
421
+ unsigned int scale) {
422
+ int returnCode = 0;
423
+ nanoarrow::UniqueSchema newUniqueField;
424
+ nanoarrow::UniqueArray newUniqueArray;
425
+ ArrowSchema* newSchema = newUniqueField.get();
426
+ ArrowArray* newArray = newUniqueArray.get();
427
+ ArrowError error;
428
+
429
+ ArrowSchemaInit(newSchema);
430
+ newSchema->flags &= (field->schema->flags & ARROW_FLAG_NULLABLE);
431
+ returnCode = ArrowSchemaSetType(newSchema, NANOARROW_TYPE_DOUBLE);
432
+ SF_CHECK_ARROW_RC(returnCode,
433
+ "[Snowflake Exception] error setting schema type double, "
434
+ "error code: %d",
435
+ returnCode);
436
+ returnCode = ArrowSchemaSetName(newSchema, field->schema->name);
437
+ SF_CHECK_ARROW_RC(returnCode,
438
+ "[Snowflake Exception] error setting schema name, "
439
+ "error code: %d",
440
+ returnCode);
441
+
442
+ returnCode = ArrowArrayInitFromSchema(newArray, newSchema, &error);
443
+ SF_CHECK_ARROW_RC(returnCode,
444
+ "[Snowflake Exception] error initializing array from "
445
+ "schema: %s, error code: %d",
446
+ ArrowErrorMessage(&error), returnCode);
447
+
448
+ for (int64_t rowIdx = 0; rowIdx < columnArray->array->length; rowIdx++) {
449
+ if (ArrowArrayViewIsNull(columnArray, rowIdx)) {
450
+ returnCode = ArrowArrayAppendNull(newArray, 1);
451
+ } else {
452
+ auto originalVal = ArrowArrayViewGetIntUnsafe(columnArray, rowIdx);
453
+ returnCode = ArrowArrayAppendDouble(
454
+ newArray, convertScaledFixedNumberToDouble(scale, originalVal));
455
+ }
456
+ SF_CHECK_ARROW_RC(returnCode,
457
+ "[Snowflake Exception] error appending double value, "
458
+ "error code: %d",
459
+ returnCode);
460
+ }
461
+
462
+ returnCode = ArrowArrayFinishBuildingDefault(newArray, &error);
463
+ SF_CHECK_ARROW_RC(returnCode,
464
+ "[Snowflake Exception] error finishing array: %s, "
465
+ "error code: %d",
466
+ ArrowErrorMessage(&error), returnCode);
467
+ field->schema->release(field->schema);
468
+ ArrowSchemaMove(newSchema, field->schema);
469
+ columnArray->array->release(columnArray->array);
470
+ ArrowArrayMove(newArray, columnArray->array);
471
+ }
472
+
473
+ // ---------------------------------------------------------------------------
474
+ // Interval Day-Time
475
+ // ---------------------------------------------------------------------------
476
+
477
+ void ArrowTableConverter::convertIntervalDayTimeColumn_nanoarrow(
478
+ ArrowSchemaView* field, ArrowArrayView* columnArray, int scale) {
479
+ int returnCode = 0;
480
+ nanoarrow::UniqueSchema newUniqueField;
481
+ nanoarrow::UniqueArray newUniqueArray;
482
+ ArrowSchema* newSchema = newUniqueField.get();
483
+ ArrowArray* newArray = newUniqueArray.get();
484
+ ArrowError error;
485
+
486
+ ArrowSchemaInit(newSchema);
487
+ newSchema->flags &= (field->schema->flags & ARROW_FLAG_NULLABLE);
488
+ returnCode = ArrowSchemaSetTypeDateTime(newSchema, NANOARROW_TYPE_DURATION,
489
+ NANOARROW_TIME_UNIT_NANO, nullptr);
490
+ SF_CHECK_ARROW_RC(returnCode,
491
+ "[Snowflake Exception] error setting schema DateTime, "
492
+ "error code: %d",
493
+ returnCode);
494
+ returnCode = ArrowSchemaSetName(newSchema, field->schema->name);
495
+ SF_CHECK_ARROW_RC(returnCode,
496
+ "[Snowflake Exception] error setting schema name, "
497
+ "error code: %d",
498
+ returnCode);
499
+
500
+ returnCode = ArrowArrayInitFromSchema(newArray, newSchema, &error);
501
+ SF_CHECK_ARROW_RC(returnCode,
502
+ "[Snowflake Exception] error initializing array from "
503
+ "schema: %s, error code: %d",
504
+ ArrowErrorMessage(&error), returnCode);
505
+ returnCode = ArrowArrayStartAppending(newArray);
506
+ SF_CHECK_ARROW_RC(returnCode,
507
+ "[Snowflake Exception] error starting appending, "
508
+ "error code: %d",
509
+ returnCode);
510
+
511
+ for (int64_t rowIdx = 0; rowIdx < columnArray->array->length; rowIdx++) {
512
+ if (ArrowArrayViewIsNull(columnArray, rowIdx)) {
513
+ returnCode = ArrowArrayAppendNull(newArray, 1);
514
+ } else {
515
+ ArrowDecimal arrowDecimal;
516
+ ArrowDecimalInit(&arrowDecimal, 128, 38, 0);
517
+ ArrowArrayViewGetDecimalUnsafe(columnArray, rowIdx, &arrowDecimal);
518
+ returnCode =
519
+ ArrowArrayAppendInt(newArray, ArrowDecimalGetIntUnsafe(&arrowDecimal));
520
+ }
521
+ SF_CHECK_ARROW_RC(returnCode,
522
+ "[Snowflake Exception] error appending interval value, "
523
+ "error code: %d",
524
+ returnCode);
525
+ }
526
+
527
+ returnCode = ArrowArrayFinishBuildingDefault(newArray, &error);
528
+ SF_CHECK_ARROW_RC(returnCode,
529
+ "[Snowflake Exception] error finishing array: %s, "
530
+ "error code: %d",
531
+ ArrowErrorMessage(&error), returnCode);
532
+ field->schema->release(field->schema);
533
+ ArrowSchemaMove(newSchema, field->schema);
534
+ columnArray->array->release(columnArray->array);
535
+ ArrowArrayMove(newArray, columnArray->array);
536
+ }
537
+
538
+ // ---------------------------------------------------------------------------
539
+ // Time
540
+ // ---------------------------------------------------------------------------
541
+
542
+ void ArrowTableConverter::convertTimeColumn_nanoarrow(
543
+ ArrowSchemaView* field, ArrowArrayView* columnArray, int scale) {
544
+ int returnCode = 0;
545
+ nanoarrow::UniqueSchema newUniqueField;
546
+ nanoarrow::UniqueArray newUniqueArray;
547
+ ArrowSchema* newSchema = newUniqueField.get();
548
+ ArrowArray* newArray = newUniqueArray.get();
549
+ ArrowError error;
550
+
551
+ ArrowSchemaInit(newSchema);
552
+ newSchema->flags &= (field->schema->flags & ARROW_FLAG_NULLABLE);
553
+
554
+ int64_t powTenSB4Val = 1;
555
+ if (scale == 0) {
556
+ returnCode = ArrowSchemaSetTypeDateTime(
557
+ newSchema, NANOARROW_TYPE_TIME32, NANOARROW_TIME_UNIT_SECOND, nullptr);
558
+ } else if (scale <= 3) {
559
+ returnCode = ArrowSchemaSetTypeDateTime(
560
+ newSchema, NANOARROW_TYPE_TIME32, NANOARROW_TIME_UNIT_MILLI, nullptr);
561
+ powTenSB4Val = sf::internal::powTenSB4[3 - scale];
562
+ } else if (scale <= 6) {
563
+ returnCode = ArrowSchemaSetTypeDateTime(
564
+ newSchema, NANOARROW_TYPE_TIME64, NANOARROW_TIME_UNIT_MICRO, nullptr);
565
+ powTenSB4Val = sf::internal::powTenSB4[6 - scale];
566
+ } else {
567
+ returnCode = ArrowSchemaSetTypeDateTime(
568
+ newSchema, NANOARROW_TYPE_TIME64, NANOARROW_TIME_UNIT_MICRO, nullptr);
569
+ powTenSB4Val = sf::internal::powTenSB4[scale - 6];
570
+ }
571
+ SF_CHECK_ARROW_RC(returnCode,
572
+ "[Snowflake Exception] error setting schema DateTime, "
573
+ "error code: %d",
574
+ returnCode);
575
+ returnCode = ArrowSchemaSetName(newSchema, field->schema->name);
576
+ SF_CHECK_ARROW_RC(returnCode,
577
+ "[Snowflake Exception] error setting schema name, "
578
+ "error code: %d",
579
+ returnCode);
580
+
581
+ returnCode = ArrowArrayInitFromSchema(newArray, newSchema, &error);
582
+ SF_CHECK_ARROW_RC(returnCode,
583
+ "[Snowflake Exception] error initializing array: %s, "
584
+ "error code: %d",
585
+ ArrowErrorMessage(&error), returnCode);
586
+ returnCode = ArrowArrayStartAppending(newArray);
587
+ SF_CHECK_ARROW_RC(returnCode,
588
+ "[Snowflake Exception] error starting appending, "
589
+ "error code: %d",
590
+ returnCode);
591
+
592
+ for (int64_t rowIdx = 0; rowIdx < columnArray->array->length; rowIdx++) {
593
+ if (ArrowArrayViewIsNull(columnArray, rowIdx)) {
594
+ returnCode = ArrowArrayAppendNull(newArray, 1);
595
+ } else {
596
+ auto val = ArrowArrayViewGetIntUnsafe(columnArray, rowIdx);
597
+ val = (scale <= 6) ? (val * powTenSB4Val) : (val / powTenSB4Val);
598
+ returnCode = ArrowArrayAppendInt(newArray, val);
599
+ }
600
+ SF_CHECK_ARROW_RC(returnCode,
601
+ "[Snowflake Exception] error appending time value, "
602
+ "error code: %d",
603
+ returnCode);
604
+ }
605
+
606
+ returnCode = ArrowArrayFinishBuildingDefault(newArray, &error);
607
+ SF_CHECK_ARROW_RC(returnCode,
608
+ "[Snowflake Exception] error finishing array: %s, "
609
+ "error code: %d",
610
+ ArrowErrorMessage(&error), returnCode);
611
+ field->schema->release(field->schema);
612
+ ArrowSchemaMove(newSchema, field->schema);
613
+ columnArray->array->release(columnArray->array);
614
+ ArrowArrayMove(newArray, columnArray->array);
615
+ }
616
+
617
+ // ---------------------------------------------------------------------------
618
+ // Nanosecond timestamp overflow helper
619
+ // ---------------------------------------------------------------------------
620
+
621
+ enum class NanoTsCheck { InRange, Downscale, Error };
622
+
623
+ /**
624
+ * Reports whether the column has to be emitted at microsecond precision,
625
+ * which is the case once a nanosecond value overflows int64 while every
626
+ * fraction stays microsecond-aligned.
627
+ *
628
+ * A value that overflows and also carries sub-microsecond digits fits no
629
+ * supported timestamp unit; that case sets a Python exception via
630
+ * setPyError and returns Error. convertBatch surfaces it after the GIL is
631
+ * reacquired. This returns a C++ discriminant instead of reading
632
+ * PyErr_Occurred, because convertBatch releases the GIL around the column
633
+ * loop. Throwing instead would terminate the process, as the Cython caller
634
+ * has no handler for a C++ exception.
635
+ */
636
+ static NanoTsCheck _checkNanosecondTimestampOverflowAndDownscale(
637
+ ArrowArrayView* columnArray, ArrowArrayView* epochArray,
638
+ ArrowArrayView* fractionArray) {
639
+ int powTenSB4 = sf::internal::powTenSB4[9];
640
+ for (int64_t rowIdx = 0; rowIdx < columnArray->array->length; rowIdx++) {
641
+ if (!ArrowArrayViewIsNull(columnArray, rowIdx)) {
642
+ int64_t epoch = ArrowArrayViewGetIntUnsafe(epochArray, rowIdx);
643
+ int64_t fraction = ArrowArrayViewGetIntUnsafe(fractionArray, rowIdx);
644
+ if (epoch > (INT64_MAX / powTenSB4) ||
645
+ epoch < (INT64_MIN / powTenSB4)) {
646
+ if (fraction % 1000 != 0) {
647
+ std::string errorInfo = Logger::formatString(
648
+ "The total number of nanoseconds %lld%09lld overflows int64 "
649
+ "range. If you use a timestamp with the nanosecond part over "
650
+ "6-digits in the Snowflake database, the timestamp must be "
651
+ "between '1677-09-21 00:12:43.145224192' and '2262-04-11 "
652
+ "23:47:16.854775807' to not overflow. Pass "
653
+ "force_microsecond_precision=True to truncate to microseconds "
654
+ "instead.",
655
+ static_cast<long long>(epoch), static_cast<long long>(fraction));
656
+ py::setPyError(PyExc_OverflowError, errorInfo.c_str());
657
+ return NanoTsCheck::Error;
658
+ }
659
+ return NanoTsCheck::Downscale;
660
+ }
661
+ }
662
+ }
663
+ return NanoTsCheck::InRange;
664
+ }
665
+
666
+ // ---------------------------------------------------------------------------
667
+ // Timestamp NTZ / LTZ
668
+ // ---------------------------------------------------------------------------
669
+
670
+ void ArrowTableConverter::convertTimestampColumn_nanoarrow(
671
+ ArrowSchemaView* field, ArrowArrayView* columnArray, int scale,
672
+ const std::string& timezone) {
673
+ int returnCode = 0;
674
+ nanoarrow::UniqueSchema newUniqueField;
675
+ nanoarrow::UniqueArray newUniqueArray;
676
+ ArrowSchema* newSchema = newUniqueField.get();
677
+ ArrowArray* newArray = newUniqueArray.get();
678
+ ArrowError error;
679
+
680
+ ArrowSchemaInit(newSchema);
681
+ newSchema->flags &= (field->schema->flags & ARROW_FLAG_NULLABLE);
682
+
683
+ const char* tz = timezone.empty() ? nullptr : timezone.c_str();
684
+
685
+ ArrowArrayView* epochArray = nullptr;
686
+ ArrowArrayView* fractionArray = nullptr;
687
+ bool has_overflow = m_force_microsecond_precision;
688
+ if (!m_force_microsecond_precision && scale > 6 &&
689
+ field->type == NANOARROW_TYPE_STRUCT) {
690
+ for (int64_t i = 0; i < field->schema->n_children; i++) {
691
+ const char* name = field->schema->children[i]->name;
692
+ if (std::strcmp(name, internal::FIELD_NAME_EPOCH.c_str()) == 0)
693
+ epochArray = columnArray->children[i];
694
+ else if (std::strcmp(name, internal::FIELD_NAME_FRACTION.c_str()) == 0)
695
+ fractionArray = columnArray->children[i];
696
+ }
697
+ auto check = _checkNanosecondTimestampOverflowAndDownscale(
698
+ columnArray, epochArray, fractionArray);
699
+ if (check == NanoTsCheck::Error) return;
700
+ has_overflow = (check == NanoTsCheck::Downscale);
701
+ }
702
+
703
+ if (scale <= 6) {
704
+ auto timeunit = NANOARROW_TIME_UNIT_SECOND;
705
+ int64_t powTenSB4Val = 1;
706
+ if (scale == 0) {
707
+ timeunit = NANOARROW_TIME_UNIT_SECOND;
708
+ } else if (scale <= 3) {
709
+ timeunit = NANOARROW_TIME_UNIT_MILLI;
710
+ powTenSB4Val = sf::internal::powTenSB4[3 - scale];
711
+ } else {
712
+ timeunit = NANOARROW_TIME_UNIT_MICRO;
713
+ powTenSB4Val = sf::internal::powTenSB4[6 - scale];
714
+ }
715
+ returnCode = ArrowSchemaSetTypeDateTime(
716
+ newSchema, NANOARROW_TYPE_TIMESTAMP, timeunit, tz);
717
+ SF_CHECK_ARROW_RC(returnCode,
718
+ "[Snowflake Exception] error setting schema DateTime, "
719
+ "error code: %d",
720
+ returnCode);
721
+ returnCode = ArrowSchemaSetName(newSchema, field->schema->name);
722
+ SF_CHECK_ARROW_RC(returnCode,
723
+ "[Snowflake Exception] error setting schema name, "
724
+ "error code: %d",
725
+ returnCode);
726
+ returnCode = ArrowArrayInitFromSchema(newArray, newSchema, &error);
727
+ SF_CHECK_ARROW_RC(returnCode,
728
+ "[Snowflake Exception] error initializing array: %s, "
729
+ "error code: %d",
730
+ ArrowErrorMessage(&error), returnCode);
731
+
732
+ for (int64_t rowIdx = 0; rowIdx < columnArray->array->length; rowIdx++) {
733
+ if (ArrowArrayViewIsNull(columnArray, rowIdx)) {
734
+ returnCode = ArrowArrayAppendNull(newArray, 1);
735
+ } else {
736
+ int64_t val =
737
+ ArrowArrayViewGetIntUnsafe(columnArray, rowIdx) * powTenSB4Val;
738
+ returnCode = ArrowArrayAppendInt(newArray, val);
739
+ }
740
+ SF_CHECK_ARROW_RC(returnCode,
741
+ "[Snowflake Exception] error appending timestamp, "
742
+ "error code: %d",
743
+ returnCode);
744
+ }
745
+ } else {
746
+ auto timeunit =
747
+ has_overflow ? NANOARROW_TIME_UNIT_MICRO : NANOARROW_TIME_UNIT_NANO;
748
+ returnCode = ArrowSchemaSetTypeDateTime(
749
+ newSchema, NANOARROW_TYPE_TIMESTAMP, timeunit, tz);
750
+ SF_CHECK_ARROW_RC(returnCode,
751
+ "[Snowflake Exception] error setting schema DateTime, "
752
+ "error code: %d",
753
+ returnCode);
754
+ returnCode = ArrowSchemaSetName(newSchema, field->schema->name);
755
+ SF_CHECK_ARROW_RC(returnCode,
756
+ "[Snowflake Exception] error setting schema name, "
757
+ "error code: %d",
758
+ returnCode);
759
+ returnCode = ArrowArrayInitFromSchema(newArray, newSchema, &error);
760
+ SF_CHECK_ARROW_RC(returnCode,
761
+ "[Snowflake Exception] error initializing array: %s, "
762
+ "error code: %d",
763
+ ArrowErrorMessage(&error), returnCode);
764
+
765
+ if (field->type == NANOARROW_TYPE_STRUCT) {
766
+ epochArray = nullptr;
767
+ fractionArray = nullptr;
768
+ for (int64_t i = 0; i < field->schema->n_children; i++) {
769
+ const char* name = field->schema->children[i]->name;
770
+ if (std::strcmp(name, internal::FIELD_NAME_EPOCH.c_str()) == 0)
771
+ epochArray = columnArray->children[i];
772
+ else if (std::strcmp(name, internal::FIELD_NAME_FRACTION.c_str()) == 0)
773
+ fractionArray = columnArray->children[i];
774
+ }
775
+ for (int64_t rowIdx = 0; rowIdx < columnArray->array->length; rowIdx++) {
776
+ if (ArrowArrayViewIsNull(columnArray, rowIdx)) {
777
+ returnCode = ArrowArrayAppendNull(newArray, 1);
778
+ } else {
779
+ int64_t epoch = ArrowArrayViewGetIntUnsafe(epochArray, rowIdx);
780
+ int64_t frac = ArrowArrayViewGetIntUnsafe(fractionArray, rowIdx);
781
+ int64_t val = has_overflow
782
+ ? (epoch * sf::internal::powTenSB4[6] + frac / 1000)
783
+ : (epoch * sf::internal::powTenSB4[9] + frac);
784
+ returnCode = ArrowArrayAppendInt(newArray, val);
785
+ }
786
+ SF_CHECK_ARROW_RC(returnCode,
787
+ "[Snowflake Exception] error appending timestamp, "
788
+ "error code: %d",
789
+ returnCode);
790
+ }
791
+ } else if (field->type == NANOARROW_TYPE_INT64) {
792
+ for (int64_t rowIdx = 0; rowIdx < columnArray->array->length; rowIdx++) {
793
+ if (ArrowArrayViewIsNull(columnArray, rowIdx)) {
794
+ returnCode = ArrowArrayAppendNull(newArray, 1);
795
+ } else {
796
+ int64_t val = ArrowArrayViewGetIntUnsafe(columnArray, rowIdx) *
797
+ sf::internal::powTenSB4[9 - scale];
798
+ returnCode = ArrowArrayAppendInt(newArray, val);
799
+ }
800
+ SF_CHECK_ARROW_RC(returnCode,
801
+ "[Snowflake Exception] error appending timestamp, "
802
+ "error code: %d",
803
+ returnCode);
804
+ }
805
+ }
806
+ }
807
+
808
+ returnCode = ArrowArrayFinishBuildingDefault(newArray, &error);
809
+ SF_CHECK_ARROW_RC(returnCode,
810
+ "[Snowflake Exception] error finishing array: %s, "
811
+ "error code: %d",
812
+ ArrowErrorMessage(&error), returnCode);
813
+ field->schema->release(field->schema);
814
+ ArrowSchemaMove(newSchema, field->schema);
815
+ columnArray->array->release(columnArray->array);
816
+ ArrowArrayMove(newArray, columnArray->array);
817
+ }
818
+
819
+ // ---------------------------------------------------------------------------
820
+ // Timestamp TZ
821
+ // ---------------------------------------------------------------------------
822
+
823
+ void ArrowTableConverter::convertTimestampTZColumn_nanoarrow(
824
+ ArrowSchemaView* field, ArrowArrayView* columnArray, int scale,
825
+ int byteLength, const std::string& timezone) {
826
+ int returnCode = 0;
827
+ nanoarrow::UniqueSchema newUniqueField;
828
+ nanoarrow::UniqueArray newUniqueArray;
829
+ ArrowSchema* newSchema = newUniqueField.get();
830
+ ArrowArray* newArray = newUniqueArray.get();
831
+ ArrowError error;
832
+
833
+ ArrowSchemaInit(newSchema);
834
+ newSchema->flags &= (field->schema->flags & ARROW_FLAG_NULLABLE);
835
+
836
+ ArrowArrayView* epochArray = nullptr;
837
+ ArrowArrayView* fractionArray = nullptr;
838
+ for (int64_t i = 0; i < field->schema->n_children; i++) {
839
+ const char* name = field->schema->children[i]->name;
840
+ if (std::strcmp(name, internal::FIELD_NAME_EPOCH.c_str()) == 0)
841
+ epochArray = columnArray->children[i];
842
+ else if (std::strcmp(name, internal::FIELD_NAME_FRACTION.c_str()) == 0)
843
+ fractionArray = columnArray->children[i];
844
+ }
845
+
846
+ bool has_overflow = m_force_microsecond_precision;
847
+ if (!m_force_microsecond_precision && scale > 6 && byteLength == 16) {
848
+ auto check = _checkNanosecondTimestampOverflowAndDownscale(
849
+ columnArray, epochArray, fractionArray);
850
+ if (check == NanoTsCheck::Error) return;
851
+ has_overflow = (check == NanoTsCheck::Downscale);
852
+ }
853
+
854
+ auto timeunit = NANOARROW_TIME_UNIT_SECOND;
855
+ if (scale == 0)
856
+ timeunit = NANOARROW_TIME_UNIT_SECOND;
857
+ else if (scale <= 3)
858
+ timeunit = NANOARROW_TIME_UNIT_MILLI;
859
+ else if (scale <= 6)
860
+ timeunit = NANOARROW_TIME_UNIT_MICRO;
861
+ else
862
+ timeunit =
863
+ has_overflow ? NANOARROW_TIME_UNIT_MICRO : NANOARROW_TIME_UNIT_NANO;
864
+
865
+ const char* tz = timezone.empty() ? nullptr : timezone.c_str();
866
+ returnCode = ArrowSchemaSetTypeDateTime(
867
+ newSchema, NANOARROW_TYPE_TIMESTAMP, timeunit, tz);
868
+ SF_CHECK_ARROW_RC(returnCode,
869
+ "[Snowflake Exception] error setting schema DateTime, "
870
+ "error code: %d",
871
+ returnCode);
872
+ returnCode = ArrowSchemaSetName(newSchema, field->schema->name);
873
+ SF_CHECK_ARROW_RC(returnCode,
874
+ "[Snowflake Exception] error setting schema name, "
875
+ "error code: %d",
876
+ returnCode);
877
+ returnCode = ArrowArrayInitFromSchema(newArray, newSchema, &error);
878
+ SF_CHECK_ARROW_RC(returnCode,
879
+ "[Snowflake Exception] error initializing array: %s, "
880
+ "error code: %d",
881
+ ArrowErrorMessage(&error), returnCode);
882
+
883
+ for (int64_t rowIdx = 0; rowIdx < columnArray->array->length; rowIdx++) {
884
+ if (ArrowArrayViewIsNull(columnArray, rowIdx)) {
885
+ returnCode = ArrowArrayAppendNull(newArray, 1);
886
+ } else {
887
+ int64_t epoch = ArrowArrayViewGetIntUnsafe(epochArray, rowIdx);
888
+ if (byteLength == 8) {
889
+ int64_t val;
890
+ if (scale == 0)
891
+ val = epoch;
892
+ else if (scale <= 3)
893
+ val = epoch * sf::internal::powTenSB4[3 - scale];
894
+ else if (scale <= 6)
895
+ val = epoch * sf::internal::powTenSB4[6 - scale];
896
+ else
897
+ val = has_overflow ? (epoch * sf::internal::powTenSB4[6])
898
+ : (epoch * sf::internal::powTenSB4[9 - scale]);
899
+ returnCode = ArrowArrayAppendInt(newArray, val);
900
+ } else if (byteLength == 16) {
901
+ int64_t frac = ArrowArrayViewGetIntUnsafe(fractionArray, rowIdx);
902
+ int64_t val;
903
+ if (scale == 0)
904
+ val = epoch;
905
+ else if (scale <= 3)
906
+ val = epoch * sf::internal::powTenSB4[3 - scale] +
907
+ frac / sf::internal::powTenSB4[6];
908
+ else if (scale <= 6)
909
+ val = epoch * sf::internal::powTenSB4[6] +
910
+ frac / sf::internal::powTenSB4[3];
911
+ else
912
+ val = has_overflow
913
+ ? (epoch * sf::internal::powTenSB4[6] + frac / 1000)
914
+ : (epoch * sf::internal::powTenSB4[9] + frac);
915
+ returnCode = ArrowArrayAppendInt(newArray, val);
916
+ } else {
917
+ py::setPyError(
918
+ PyExc_Exception,
919
+ Logger::formatString(
920
+ "[Snowflake Exception] unknown byteLength(%d) for "
921
+ "TIMESTAMP_TZ",
922
+ byteLength).c_str());
923
+ return;
924
+ }
925
+ }
926
+ SF_CHECK_ARROW_RC(returnCode,
927
+ "[Snowflake Exception] error appending timestamp_tz, "
928
+ "error code: %d",
929
+ returnCode);
930
+ }
931
+
932
+ returnCode = ArrowArrayFinishBuildingDefault(newArray, &error);
933
+ SF_CHECK_ARROW_RC(returnCode,
934
+ "[Snowflake Exception] error finishing array: %s, "
935
+ "error code: %d",
936
+ ArrowErrorMessage(&error), returnCode);
937
+ field->schema->release(field->schema);
938
+ ArrowSchemaMove(newSchema, field->schema);
939
+ columnArray->array->release(columnArray->array);
940
+ ArrowArrayMove(newArray, columnArray->array);
941
+ }
942
+
943
+ } // namespace sf