1#include "duckdb/storage/table/table_statistics.hpp"
2#include "duckdb/storage/table/persistent_table_data.hpp"
3
4namespace duckdb {
5
6void TableStatistics::Initialize(const vector<LogicalType> &types, PersistentTableData &data) {
7 D_ASSERT(Empty());
8
9 column_stats = std::move(data.table_stats.column_stats);
10 if (column_stats.size() != types.size()) { // LCOV_EXCL_START
11 throw IOException("Table statistics column count is not aligned with table column count. Corrupt file?");
12 } // LCOV_EXCL_STOP
13}
14
15void TableStatistics::InitializeEmpty(const vector<LogicalType> &types) {
16 D_ASSERT(Empty());
17
18 for (auto &type : types) {
19 column_stats.push_back(x: ColumnStatistics::CreateEmptyStats(type));
20 }
21}
22
23void TableStatistics::InitializeAddColumn(TableStatistics &parent, const LogicalType &new_column_type) {
24 D_ASSERT(Empty());
25
26 lock_guard<mutex> stats_lock(parent.stats_lock);
27 for (idx_t i = 0; i < parent.column_stats.size(); i++) {
28 column_stats.push_back(x: parent.column_stats[i]);
29 }
30 column_stats.push_back(x: ColumnStatistics::CreateEmptyStats(type: new_column_type));
31}
32
33void TableStatistics::InitializeRemoveColumn(TableStatistics &parent, idx_t removed_column) {
34 D_ASSERT(Empty());
35
36 lock_guard<mutex> stats_lock(parent.stats_lock);
37 for (idx_t i = 0; i < parent.column_stats.size(); i++) {
38 if (i != removed_column) {
39 column_stats.push_back(x: parent.column_stats[i]);
40 }
41 }
42}
43
44void TableStatistics::InitializeAlterType(TableStatistics &parent, idx_t changed_idx, const LogicalType &new_type) {
45 D_ASSERT(Empty());
46
47 lock_guard<mutex> stats_lock(parent.stats_lock);
48 for (idx_t i = 0; i < parent.column_stats.size(); i++) {
49 if (i == changed_idx) {
50 column_stats.push_back(x: ColumnStatistics::CreateEmptyStats(type: new_type));
51 } else {
52 column_stats.push_back(x: parent.column_stats[i]);
53 }
54 }
55}
56
57void TableStatistics::InitializeAddConstraint(TableStatistics &parent) {
58 D_ASSERT(Empty());
59
60 lock_guard<mutex> stats_lock(parent.stats_lock);
61 for (idx_t i = 0; i < parent.column_stats.size(); i++) {
62 column_stats.push_back(x: parent.column_stats[i]);
63 }
64}
65
66void TableStatistics::MergeStats(TableStatistics &other) {
67 auto l = GetLock();
68 D_ASSERT(column_stats.size() == other.column_stats.size());
69 for (idx_t i = 0; i < column_stats.size(); i++) {
70 column_stats[i]->Merge(other&: *other.column_stats[i]);
71 }
72}
73
74void TableStatistics::MergeStats(idx_t i, BaseStatistics &stats) {
75 auto l = GetLock();
76 MergeStats(lock&: *l, i, stats);
77}
78
79void TableStatistics::MergeStats(TableStatisticsLock &lock, idx_t i, BaseStatistics &stats) {
80 column_stats[i]->Statistics().Merge(other: stats);
81}
82
83ColumnStatistics &TableStatistics::GetStats(idx_t i) {
84 return *column_stats[i];
85}
86
87unique_ptr<BaseStatistics> TableStatistics::CopyStats(idx_t i) {
88 lock_guard<mutex> l(stats_lock);
89 auto result = column_stats[i]->Statistics().Copy();
90 if (column_stats[i]->HasDistinctStats()) {
91 result.SetDistinctCount(column_stats[i]->DistinctStats().GetCount());
92 }
93 return result.ToUnique();
94}
95
96void TableStatistics::CopyStats(TableStatistics &other) {
97 for (auto &stats : column_stats) {
98 other.column_stats.push_back(x: stats->Copy());
99 }
100}
101
102void TableStatistics::Serialize(Serializer &serializer) {
103 for (auto &stats : column_stats) {
104 stats->Serialize(serializer);
105 }
106}
107
108void TableStatistics::Deserialize(Deserializer &source, ColumnList &columns) {
109 for (auto &col : columns.Physical()) {
110 auto stats = ColumnStatistics::Deserialize(source, type: col.GetType());
111 column_stats.push_back(x: std::move(stats));
112 }
113}
114
115unique_ptr<TableStatisticsLock> TableStatistics::GetLock() {
116 return make_uniq<TableStatisticsLock>(args&: stats_lock);
117}
118
119bool TableStatistics::Empty() {
120 return column_stats.empty();
121}
122
123} // namespace duckdb
124