1 | #include "duckdb/storage/statistics/struct_stats.hpp" |
2 | #include "duckdb/storage/statistics/base_statistics.hpp" |
3 | #include "duckdb/common/field_writer.hpp" |
4 | #include "duckdb/common/types/vector.hpp" |
5 | |
6 | namespace duckdb { |
7 | |
8 | void StructStats::Construct(BaseStatistics &stats) { |
9 | auto &child_types = StructType::GetChildTypes(type: stats.GetType()); |
10 | stats.child_stats = unsafe_unique_array<BaseStatistics>(new BaseStatistics[child_types.size()]); |
11 | for (idx_t i = 0; i < child_types.size(); i++) { |
12 | BaseStatistics::Construct(stats&: stats.child_stats[i], type: child_types[i].second); |
13 | } |
14 | } |
15 | |
16 | BaseStatistics StructStats::CreateUnknown(LogicalType type) { |
17 | auto &child_types = StructType::GetChildTypes(type); |
18 | BaseStatistics result(std::move(type)); |
19 | result.InitializeUnknown(); |
20 | for (idx_t i = 0; i < child_types.size(); i++) { |
21 | result.child_stats[i].Copy(other: BaseStatistics::CreateUnknown(type: child_types[i].second)); |
22 | } |
23 | return result; |
24 | } |
25 | |
26 | BaseStatistics StructStats::CreateEmpty(LogicalType type) { |
27 | auto &child_types = StructType::GetChildTypes(type); |
28 | BaseStatistics result(std::move(type)); |
29 | result.InitializeEmpty(); |
30 | for (idx_t i = 0; i < child_types.size(); i++) { |
31 | result.child_stats[i].Copy(other: BaseStatistics::CreateEmpty(type: child_types[i].second)); |
32 | } |
33 | return result; |
34 | } |
35 | |
36 | const BaseStatistics *StructStats::GetChildStats(const BaseStatistics &stats) { |
37 | if (stats.GetStatsType() != StatisticsType::STRUCT_STATS) { |
38 | throw InternalException("Calling StructStats::GetChildStats on stats that is not a struct" ); |
39 | } |
40 | return stats.child_stats.get(); |
41 | } |
42 | |
43 | const BaseStatistics &StructStats::GetChildStats(const BaseStatistics &stats, idx_t i) { |
44 | D_ASSERT(stats.GetStatsType() == StatisticsType::STRUCT_STATS); |
45 | if (i >= StructType::GetChildCount(type: stats.GetType())) { |
46 | throw InternalException("Calling StructStats::GetChildStats but there are no stats for this index" ); |
47 | } |
48 | return stats.child_stats[i]; |
49 | } |
50 | |
51 | BaseStatistics &StructStats::GetChildStats(BaseStatistics &stats, idx_t i) { |
52 | D_ASSERT(stats.GetStatsType() == StatisticsType::STRUCT_STATS); |
53 | if (i >= StructType::GetChildCount(type: stats.GetType())) { |
54 | throw InternalException("Calling StructStats::GetChildStats but there are no stats for this index" ); |
55 | } |
56 | return stats.child_stats[i]; |
57 | } |
58 | |
59 | void StructStats::SetChildStats(BaseStatistics &stats, idx_t i, const BaseStatistics &new_stats) { |
60 | D_ASSERT(stats.GetStatsType() == StatisticsType::STRUCT_STATS); |
61 | D_ASSERT(i < StructType::GetChildCount(stats.GetType())); |
62 | stats.child_stats[i].Copy(other: new_stats); |
63 | } |
64 | |
65 | void StructStats::SetChildStats(BaseStatistics &stats, idx_t i, unique_ptr<BaseStatistics> new_stats) { |
66 | D_ASSERT(stats.GetStatsType() == StatisticsType::STRUCT_STATS); |
67 | if (!new_stats) { |
68 | StructStats::SetChildStats(stats, i, |
69 | new_stats: BaseStatistics::CreateUnknown(type: StructType::GetChildType(type: stats.GetType(), index: i))); |
70 | } else { |
71 | StructStats::SetChildStats(stats, i, new_stats: *new_stats); |
72 | } |
73 | } |
74 | |
75 | void StructStats::Copy(BaseStatistics &stats, const BaseStatistics &other) { |
76 | auto count = StructType::GetChildCount(type: stats.GetType()); |
77 | for (idx_t i = 0; i < count; i++) { |
78 | stats.child_stats[i].Copy(other: other.child_stats[i]); |
79 | } |
80 | } |
81 | |
82 | void StructStats::Merge(BaseStatistics &stats, const BaseStatistics &other) { |
83 | if (other.GetType().id() == LogicalTypeId::VALIDITY) { |
84 | return; |
85 | } |
86 | D_ASSERT(stats.GetType() == other.GetType()); |
87 | auto child_count = StructType::GetChildCount(type: stats.GetType()); |
88 | for (idx_t i = 0; i < child_count; i++) { |
89 | stats.child_stats[i].Merge(other: other.child_stats[i]); |
90 | } |
91 | } |
92 | |
93 | void StructStats::Serialize(const BaseStatistics &stats, FieldWriter &writer) { |
94 | auto child_stats = StructStats::GetChildStats(stats); |
95 | auto child_count = StructType::GetChildCount(type: stats.GetType()); |
96 | for (idx_t i = 0; i < child_count; i++) { |
97 | writer.WriteSerializable(element: child_stats[i]); |
98 | } |
99 | } |
100 | |
101 | BaseStatistics StructStats::Deserialize(FieldReader &reader, LogicalType type) { |
102 | D_ASSERT(type.InternalType() == PhysicalType::STRUCT); |
103 | auto &child_types = StructType::GetChildTypes(type); |
104 | BaseStatistics result(std::move(type)); |
105 | for (idx_t i = 0; i < child_types.size(); i++) { |
106 | result.child_stats[i].Copy( |
107 | other: reader.ReadRequiredSerializable<BaseStatistics, BaseStatistics>(args: child_types[i].second)); |
108 | } |
109 | return result; |
110 | } |
111 | |
112 | string StructStats::ToString(const BaseStatistics &stats) { |
113 | string result; |
114 | result += " {" ; |
115 | auto &child_types = StructType::GetChildTypes(type: stats.GetType()); |
116 | for (idx_t i = 0; i < child_types.size(); i++) { |
117 | if (i > 0) { |
118 | result += ", " ; |
119 | } |
120 | result += child_types[i].first + ": " + stats.child_stats[i].ToString(); |
121 | } |
122 | result += "}" ; |
123 | return result; |
124 | } |
125 | |
126 | void StructStats::Verify(const BaseStatistics &stats, Vector &vector, const SelectionVector &sel, idx_t count) { |
127 | auto &child_entries = StructVector::GetEntries(vector); |
128 | for (idx_t i = 0; i < child_entries.size(); i++) { |
129 | stats.child_stats[i].Verify(vector&: *child_entries[i], sel, count); |
130 | } |
131 | } |
132 | |
133 | } // namespace duckdb |
134 | |