1 | //===----------------------------------------------------------------------===// |
2 | // DuckDB |
3 | // |
4 | // duckdb/main/capi/capi_cast_from_decimal.hpp |
5 | // |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #pragma once |
10 | |
11 | #include "duckdb/main/capi/cast/utils.hpp" |
12 | |
13 | namespace duckdb { |
14 | |
15 | template <class INTERNAL_TYPE> |
16 | struct ToCDecimalCastWrapper { |
17 | template <class SOURCE_TYPE> |
18 | static bool Operation(SOURCE_TYPE input, duckdb_decimal &result, std::string *error, uint8_t width, uint8_t scale) { |
19 | throw NotImplementedException("Type not implemented for CDecimalCastWrapper" ); |
20 | } |
21 | }; |
22 | |
23 | //! Hugeint |
24 | template <> |
25 | struct ToCDecimalCastWrapper<hugeint_t> { |
26 | template <class SOURCE_TYPE> |
27 | static bool Operation(SOURCE_TYPE input, duckdb_decimal &result, std::string *error, uint8_t width, uint8_t scale) { |
28 | hugeint_t intermediate_result; |
29 | |
30 | if (!TryCastToDecimal::Operation<SOURCE_TYPE, hugeint_t>(input, intermediate_result, error, width, scale)) { |
31 | result = FetchDefaultValue::Operation<duckdb_decimal>(); |
32 | return false; |
33 | } |
34 | result.scale = scale; |
35 | result.width = width; |
36 | |
37 | duckdb_hugeint hugeint_value; |
38 | hugeint_value.upper = intermediate_result.upper; |
39 | hugeint_value.lower = intermediate_result.lower; |
40 | result.value = hugeint_value; |
41 | return true; |
42 | } |
43 | }; |
44 | |
45 | //! FIXME: reduce duplication here by just matching on the signed-ness of the type |
46 | //! INTERNAL_TYPE = int16_t |
47 | template <> |
48 | struct ToCDecimalCastWrapper<int16_t> { |
49 | template <class SOURCE_TYPE> |
50 | static bool Operation(SOURCE_TYPE input, duckdb_decimal &result, std::string *error, uint8_t width, uint8_t scale) { |
51 | int16_t intermediate_result; |
52 | |
53 | if (!TryCastToDecimal::Operation<SOURCE_TYPE, int16_t>(input, intermediate_result, error, width, scale)) { |
54 | result = FetchDefaultValue::Operation<duckdb_decimal>(); |
55 | return false; |
56 | } |
57 | hugeint_t hugeint_result = Hugeint::Convert(value: intermediate_result); |
58 | |
59 | result.scale = scale; |
60 | result.width = width; |
61 | |
62 | duckdb_hugeint hugeint_value; |
63 | hugeint_value.upper = hugeint_result.upper; |
64 | hugeint_value.lower = hugeint_result.lower; |
65 | result.value = hugeint_value; |
66 | return true; |
67 | } |
68 | }; |
69 | //! INTERNAL_TYPE = int32_t |
70 | template <> |
71 | struct ToCDecimalCastWrapper<int32_t> { |
72 | template <class SOURCE_TYPE> |
73 | static bool Operation(SOURCE_TYPE input, duckdb_decimal &result, std::string *error, uint8_t width, uint8_t scale) { |
74 | int32_t intermediate_result; |
75 | |
76 | if (!TryCastToDecimal::Operation<SOURCE_TYPE, int32_t>(input, intermediate_result, error, width, scale)) { |
77 | result = FetchDefaultValue::Operation<duckdb_decimal>(); |
78 | return false; |
79 | } |
80 | hugeint_t hugeint_result = Hugeint::Convert(value: intermediate_result); |
81 | |
82 | result.scale = scale; |
83 | result.width = width; |
84 | |
85 | duckdb_hugeint hugeint_value; |
86 | hugeint_value.upper = hugeint_result.upper; |
87 | hugeint_value.lower = hugeint_result.lower; |
88 | result.value = hugeint_value; |
89 | return true; |
90 | } |
91 | }; |
92 | //! INTERNAL_TYPE = int64_t |
93 | template <> |
94 | struct ToCDecimalCastWrapper<int64_t> { |
95 | template <class SOURCE_TYPE> |
96 | static bool Operation(SOURCE_TYPE input, duckdb_decimal &result, std::string *error, uint8_t width, uint8_t scale) { |
97 | int64_t intermediate_result; |
98 | |
99 | if (!TryCastToDecimal::Operation<SOURCE_TYPE, int64_t>(input, intermediate_result, error, width, scale)) { |
100 | result = FetchDefaultValue::Operation<duckdb_decimal>(); |
101 | return false; |
102 | } |
103 | hugeint_t hugeint_result = Hugeint::Convert(value: intermediate_result); |
104 | |
105 | result.scale = scale; |
106 | result.width = width; |
107 | |
108 | duckdb_hugeint hugeint_value; |
109 | hugeint_value.upper = hugeint_result.upper; |
110 | hugeint_value.lower = hugeint_result.lower; |
111 | result.value = hugeint_value; |
112 | return true; |
113 | } |
114 | }; |
115 | |
116 | template <class SOURCE_TYPE, class OP> |
117 | duckdb_decimal TryCastToDecimalCInternal(SOURCE_TYPE source, uint8_t width, uint8_t scale) { |
118 | duckdb_decimal result; |
119 | try { |
120 | if (!OP::template Operation<SOURCE_TYPE>(source, result, nullptr, width, scale)) { |
121 | return FetchDefaultValue::Operation<duckdb_decimal>(); |
122 | } |
123 | } catch (...) { |
124 | return FetchDefaultValue::Operation<duckdb_decimal>(); |
125 | } |
126 | return result; |
127 | } |
128 | |
129 | template <class SOURCE_TYPE, class OP> |
130 | duckdb_decimal TryCastToDecimalCInternal(duckdb_result *result, idx_t col, idx_t row, uint8_t width, uint8_t scale) { |
131 | return TryCastToDecimalCInternal<SOURCE_TYPE, OP>(UnsafeFetch<SOURCE_TYPE>(result, col, row), width, scale); |
132 | } |
133 | |
134 | } // namespace duckdb |
135 | |