1 | //===----------------------------------------------------------------------===// |
2 | // DuckDB |
3 | // |
4 | // duckdb/function/cast/default_casts.hpp |
5 | // |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #pragma once |
10 | |
11 | #include "duckdb/common/types.hpp" |
12 | #include "duckdb/common/types/vector.hpp" |
13 | #include "duckdb/common/helper.hpp" |
14 | #include "duckdb/common/optional_ptr.hpp" |
15 | #include "duckdb/function/scalar_function.hpp" |
16 | |
17 | namespace duckdb { |
18 | |
19 | class CastFunctionSet; |
20 | struct FunctionLocalState; |
21 | |
22 | //! Extra data that can be attached to a bind function of a cast, and is available during binding |
23 | struct BindCastInfo { |
24 | DUCKDB_API virtual ~BindCastInfo(); |
25 | |
26 | template <class TARGET> |
27 | TARGET &Cast() { |
28 | D_ASSERT(dynamic_cast<TARGET *>(this)); |
29 | return reinterpret_cast<TARGET &>(*this); |
30 | } |
31 | template <class TARGET> |
32 | const TARGET &Cast() const { |
33 | D_ASSERT(dynamic_cast<const TARGET *>(this)); |
34 | return reinterpret_cast<const TARGET &>(*this); |
35 | } |
36 | }; |
37 | |
38 | //! Extra data that can be returned by the bind of a cast, and is available during execution of a cast |
39 | struct BoundCastData { |
40 | DUCKDB_API virtual ~BoundCastData(); |
41 | |
42 | DUCKDB_API virtual unique_ptr<BoundCastData> Copy() const = 0; |
43 | |
44 | template <class TARGET> |
45 | TARGET &Cast() { |
46 | D_ASSERT(dynamic_cast<TARGET *>(this)); |
47 | return reinterpret_cast<TARGET &>(*this); |
48 | } |
49 | template <class TARGET> |
50 | const TARGET &Cast() const { |
51 | D_ASSERT(dynamic_cast<const TARGET *>(this)); |
52 | return reinterpret_cast<const TARGET &>(*this); |
53 | } |
54 | }; |
55 | |
56 | struct CastParameters { |
57 | CastParameters() { |
58 | } |
59 | CastParameters(BoundCastData *cast_data, bool strict, string *error_message, |
60 | optional_ptr<FunctionLocalState> local_state) |
61 | : cast_data(cast_data), strict(strict), error_message(error_message), local_state(local_state) { |
62 | } |
63 | CastParameters(CastParameters &parent, optional_ptr<BoundCastData> cast_data, |
64 | optional_ptr<FunctionLocalState> local_state) |
65 | : cast_data(cast_data), strict(parent.strict), error_message(parent.error_message), local_state(local_state) { |
66 | } |
67 | |
68 | //! The bound cast data (if any) |
69 | optional_ptr<BoundCastData> cast_data; |
70 | //! whether or not to enable strict casting |
71 | bool strict = false; |
72 | // out: error message in case cast has failed |
73 | string *error_message = nullptr; |
74 | //! Local state |
75 | optional_ptr<FunctionLocalState> local_state; |
76 | }; |
77 | |
78 | struct CastLocalStateParameters { |
79 | CastLocalStateParameters(optional_ptr<ClientContext> context_p, optional_ptr<BoundCastData> cast_data_p) |
80 | : context(context_p), cast_data(cast_data_p) { |
81 | } |
82 | CastLocalStateParameters(ClientContext &context_p, optional_ptr<BoundCastData> cast_data_p) |
83 | : context(&context_p), cast_data(cast_data_p) { |
84 | } |
85 | CastLocalStateParameters(CastLocalStateParameters &parent, optional_ptr<BoundCastData> cast_data_p) |
86 | : context(parent.context), cast_data(cast_data_p) { |
87 | } |
88 | |
89 | optional_ptr<ClientContext> context; |
90 | //! The bound cast data (if any) |
91 | optional_ptr<BoundCastData> cast_data; |
92 | }; |
93 | |
94 | typedef bool (*cast_function_t)(Vector &source, Vector &result, idx_t count, CastParameters ¶meters); |
95 | typedef unique_ptr<FunctionLocalState> (*init_cast_local_state_t)(CastLocalStateParameters ¶meters); |
96 | |
97 | struct BoundCastInfo { |
98 | DUCKDB_API |
99 | BoundCastInfo( |
100 | cast_function_t function, unique_ptr<BoundCastData> cast_data = nullptr, |
101 | init_cast_local_state_t init_local_state = nullptr); // NOLINT: allow explicit cast from cast_function_t |
102 | cast_function_t function; |
103 | init_cast_local_state_t init_local_state; |
104 | unique_ptr<BoundCastData> cast_data; |
105 | |
106 | public: |
107 | BoundCastInfo Copy() const; |
108 | }; |
109 | |
110 | struct BindCastInput { |
111 | DUCKDB_API BindCastInput(CastFunctionSet &function_set, optional_ptr<BindCastInfo> info, |
112 | optional_ptr<ClientContext> context); |
113 | |
114 | CastFunctionSet &function_set; |
115 | optional_ptr<BindCastInfo> info; |
116 | optional_ptr<ClientContext> context; |
117 | |
118 | public: |
119 | DUCKDB_API BoundCastInfo GetCastFunction(const LogicalType &source, const LogicalType &target); |
120 | }; |
121 | |
122 | struct DefaultCasts { |
123 | DUCKDB_API static BoundCastInfo GetDefaultCastFunction(BindCastInput &input, const LogicalType &source, |
124 | const LogicalType &target); |
125 | |
126 | DUCKDB_API static bool NopCast(Vector &source, Vector &result, idx_t count, CastParameters ¶meters); |
127 | DUCKDB_API static bool TryVectorNullCast(Vector &source, Vector &result, idx_t count, CastParameters ¶meters); |
128 | DUCKDB_API static bool ReinterpretCast(Vector &source, Vector &result, idx_t count, CastParameters ¶meters); |
129 | |
130 | private: |
131 | static BoundCastInfo BlobCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
132 | static BoundCastInfo BitCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
133 | static BoundCastInfo DateCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
134 | static BoundCastInfo DecimalCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
135 | static BoundCastInfo EnumCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
136 | static BoundCastInfo IntervalCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
137 | static BoundCastInfo ListCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
138 | static BoundCastInfo NumericCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
139 | static BoundCastInfo MapCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
140 | static BoundCastInfo PointerCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
141 | static BoundCastInfo StringCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
142 | static BoundCastInfo StructCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
143 | static BoundCastInfo TimeCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
144 | static BoundCastInfo TimeTzCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
145 | static BoundCastInfo TimestampCastSwitch(BindCastInput &input, const LogicalType &source, |
146 | const LogicalType &target); |
147 | static BoundCastInfo TimestampTzCastSwitch(BindCastInput &input, const LogicalType &source, |
148 | const LogicalType &target); |
149 | static BoundCastInfo TimestampNsCastSwitch(BindCastInput &input, const LogicalType &source, |
150 | const LogicalType &target); |
151 | static BoundCastInfo TimestampMsCastSwitch(BindCastInput &input, const LogicalType &source, |
152 | const LogicalType &target); |
153 | static BoundCastInfo TimestampSecCastSwitch(BindCastInput &input, const LogicalType &source, |
154 | const LogicalType &target); |
155 | static BoundCastInfo UnionCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
156 | static BoundCastInfo UUIDCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target); |
157 | |
158 | static BoundCastInfo ImplicitToUnionCast(BindCastInput &input, const LogicalType &source, |
159 | const LogicalType &target); |
160 | }; |
161 | |
162 | } // namespace duckdb |
163 | |