1#include "duckdb/main/capi/cast/from_decimal.hpp"
2#include "duckdb/common/types/decimal.hpp"
3
4namespace duckdb {
5
6//! DECIMAL -> VARCHAR
7template <>
8bool CastDecimalCInternal(duckdb_result *source, duckdb_string &result, idx_t col, idx_t row) {
9 auto result_data = (duckdb::DuckDBResultData *)source->internal_data;
10 auto &query_result = result_data->result;
11 auto &source_type = query_result->types[col];
12 auto width = duckdb::DecimalType::GetWidth(type: source_type);
13 auto scale = duckdb::DecimalType::GetScale(type: source_type);
14 duckdb::Vector result_vec(duckdb::LogicalType::VARCHAR, false, false);
15 duckdb::string_t result_string;
16 void *source_address = UnsafeFetchPtr<hugeint_t>(result: source, col, row);
17 switch (source_type.InternalType()) {
18 case duckdb::PhysicalType::INT16:
19 result_string = duckdb::StringCastFromDecimal::Operation<int16_t>(input: UnsafeFetchFromPtr<int16_t>(pointer: source_address),
20 width, scale, result&: result_vec);
21 break;
22 case duckdb::PhysicalType::INT32:
23 result_string = duckdb::StringCastFromDecimal::Operation<int32_t>(input: UnsafeFetchFromPtr<int32_t>(pointer: source_address),
24 width, scale, result&: result_vec);
25 break;
26 case duckdb::PhysicalType::INT64:
27 result_string = duckdb::StringCastFromDecimal::Operation<int64_t>(input: UnsafeFetchFromPtr<int64_t>(pointer: source_address),
28 width, scale, result&: result_vec);
29 break;
30 case duckdb::PhysicalType::INT128:
31 result_string = duckdb::StringCastFromDecimal::Operation<hugeint_t>(
32 input: UnsafeFetchFromPtr<hugeint_t>(pointer: source_address), width, scale, result&: result_vec);
33 break;
34 default:
35 throw duckdb::InternalException("Unimplemented internal type for decimal");
36 }
37 result.data = reinterpret_cast<char *>(duckdb_malloc(size: sizeof(char) * (result_string.GetSize() + 1)));
38 memcpy(dest: result.data, src: result_string.GetData(), n: result_string.GetSize());
39 result.data[result_string.GetSize()] = '\0';
40 result.size = result_string.GetSize();
41 return true;
42}
43
44template <class INTERNAL_TYPE>
45duckdb_hugeint FetchInternals(void *source_address) {
46 throw duckdb::NotImplementedException("FetchInternals not implemented for internal type");
47}
48
49template <>
50duckdb_hugeint FetchInternals<int16_t>(void *source_address) {
51 duckdb_hugeint result;
52 int16_t intermediate_result;
53
54 if (!TryCast::Operation<int16_t, int16_t>(input: UnsafeFetchFromPtr<int16_t>(pointer: source_address), result&: intermediate_result)) {
55 intermediate_result = FetchDefaultValue::Operation<int16_t>();
56 }
57 hugeint_t hugeint_result = Hugeint::Cast<int16_t>(input: intermediate_result);
58 result.lower = hugeint_result.lower;
59 result.upper = hugeint_result.upper;
60 return result;
61}
62template <>
63duckdb_hugeint FetchInternals<int32_t>(void *source_address) {
64 duckdb_hugeint result;
65 int32_t intermediate_result;
66
67 if (!TryCast::Operation<int32_t, int32_t>(input: UnsafeFetchFromPtr<int32_t>(pointer: source_address), result&: intermediate_result)) {
68 intermediate_result = FetchDefaultValue::Operation<int32_t>();
69 }
70 hugeint_t hugeint_result = Hugeint::Cast<int32_t>(input: intermediate_result);
71 result.lower = hugeint_result.lower;
72 result.upper = hugeint_result.upper;
73 return result;
74}
75template <>
76duckdb_hugeint FetchInternals<int64_t>(void *source_address) {
77 duckdb_hugeint result;
78 int64_t intermediate_result;
79
80 if (!TryCast::Operation<int64_t, int64_t>(input: UnsafeFetchFromPtr<int64_t>(pointer: source_address), result&: intermediate_result)) {
81 intermediate_result = FetchDefaultValue::Operation<int64_t>();
82 }
83 hugeint_t hugeint_result = Hugeint::Cast<int64_t>(input: intermediate_result);
84 result.lower = hugeint_result.lower;
85 result.upper = hugeint_result.upper;
86 return result;
87}
88template <>
89duckdb_hugeint FetchInternals<hugeint_t>(void *source_address) {
90 duckdb_hugeint result;
91 hugeint_t intermediate_result;
92
93 if (!TryCast::Operation<hugeint_t, hugeint_t>(input: UnsafeFetchFromPtr<hugeint_t>(pointer: source_address), result&: intermediate_result)) {
94 intermediate_result = FetchDefaultValue::Operation<hugeint_t>();
95 }
96 result.lower = intermediate_result.lower;
97 result.upper = intermediate_result.upper;
98 return result;
99}
100
101//! DECIMAL -> DECIMAL (internal fetch)
102template <>
103bool CastDecimalCInternal(duckdb_result *source, duckdb_decimal &result, idx_t col, idx_t row) {
104 auto result_data = (duckdb::DuckDBResultData *)source->internal_data;
105 result_data->result->types[col].GetDecimalProperties(width&: result.width, scale&: result.scale);
106 auto source_address = UnsafeFetchPtr<hugeint_t>(result: source, col, row);
107
108 if (result.width > duckdb::Decimal::MAX_WIDTH_INT64) {
109 result.value = FetchInternals<hugeint_t>(source_address);
110 } else if (result.width > duckdb::Decimal::MAX_WIDTH_INT32) {
111 result.value = FetchInternals<int64_t>(source_address);
112 } else if (result.width > duckdb::Decimal::MAX_WIDTH_INT16) {
113 result.value = FetchInternals<int32_t>(source_address);
114 } else {
115 result.value = FetchInternals<int16_t>(source_address);
116 }
117 return true;
118}
119
120} // namespace duckdb
121