1 | #include "duckdb/function/cast/default_casts.hpp" |
2 | #include "duckdb/function/cast/cast_function_set.hpp" |
3 | #include "duckdb/function/cast/bound_cast_data.hpp" |
4 | |
5 | namespace duckdb { |
6 | |
7 | unique_ptr<BoundCastData> MapBoundCastData::BindMapToMapCast(BindCastInput &input, const LogicalType &source, |
8 | const LogicalType &target) { |
9 | vector<BoundCastInfo> child_cast_info; |
10 | auto source_key = MapType::KeyType(type: source); |
11 | auto target_key = MapType::KeyType(type: target); |
12 | auto source_val = MapType::ValueType(type: source); |
13 | auto target_val = MapType::ValueType(type: target); |
14 | auto key_cast = input.GetCastFunction(source: source_key, target: target_key); |
15 | auto value_cast = input.GetCastFunction(source: source_val, target: target_val); |
16 | return make_uniq<MapBoundCastData>(args: std::move(key_cast), args: std::move(value_cast)); |
17 | } |
18 | |
19 | static bool MapToVarcharCast(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { |
20 | auto constant = source.GetVectorType() == VectorType::CONSTANT_VECTOR; |
21 | auto varchar_type = LogicalType::MAP(key: LogicalType::VARCHAR, value: LogicalType::VARCHAR); |
22 | Vector varchar_map(varchar_type, count); |
23 | |
24 | // since map's physical type is a list, the ListCast can be utilized |
25 | ListCast::ListToListCast(source, result&: varchar_map, count, parameters); |
26 | |
27 | varchar_map.Flatten(count); |
28 | auto &validity = FlatVector::Validity(vector&: varchar_map); |
29 | auto &key_str = MapVector::GetKeys(vector&: varchar_map); |
30 | auto &val_str = MapVector::GetValues(vector&: varchar_map); |
31 | |
32 | key_str.Flatten(count: ListVector::GetListSize(vector: source)); |
33 | val_str.Flatten(count: ListVector::GetListSize(vector: source)); |
34 | |
35 | auto list_data = ListVector::GetData(v&: varchar_map); |
36 | auto key_data = FlatVector::GetData<string_t>(vector&: key_str); |
37 | auto val_data = FlatVector::GetData<string_t>(vector&: val_str); |
38 | auto &key_validity = FlatVector::Validity(vector&: key_str); |
39 | auto &val_validity = FlatVector::Validity(vector&: val_str); |
40 | auto &struct_validity = FlatVector::Validity(vector&: ListVector::GetEntry(vector&: varchar_map)); |
41 | |
42 | auto result_data = FlatVector::GetData<string_t>(vector&: result); |
43 | for (idx_t i = 0; i < count; i++) { |
44 | if (!validity.RowIsValid(row_idx: i)) { |
45 | FlatVector::SetNull(vector&: result, idx: i, is_null: true); |
46 | continue; |
47 | } |
48 | auto list = list_data[i]; |
49 | string ret = "{" ; |
50 | for (idx_t list_idx = 0; list_idx < list.length; list_idx++) { |
51 | if (list_idx > 0) { |
52 | ret += ", " ; |
53 | } |
54 | auto idx = list.offset + list_idx; |
55 | |
56 | if (!struct_validity.RowIsValid(row_idx: idx)) { |
57 | ret += "NULL" ; |
58 | continue; |
59 | } |
60 | if (!key_validity.RowIsValid(row_idx: idx)) { |
61 | // throw InternalException("Error in map: key validity invalid?!"); |
62 | ret += "invalid" ; |
63 | continue; |
64 | } |
65 | ret += key_data[idx].GetString(); |
66 | ret += "=" ; |
67 | ret += val_validity.RowIsValid(row_idx: idx) ? val_data[idx].GetString() : "NULL" ; |
68 | } |
69 | ret += "}" ; |
70 | result_data[i] = StringVector::AddString(vector&: result, data: ret); |
71 | } |
72 | |
73 | if (constant) { |
74 | result.SetVectorType(VectorType::CONSTANT_VECTOR); |
75 | } |
76 | return true; |
77 | } |
78 | |
79 | BoundCastInfo DefaultCasts::MapCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target) { |
80 | switch (target.id()) { |
81 | case LogicalTypeId::MAP: |
82 | return BoundCastInfo(ListCast::ListToListCast, ListBoundCastData::BindListToListCast(input, source, target), |
83 | ListBoundCastData::InitListLocalState); |
84 | case LogicalTypeId::VARCHAR: { |
85 | auto varchar_type = LogicalType::MAP(key: LogicalType::VARCHAR, value: LogicalType::VARCHAR); |
86 | return BoundCastInfo(MapToVarcharCast, ListBoundCastData::BindListToListCast(input, source, target: varchar_type), |
87 | ListBoundCastData::InitListLocalState); |
88 | } |
89 | default: |
90 | return TryVectorNullCast; |
91 | } |
92 | } |
93 | |
94 | } // namespace duckdb |
95 | |