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
11namespace duckdb {
12
13struct PragmaLastProfilingOutputOperatorData : public GlobalTableFunctionState {
14 PragmaLastProfilingOutputOperatorData() : initialized(false) {
15 }
16
17 ColumnDataScanState scan_state;
18 bool initialized;
19};
20
21struct PragmaLastProfilingOutputData : public TableFunctionData {
22 explicit PragmaLastProfilingOutputData(vector<LogicalType> &types) : types(types) {
23 }
24 unique_ptr<ColumnDataCollection> collection;
25 vector<LogicalType> types;
26};
27
28static 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
49static 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
58unique_ptr<GlobalTableFunctionState> PragmaLastProfilingOutputInit(ClientContext &context,
59 TableFunctionInitInput &input) {
60 return make_uniq<PragmaLastProfilingOutputOperatorData>();
61}
62
63static 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
96void PragmaLastProfilingOutput::RegisterFunction(BuiltinFunctions &set) {
97 set.AddFunction(function: TableFunction("pragma_last_profiling_output", {}, PragmaLastProfilingOutputFunction,
98 PragmaLastProfilingOutputBind, PragmaLastProfilingOutputInit));
99}
100
101} // namespace duckdb
102