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
5namespace duckdb {
6
7unique_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
19static bool MapToVarcharCast(Vector &source, Vector &result, idx_t count, CastParameters &parameters) {
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
79BoundCastInfo 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