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
13namespace duckdb {
14
15template <class INTERNAL_TYPE>
16struct 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
24template <>
25struct 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
47template <>
48struct 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
70template <>
71struct 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
93template <>
94struct 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
116template <class SOURCE_TYPE, class OP>
117duckdb_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
129template <class SOURCE_TYPE, class OP>
130duckdb_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