1 | #include "duckdb/function/table/system_functions.hpp" |
2 | |
3 | #include "duckdb/catalog/catalog.hpp" |
4 | #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" |
5 | #include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp" |
6 | #include "duckdb/parser/qualified_name.hpp" |
7 | #include "duckdb/planner/constraints/bound_not_null_constraint.hpp" |
8 | #include "duckdb/planner/constraints/bound_unique_constraint.hpp" |
9 | |
10 | #include "duckdb/common/exception.hpp" |
11 | #include "duckdb/common/limits.hpp" |
12 | #include "duckdb/storage/data_table.hpp" |
13 | #include "duckdb/storage/table_storage_info.hpp" |
14 | #include "duckdb/planner/binder.hpp" |
15 | |
16 | #include <algorithm> |
17 | |
18 | namespace duckdb { |
19 | |
20 | struct PragmaStorageFunctionData : public TableFunctionData { |
21 | explicit PragmaStorageFunctionData(TableCatalogEntry &table_entry) : table_entry(table_entry) { |
22 | } |
23 | |
24 | TableCatalogEntry &table_entry; |
25 | vector<ColumnSegmentInfo> column_segments_info; |
26 | }; |
27 | |
28 | struct PragmaStorageOperatorData : public GlobalTableFunctionState { |
29 | PragmaStorageOperatorData() : offset(0) { |
30 | } |
31 | |
32 | idx_t offset; |
33 | }; |
34 | |
35 | static unique_ptr<FunctionData> PragmaStorageInfoBind(ClientContext &context, TableFunctionBindInput &input, |
36 | vector<LogicalType> &return_types, vector<string> &names) { |
37 | names.emplace_back(args: "row_group_id" ); |
38 | return_types.emplace_back(args: LogicalType::BIGINT); |
39 | |
40 | names.emplace_back(args: "column_name" ); |
41 | return_types.emplace_back(args: LogicalType::VARCHAR); |
42 | |
43 | names.emplace_back(args: "column_id" ); |
44 | return_types.emplace_back(args: LogicalType::BIGINT); |
45 | |
46 | names.emplace_back(args: "column_path" ); |
47 | return_types.emplace_back(args: LogicalType::VARCHAR); |
48 | |
49 | names.emplace_back(args: "segment_id" ); |
50 | return_types.emplace_back(args: LogicalType::BIGINT); |
51 | |
52 | names.emplace_back(args: "segment_type" ); |
53 | return_types.emplace_back(args: LogicalType::VARCHAR); |
54 | |
55 | names.emplace_back(args: "start" ); |
56 | return_types.emplace_back(args: LogicalType::BIGINT); |
57 | |
58 | names.emplace_back(args: "count" ); |
59 | return_types.emplace_back(args: LogicalType::BIGINT); |
60 | |
61 | names.emplace_back(args: "compression" ); |
62 | return_types.emplace_back(args: LogicalType::VARCHAR); |
63 | |
64 | names.emplace_back(args: "stats" ); |
65 | return_types.emplace_back(args: LogicalType::VARCHAR); |
66 | |
67 | names.emplace_back(args: "has_updates" ); |
68 | return_types.emplace_back(args: LogicalType::BOOLEAN); |
69 | |
70 | names.emplace_back(args: "persistent" ); |
71 | return_types.emplace_back(args: LogicalType::BOOLEAN); |
72 | |
73 | names.emplace_back(args: "block_id" ); |
74 | return_types.emplace_back(args: LogicalType::BIGINT); |
75 | |
76 | names.emplace_back(args: "block_offset" ); |
77 | return_types.emplace_back(args: LogicalType::BIGINT); |
78 | |
79 | auto qname = QualifiedName::Parse(input: input.inputs[0].GetValue<string>()); |
80 | |
81 | // look up the table name in the catalog |
82 | Binder::BindSchemaOrCatalog(context, catalog&: qname.catalog, schema&: qname.schema); |
83 | auto &table_entry = Catalog::GetEntry<TableCatalogEntry>(context, catalog_name: qname.catalog, schema_name: qname.schema, name: qname.name); |
84 | auto result = make_uniq<PragmaStorageFunctionData>(args&: table_entry); |
85 | result->column_segments_info = table_entry.GetColumnSegmentInfo(); |
86 | return std::move(result); |
87 | } |
88 | |
89 | unique_ptr<GlobalTableFunctionState> PragmaStorageInfoInit(ClientContext &context, TableFunctionInitInput &input) { |
90 | return make_uniq<PragmaStorageOperatorData>(); |
91 | } |
92 | |
93 | static void PragmaStorageInfoFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { |
94 | auto &bind_data = data_p.bind_data->Cast<PragmaStorageFunctionData>(); |
95 | auto &data = data_p.global_state->Cast<PragmaStorageOperatorData>(); |
96 | idx_t count = 0; |
97 | auto &columns = bind_data.table_entry.GetColumns(); |
98 | while (data.offset < bind_data.column_segments_info.size() && count < STANDARD_VECTOR_SIZE) { |
99 | auto &entry = bind_data.column_segments_info[data.offset++]; |
100 | |
101 | idx_t col_idx = 0; |
102 | // row_group_id |
103 | output.SetValue(col_idx: col_idx++, index: count, val: Value::BIGINT(value: entry.row_group_index)); |
104 | // column_name |
105 | auto &col = columns.GetColumn(index: PhysicalIndex(entry.column_id)); |
106 | output.SetValue(col_idx: col_idx++, index: count, val: Value(col.Name())); |
107 | // column_id |
108 | output.SetValue(col_idx: col_idx++, index: count, val: Value::BIGINT(value: entry.column_id)); |
109 | // column_path |
110 | output.SetValue(col_idx: col_idx++, index: count, val: Value(entry.column_path)); |
111 | // segment_id |
112 | output.SetValue(col_idx: col_idx++, index: count, val: Value::BIGINT(value: entry.segment_idx)); |
113 | // segment_type |
114 | output.SetValue(col_idx: col_idx++, index: count, val: Value(entry.segment_type)); |
115 | // start |
116 | output.SetValue(col_idx: col_idx++, index: count, val: Value::BIGINT(value: entry.segment_start)); |
117 | // count |
118 | output.SetValue(col_idx: col_idx++, index: count, val: Value::BIGINT(value: entry.segment_count)); |
119 | // compression |
120 | output.SetValue(col_idx: col_idx++, index: count, val: Value(entry.compression_type)); |
121 | // stats |
122 | output.SetValue(col_idx: col_idx++, index: count, val: Value(entry.segment_stats)); |
123 | // has_updates |
124 | output.SetValue(col_idx: col_idx++, index: count, val: Value::BOOLEAN(value: entry.has_updates)); |
125 | // persistent |
126 | output.SetValue(col_idx: col_idx++, index: count, val: Value::BOOLEAN(value: entry.persistent)); |
127 | // block_id |
128 | // block_offset |
129 | if (entry.persistent) { |
130 | output.SetValue(col_idx: col_idx++, index: count, val: Value::BIGINT(value: entry.block_id)); |
131 | output.SetValue(col_idx: col_idx++, index: count, val: Value::BIGINT(value: entry.block_offset)); |
132 | } else { |
133 | output.SetValue(col_idx: col_idx++, index: count, val: Value()); |
134 | output.SetValue(col_idx: col_idx++, index: count, val: Value()); |
135 | } |
136 | count++; |
137 | } |
138 | output.SetCardinality(count); |
139 | } |
140 | |
141 | void PragmaStorageInfo::RegisterFunction(BuiltinFunctions &set) { |
142 | set.AddFunction(function: TableFunction("pragma_storage_info" , {LogicalType::VARCHAR}, PragmaStorageInfoFunction, |
143 | PragmaStorageInfoBind, PragmaStorageInfoInit)); |
144 | } |
145 | |
146 | } // namespace duckdb |
147 | |