1 | #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" |
2 | #include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp" |
3 | #include "duckdb/common/limits.hpp" |
4 | #include "duckdb/common/types/column/column_data_collection.hpp" |
5 | #include "duckdb/function/table/system_functions.hpp" |
6 | #include "duckdb/main/client_context.hpp" |
7 | #include "duckdb/main/client_data.hpp" |
8 | #include "duckdb/main/query_profiler.hpp" |
9 | #include "duckdb/planner/constraints/bound_not_null_constraint.hpp" |
10 | |
11 | namespace duckdb { |
12 | |
13 | struct PragmaLastProfilingOutputOperatorData : public GlobalTableFunctionState { |
14 | PragmaLastProfilingOutputOperatorData() : initialized(false) { |
15 | } |
16 | |
17 | ColumnDataScanState scan_state; |
18 | bool initialized; |
19 | }; |
20 | |
21 | struct PragmaLastProfilingOutputData : public TableFunctionData { |
22 | explicit PragmaLastProfilingOutputData(vector<LogicalType> &types) : types(types) { |
23 | } |
24 | unique_ptr<ColumnDataCollection> collection; |
25 | vector<LogicalType> types; |
26 | }; |
27 | |
28 | static unique_ptr<FunctionData> PragmaLastProfilingOutputBind(ClientContext &context, TableFunctionBindInput &input, |
29 | vector<LogicalType> &return_types, |
30 | vector<string> &names) { |
31 | names.emplace_back(args: "OPERATOR_ID" ); |
32 | return_types.emplace_back(args: LogicalType::INTEGER); |
33 | |
34 | names.emplace_back(args: "NAME" ); |
35 | return_types.emplace_back(args: LogicalType::VARCHAR); |
36 | |
37 | names.emplace_back(args: "TIME" ); |
38 | return_types.emplace_back(args: LogicalType::DOUBLE); |
39 | |
40 | names.emplace_back(args: "CARDINALITY" ); |
41 | return_types.emplace_back(args: LogicalType::BIGINT); |
42 | |
43 | names.emplace_back(args: "DESCRIPTION" ); |
44 | return_types.emplace_back(args: LogicalType::VARCHAR); |
45 | |
46 | return make_uniq<PragmaLastProfilingOutputData>(args&: return_types); |
47 | } |
48 | |
49 | static void SetValue(DataChunk &output, int index, int op_id, string name, double time, int64_t car, |
50 | string description) { |
51 | output.SetValue(col_idx: 0, index, val: op_id); |
52 | output.SetValue(col_idx: 1, index, val: std::move(name)); |
53 | output.SetValue(col_idx: 2, index, val: time); |
54 | output.SetValue(col_idx: 3, index, val: car); |
55 | output.SetValue(col_idx: 4, index, val: std::move(description)); |
56 | } |
57 | |
58 | unique_ptr<GlobalTableFunctionState> PragmaLastProfilingOutputInit(ClientContext &context, |
59 | TableFunctionInitInput &input) { |
60 | return make_uniq<PragmaLastProfilingOutputOperatorData>(); |
61 | } |
62 | |
63 | static void PragmaLastProfilingOutputFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { |
64 | auto &state = data_p.global_state->Cast<PragmaLastProfilingOutputOperatorData>(); |
65 | auto &data = data_p.bind_data->CastNoConst<PragmaLastProfilingOutputData>(); |
66 | if (!state.initialized) { |
67 | // create a ColumnDataCollection |
68 | auto collection = make_uniq<ColumnDataCollection>(args&: context, args&: data.types); |
69 | |
70 | DataChunk chunk; |
71 | chunk.Initialize(context, types: data.types); |
72 | int operator_counter = 1; |
73 | auto &client_data = ClientData::Get(context); |
74 | if (!client_data.query_profiler_history->GetPrevProfilers().empty()) { |
75 | auto &tree_map = client_data.query_profiler_history->GetPrevProfilers().back().second->GetTreeMap(); |
76 | for (auto op : tree_map) { |
77 | auto &tree_info = op.second.get(); |
78 | SetValue(output&: chunk, index: chunk.size(), op_id: operator_counter++, name: tree_info.name, time: tree_info.info.time, |
79 | car: tree_info.info.elements, description: " " ); |
80 | chunk.SetCardinality(chunk.size() + 1); |
81 | if (chunk.size() == STANDARD_VECTOR_SIZE) { |
82 | collection->Append(new_chunk&: chunk); |
83 | chunk.Reset(); |
84 | } |
85 | } |
86 | } |
87 | collection->Append(new_chunk&: chunk); |
88 | data.collection = std::move(collection); |
89 | data.collection->InitializeScan(state&: state.scan_state); |
90 | state.initialized = true; |
91 | } |
92 | |
93 | data.collection->Scan(state&: state.scan_state, result&: output); |
94 | } |
95 | |
96 | void PragmaLastProfilingOutput::RegisterFunction(BuiltinFunctions &set) { |
97 | set.AddFunction(function: TableFunction("pragma_last_profiling_output" , {}, PragmaLastProfilingOutputFunction, |
98 | PragmaLastProfilingOutputBind, PragmaLastProfilingOutputInit)); |
99 | } |
100 | |
101 | } // namespace duckdb |
102 | |