1#include "duckdb/function/table/system_functions.hpp"
2
3#include "duckdb/catalog/catalog.hpp"
4#include "duckdb/catalog/catalog_entry/schema_catalog_entry.hpp"
5#include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp"
6#include "duckdb/common/exception.hpp"
7#include "duckdb/main/client_context.hpp"
8#include "duckdb/main/client_data.hpp"
9
10namespace duckdb {
11
12struct DuckDBViewsData : public GlobalTableFunctionState {
13 DuckDBViewsData() : offset(0) {
14 }
15
16 vector<reference<CatalogEntry>> entries;
17 idx_t offset;
18};
19
20static unique_ptr<FunctionData> DuckDBViewsBind(ClientContext &context, TableFunctionBindInput &input,
21 vector<LogicalType> &return_types, vector<string> &names) {
22 names.emplace_back(args: "database_name");
23 return_types.emplace_back(args: LogicalType::VARCHAR);
24
25 names.emplace_back(args: "database_oid");
26 return_types.emplace_back(args: LogicalType::BIGINT);
27
28 names.emplace_back(args: "schema_name");
29 return_types.emplace_back(args: LogicalType::VARCHAR);
30
31 names.emplace_back(args: "schema_oid");
32 return_types.emplace_back(args: LogicalType::BIGINT);
33
34 names.emplace_back(args: "view_name");
35 return_types.emplace_back(args: LogicalType::VARCHAR);
36
37 names.emplace_back(args: "view_oid");
38 return_types.emplace_back(args: LogicalType::BIGINT);
39
40 names.emplace_back(args: "internal");
41 return_types.emplace_back(args: LogicalType::BOOLEAN);
42
43 names.emplace_back(args: "temporary");
44 return_types.emplace_back(args: LogicalType::BOOLEAN);
45
46 names.emplace_back(args: "column_count");
47 return_types.emplace_back(args: LogicalType::BIGINT);
48
49 names.emplace_back(args: "sql");
50 return_types.emplace_back(args: LogicalType::VARCHAR);
51
52 return nullptr;
53}
54
55unique_ptr<GlobalTableFunctionState> DuckDBViewsInit(ClientContext &context, TableFunctionInitInput &input) {
56 auto result = make_uniq<DuckDBViewsData>();
57
58 // scan all the schemas for tables and collect them and collect them
59 auto schemas = Catalog::GetAllSchemas(context);
60 for (auto &schema : schemas) {
61 schema.get().Scan(context, type: CatalogType::VIEW_ENTRY,
62 callback: [&](CatalogEntry &entry) { result->entries.push_back(x: entry); });
63 };
64 return std::move(result);
65}
66
67void DuckDBViewsFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) {
68 auto &data = data_p.global_state->Cast<DuckDBViewsData>();
69 if (data.offset >= data.entries.size()) {
70 // finished returning values
71 return;
72 }
73 // start returning values
74 // either fill up the chunk or return all the remaining columns
75 idx_t count = 0;
76 while (data.offset < data.entries.size() && count < STANDARD_VECTOR_SIZE) {
77 auto &entry = data.entries[data.offset++].get();
78
79 if (entry.type != CatalogType::VIEW_ENTRY) {
80 continue;
81 }
82 auto &view = entry.Cast<ViewCatalogEntry>();
83
84 // return values:
85 idx_t col = 0;
86 // database_name, VARCHAR
87 output.SetValue(col_idx: col++, index: count, val: view.catalog.GetName());
88 // database_oid, BIGINT
89 output.SetValue(col_idx: col++, index: count, val: Value::BIGINT(value: view.catalog.GetOid()));
90 // schema_name, LogicalType::VARCHAR
91 output.SetValue(col_idx: col++, index: count, val: Value(view.schema.name));
92 // schema_oid, LogicalType::BIGINT
93 output.SetValue(col_idx: col++, index: count, val: Value::BIGINT(value: view.schema.oid));
94 // view_name, LogicalType::VARCHAR
95 output.SetValue(col_idx: col++, index: count, val: Value(view.name));
96 // view_oid, LogicalType::BIGINT
97 output.SetValue(col_idx: col++, index: count, val: Value::BIGINT(value: view.oid));
98 // internal, LogicalType::BOOLEAN
99 output.SetValue(col_idx: col++, index: count, val: Value::BOOLEAN(value: view.internal));
100 // temporary, LogicalType::BOOLEAN
101 output.SetValue(col_idx: col++, index: count, val: Value::BOOLEAN(value: view.temporary));
102 // column_count, LogicalType::BIGINT
103 output.SetValue(col_idx: col++, index: count, val: Value::BIGINT(value: view.types.size()));
104 // sql, LogicalType::VARCHAR
105 output.SetValue(col_idx: col++, index: count, val: Value(view.ToSQL()));
106
107 count++;
108 }
109 output.SetCardinality(count);
110}
111
112void DuckDBViewsFun::RegisterFunction(BuiltinFunctions &set) {
113 set.AddFunction(function: TableFunction("duckdb_views", {}, DuckDBViewsFunction, DuckDBViewsBind, DuckDBViewsInit));
114}
115
116} // namespace duckdb
117