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
6namespace duckdb {
7
8void 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
16BaseStatistics 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
26BaseStatistics 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
36const 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
43const 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
51BaseStatistics &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
59void 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
65void 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
75void 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
82void 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
93void 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
101BaseStatistics 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
112string 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
126void 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