| 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 | |