1 | //===--------------------------------------------------------------------===// |
2 | // cast_operators.cpp |
3 | // Description: This file contains the implementation of the different casts |
4 | //===--------------------------------------------------------------------===// |
5 | #include "duckdb/common/operator/cast_operators.hpp" |
6 | #include "duckdb/common/types/chunk_collection.hpp" |
7 | #include "duckdb/common/vector_operations/unary_executor.hpp" |
8 | #include "duckdb/common/vector_operations/vector_operations.hpp" |
9 | |
10 | using namespace duckdb; |
11 | using namespace std; |
12 | |
13 | template <class SRC, class OP> static void string_cast(Vector &source, Vector &result, idx_t count) { |
14 | assert(result.type == TypeId::VARCHAR); |
15 | UnaryExecutor::Execute<SRC, string_t, true>(source, result, count, |
16 | [&](SRC input) { return OP::template Operation<SRC>(input, result); }); |
17 | } |
18 | |
19 | static NotImplementedException UnimplementedCast(SQLType source_type, SQLType target_type) { |
20 | return NotImplementedException("Unimplemented type for cast (%s -> %s)" , SQLTypeToString(source_type).c_str(), |
21 | SQLTypeToString(target_type).c_str()); |
22 | } |
23 | |
24 | // NULL cast only works if all values in source are NULL, otherwise an unimplemented cast exception is thrown |
25 | static void null_cast(Vector &source, Vector &result, SQLType source_type, SQLType target_type, idx_t count) { |
26 | if (VectorOperations::HasNotNull(source, count)) { |
27 | throw UnimplementedCast(source_type, target_type); |
28 | } |
29 | if (source.vector_type == VectorType::CONSTANT_VECTOR) { |
30 | result.vector_type = VectorType::CONSTANT_VECTOR; |
31 | ConstantVector::SetNull(result, true); |
32 | } else { |
33 | result.vector_type = VectorType::FLAT_VECTOR; |
34 | FlatVector::Nullmask(result).set(); |
35 | } |
36 | } |
37 | |
38 | template <class SRC> |
39 | static void numeric_cast_switch(Vector &source, Vector &result, SQLType source_type, SQLType target_type, idx_t count) { |
40 | // now switch on the result type |
41 | switch (target_type.id) { |
42 | case SQLTypeId::BOOLEAN: |
43 | assert(result.type == TypeId::BOOL); |
44 | UnaryExecutor::Execute<SRC, bool, duckdb::Cast, true>(source, result, count); |
45 | break; |
46 | case SQLTypeId::TINYINT: |
47 | assert(result.type == TypeId::INT8); |
48 | UnaryExecutor::Execute<SRC, int8_t, duckdb::Cast, true>(source, result, count); |
49 | break; |
50 | case SQLTypeId::SMALLINT: |
51 | assert(result.type == TypeId::INT16); |
52 | UnaryExecutor::Execute<SRC, int16_t, duckdb::Cast, true>(source, result, count); |
53 | break; |
54 | case SQLTypeId::INTEGER: |
55 | assert(result.type == TypeId::INT32); |
56 | UnaryExecutor::Execute<SRC, int32_t, duckdb::Cast, true>(source, result, count); |
57 | break; |
58 | case SQLTypeId::BIGINT: |
59 | assert(result.type == TypeId::INT64); |
60 | UnaryExecutor::Execute<SRC, int64_t, duckdb::Cast, true>(source, result, count); |
61 | break; |
62 | case SQLTypeId::FLOAT: |
63 | assert(result.type == TypeId::FLOAT); |
64 | UnaryExecutor::Execute<SRC, float, duckdb::Cast, true>(source, result, count); |
65 | break; |
66 | case SQLTypeId::DECIMAL: |
67 | case SQLTypeId::DOUBLE: |
68 | assert(result.type == TypeId::DOUBLE); |
69 | UnaryExecutor::Execute<SRC, double, duckdb::Cast, true>(source, result, count); |
70 | break; |
71 | case SQLTypeId::VARCHAR: { |
72 | string_cast<SRC, duckdb::StringCast>(source, result, count); |
73 | break; |
74 | } |
75 | case SQLTypeId::LIST: { |
76 | assert(result.type == TypeId::LIST); |
77 | auto list_child = make_unique<ChunkCollection>(); |
78 | ListVector::SetEntry(result, move(list_child)); |
79 | null_cast(source, result, source_type, target_type, count); |
80 | break; |
81 | } |
82 | default: |
83 | null_cast(source, result, source_type, target_type, count); |
84 | break; |
85 | } |
86 | } |
87 | |
88 | template <class OP> |
89 | static void string_cast_numric_switch(Vector &source, Vector &result, SQLType source_type, SQLType target_type, |
90 | idx_t count) { |
91 | // now switch on the result type |
92 | switch (target_type.id) { |
93 | case SQLTypeId::BOOLEAN: |
94 | assert(result.type == TypeId::BOOL); |
95 | UnaryExecutor::Execute<string_t, bool, OP, true>(source, result, count); |
96 | break; |
97 | case SQLTypeId::TINYINT: |
98 | assert(result.type == TypeId::INT8); |
99 | UnaryExecutor::Execute<string_t, int8_t, OP, true>(source, result, count); |
100 | break; |
101 | case SQLTypeId::SMALLINT: |
102 | assert(result.type == TypeId::INT16); |
103 | UnaryExecutor::Execute<string_t, int16_t, OP, true>(source, result, count); |
104 | break; |
105 | case SQLTypeId::INTEGER: |
106 | assert(result.type == TypeId::INT32); |
107 | UnaryExecutor::Execute<string_t, int32_t, OP, true>(source, result, count); |
108 | break; |
109 | case SQLTypeId::BIGINT: |
110 | assert(result.type == TypeId::INT64); |
111 | UnaryExecutor::Execute<string_t, int64_t, OP, true>(source, result, count); |
112 | break; |
113 | case SQLTypeId::FLOAT: |
114 | assert(result.type == TypeId::FLOAT); |
115 | UnaryExecutor::Execute<string_t, float, OP, true>(source, result, count); |
116 | break; |
117 | case SQLTypeId::DECIMAL: |
118 | case SQLTypeId::DOUBLE: |
119 | assert(result.type == TypeId::DOUBLE); |
120 | UnaryExecutor::Execute<string_t, double, OP, true>(source, result, count); |
121 | break; |
122 | default: |
123 | null_cast(source, result, source_type, target_type, count); |
124 | break; |
125 | } |
126 | } |
127 | |
128 | static void string_cast_switch(Vector &source, Vector &result, SQLType source_type, SQLType target_type, idx_t count, |
129 | bool strict = false) { |
130 | // now switch on the result type |
131 | switch (target_type.id) { |
132 | case SQLTypeId::DATE: |
133 | assert(result.type == TypeId::INT32); |
134 | if (strict) { |
135 | UnaryExecutor::Execute<string_t, date_t, duckdb::StrictCastToDate, true>(source, result, count); |
136 | } else { |
137 | UnaryExecutor::Execute<string_t, date_t, duckdb::CastToDate, true>(source, result, count); |
138 | } |
139 | break; |
140 | case SQLTypeId::TIME: |
141 | assert(result.type == TypeId::INT32); |
142 | if (strict) { |
143 | UnaryExecutor::Execute<string_t, dtime_t, duckdb::StrictCastToTime, true>(source, result, count); |
144 | } else { |
145 | UnaryExecutor::Execute<string_t, dtime_t, duckdb::CastToTime, true>(source, result, count); |
146 | } |
147 | break; |
148 | case SQLTypeId::TIMESTAMP: |
149 | assert(result.type == TypeId::INT64); |
150 | UnaryExecutor::Execute<string_t, timestamp_t, duckdb::CastToTimestamp, true>(source, result, count); |
151 | break; |
152 | case SQLTypeId::BLOB: |
153 | assert(result.type == TypeId::VARCHAR); |
154 | string_cast<string_t, duckdb::CastToBlob>(source, result, count); |
155 | break; |
156 | default: |
157 | if (strict) { |
158 | string_cast_numric_switch<duckdb::StrictCast>(source, result, source_type, target_type, count); |
159 | } else { |
160 | string_cast_numric_switch<duckdb::Cast>(source, result, source_type, target_type, count); |
161 | } |
162 | break; |
163 | } |
164 | } |
165 | |
166 | static void date_cast_switch(Vector &source, Vector &result, SQLType source_type, SQLType target_type, idx_t count) { |
167 | // now switch on the result type |
168 | switch (target_type.id) { |
169 | case SQLTypeId::VARCHAR: |
170 | // date to varchar |
171 | string_cast<date_t, duckdb::CastFromDate>(source, result, count); |
172 | break; |
173 | case SQLTypeId::TIMESTAMP: |
174 | // date to timestamp |
175 | UnaryExecutor::Execute<date_t, timestamp_t, duckdb::CastDateToTimestamp, true>(source, result, count); |
176 | break; |
177 | default: |
178 | null_cast(source, result, source_type, target_type, count); |
179 | break; |
180 | } |
181 | } |
182 | |
183 | static void time_cast_switch(Vector &source, Vector &result, SQLType source_type, SQLType target_type, idx_t count) { |
184 | // now switch on the result type |
185 | switch (target_type.id) { |
186 | case SQLTypeId::VARCHAR: |
187 | // time to varchar |
188 | string_cast<dtime_t, duckdb::CastFromTime>(source, result, count); |
189 | break; |
190 | default: |
191 | null_cast(source, result, source_type, target_type, count); |
192 | break; |
193 | } |
194 | } |
195 | |
196 | static void timestamp_cast_switch(Vector &source, Vector &result, SQLType source_type, SQLType target_type, |
197 | idx_t count) { |
198 | // now switch on the result type |
199 | switch (target_type.id) { |
200 | case SQLTypeId::VARCHAR: |
201 | // timestamp to varchar |
202 | string_cast<timestamp_t, duckdb::CastFromTimestamp>(source, result, count); |
203 | break; |
204 | case SQLTypeId::DATE: |
205 | // timestamp to date |
206 | UnaryExecutor::Execute<timestamp_t, date_t, duckdb::CastTimestampToDate, true>(source, result, count); |
207 | break; |
208 | case SQLTypeId::TIME: |
209 | // timestamp to time |
210 | UnaryExecutor::Execute<timestamp_t, dtime_t, duckdb::CastTimestampToTime, true>(source, result, count); |
211 | break; |
212 | default: |
213 | null_cast(source, result, source_type, target_type, count); |
214 | break; |
215 | } |
216 | } |
217 | |
218 | static void blob_cast_switch(Vector &source, Vector &result, SQLType source_type, SQLType target_type, |
219 | idx_t count) { |
220 | // now switch on the result type |
221 | switch (target_type.id) { |
222 | case SQLTypeId::VARCHAR: |
223 | // blob to varchar |
224 | string_cast<string_t, duckdb::CastFromBlob>(source, result, count); |
225 | break; |
226 | default: |
227 | null_cast(source, result, source_type, target_type, count); |
228 | break; |
229 | } |
230 | } |
231 | |
232 | void VectorOperations::Cast(Vector &source, Vector &result, SQLType source_type, SQLType target_type, idx_t count, |
233 | bool strict) { |
234 | assert(source_type != target_type); |
235 | // first switch on source type |
236 | switch (source_type.id) { |
237 | case SQLTypeId::BOOLEAN: |
238 | assert(source.type == TypeId::BOOL); |
239 | numeric_cast_switch<bool>(source, result, source_type, target_type, count); |
240 | break; |
241 | case SQLTypeId::TINYINT: |
242 | assert(source.type == TypeId::INT8); |
243 | numeric_cast_switch<int8_t>(source, result, source_type, target_type, count); |
244 | break; |
245 | case SQLTypeId::SMALLINT: |
246 | assert(source.type == TypeId::INT16); |
247 | numeric_cast_switch<int16_t>(source, result, source_type, target_type, count); |
248 | break; |
249 | case SQLTypeId::INTEGER: |
250 | assert(source.type == TypeId::INT32); |
251 | numeric_cast_switch<int32_t>(source, result, source_type, target_type, count); |
252 | break; |
253 | case SQLTypeId::BIGINT: |
254 | assert(source.type == TypeId::INT64); |
255 | numeric_cast_switch<int64_t>(source, result, source_type, target_type, count); |
256 | break; |
257 | case SQLTypeId::FLOAT: |
258 | assert(source.type == TypeId::FLOAT); |
259 | numeric_cast_switch<float>(source, result, source_type, target_type, count); |
260 | break; |
261 | case SQLTypeId::DECIMAL: |
262 | case SQLTypeId::DOUBLE: |
263 | assert(source.type == TypeId::DOUBLE); |
264 | numeric_cast_switch<double>(source, result, source_type, target_type, count); |
265 | break; |
266 | case SQLTypeId::DATE: |
267 | assert(source.type == TypeId::INT32); |
268 | date_cast_switch(source, result, source_type, target_type, count); |
269 | break; |
270 | case SQLTypeId::TIME: |
271 | assert(source.type == TypeId::INT32); |
272 | time_cast_switch(source, result, source_type, target_type, count); |
273 | break; |
274 | case SQLTypeId::TIMESTAMP: |
275 | assert(source.type == TypeId::INT64); |
276 | timestamp_cast_switch(source, result, source_type, target_type, count); |
277 | break; |
278 | case SQLTypeId::VARCHAR: |
279 | assert(source.type == TypeId::VARCHAR); |
280 | string_cast_switch(source, result, source_type, target_type, count, strict); |
281 | break; |
282 | case SQLTypeId::BLOB: |
283 | assert(source.type == TypeId::VARCHAR); |
284 | blob_cast_switch(source, result, source_type, target_type, count); |
285 | break; |
286 | case SQLTypeId::SQLNULL: { |
287 | // cast a NULL to another type, just copy the properties and change the type |
288 | result.vector_type = VectorType::CONSTANT_VECTOR; |
289 | ConstantVector::SetNull(result, true); |
290 | break; |
291 | } |
292 | default: |
293 | throw UnimplementedCast(source_type, target_type); |
294 | } |
295 | } |
296 | |
297 | void VectorOperations::Cast(Vector &source, Vector &result, idx_t count, bool strict) { |
298 | return VectorOperations::Cast(source, result, SQLTypeFromInternalType(source.type), |
299 | SQLTypeFromInternalType(result.type), count, strict); |
300 | } |
301 | |