1 | //===----------------------------------------------------------------------===// |
2 | // DuckDB |
3 | // |
4 | // duckdb/main/capi/cast/utils.hpp |
5 | // |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #pragma once |
10 | |
11 | #include "duckdb/main/capi/capi_internal.hpp" |
12 | #include "duckdb/common/operator/cast_operators.hpp" |
13 | #include "duckdb/common/operator/string_cast.hpp" |
14 | #include "duckdb/common/operator/decimal_cast_operators.hpp" |
15 | |
16 | namespace duckdb { |
17 | |
18 | //===--------------------------------------------------------------------===// |
19 | // Unsafe Fetch (for internal use only) |
20 | //===--------------------------------------------------------------------===// |
21 | template <class T> |
22 | T UnsafeFetchFromPtr(void *pointer) { |
23 | return *((T *)pointer); |
24 | } |
25 | |
26 | template <class T> |
27 | void *UnsafeFetchPtr(duckdb_result *result, idx_t col, idx_t row) { |
28 | D_ASSERT(row < result->__deprecated_row_count); |
29 | return (void *)&(((T *)result->__deprecated_columns[col].__deprecated_data)[row]); |
30 | } |
31 | |
32 | template <class T> |
33 | T UnsafeFetch(duckdb_result *result, idx_t col, idx_t row) { |
34 | return UnsafeFetchFromPtr<T>(UnsafeFetchPtr<T>(result, col, row)); |
35 | } |
36 | |
37 | //===--------------------------------------------------------------------===// |
38 | // Fetch Default Value |
39 | //===--------------------------------------------------------------------===// |
40 | struct FetchDefaultValue { |
41 | template <class T> |
42 | static T Operation() { |
43 | return 0; |
44 | } |
45 | }; |
46 | |
47 | template <> |
48 | duckdb_decimal FetchDefaultValue::Operation(); |
49 | template <> |
50 | date_t FetchDefaultValue::Operation(); |
51 | template <> |
52 | dtime_t FetchDefaultValue::Operation(); |
53 | template <> |
54 | timestamp_t FetchDefaultValue::Operation(); |
55 | template <> |
56 | interval_t FetchDefaultValue::Operation(); |
57 | template <> |
58 | char *FetchDefaultValue::Operation(); |
59 | template <> |
60 | duckdb_string FetchDefaultValue::Operation(); |
61 | template <> |
62 | duckdb_blob FetchDefaultValue::Operation(); |
63 | |
64 | //===--------------------------------------------------------------------===// |
65 | // String Casts |
66 | //===--------------------------------------------------------------------===// |
67 | template <class OP> |
68 | struct FromCStringCastWrapper { |
69 | template <class SOURCE_TYPE, class RESULT_TYPE> |
70 | static bool Operation(SOURCE_TYPE input_str, RESULT_TYPE &result) { |
71 | string_t input(input_str); |
72 | return OP::template Operation<string_t, RESULT_TYPE>(input, result); |
73 | } |
74 | }; |
75 | |
76 | template <class OP> |
77 | struct ToCStringCastWrapper { |
78 | template <class SOURCE_TYPE, class RESULT_TYPE> |
79 | static bool Operation(SOURCE_TYPE input, RESULT_TYPE &result) { |
80 | Vector result_vector(LogicalType::VARCHAR, nullptr); |
81 | auto result_string = OP::template Operation<SOURCE_TYPE>(input, result_vector); |
82 | auto result_size = result_string.GetSize(); |
83 | auto result_data = result_string.GetData(); |
84 | |
85 | char *allocated_data = char_ptr_cast(duckdb_malloc(result_size + 1)); |
86 | memcpy(allocated_data, result_data, result_size); |
87 | allocated_data[result_size] = '\0'; |
88 | result.data = allocated_data; |
89 | result.size = result_size; |
90 | return true; |
91 | } |
92 | }; |
93 | |
94 | //===--------------------------------------------------------------------===// |
95 | // Blob Casts |
96 | //===--------------------------------------------------------------------===// |
97 | struct FromCBlobCastWrapper { |
98 | template <class SOURCE_TYPE, class RESULT_TYPE> |
99 | static bool Operation(SOURCE_TYPE input_str, RESULT_TYPE &result) { |
100 | return false; |
101 | } |
102 | }; |
103 | |
104 | template <> |
105 | bool FromCBlobCastWrapper::Operation(duckdb_blob input, duckdb_string &result); |
106 | |
107 | template <class SOURCE_TYPE, class RESULT_TYPE, class OP> |
108 | RESULT_TYPE TryCastCInternal(duckdb_result *result, idx_t col, idx_t row) { |
109 | RESULT_TYPE result_value; |
110 | try { |
111 | if (!OP::template Operation<SOURCE_TYPE, RESULT_TYPE>(UnsafeFetch<SOURCE_TYPE>(result, col, row), |
112 | result_value)) { |
113 | return FetchDefaultValue::Operation<RESULT_TYPE>(); |
114 | } |
115 | } catch (...) { |
116 | return FetchDefaultValue::Operation<RESULT_TYPE>(); |
117 | } |
118 | return result_value; |
119 | } |
120 | |
121 | } // namespace duckdb |
122 | |
123 | bool CanFetchValue(duckdb_result *result, idx_t col, idx_t row); |
124 | bool CanUseDeprecatedFetch(duckdb_result *result, idx_t col, idx_t row); |
125 | |