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