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/common/exception.hpp"
6#include "duckdb/main/client_context.hpp"
7#include "duckdb/main/client_data.hpp"
8
9namespace duckdb {
10
11struct DuckDBSchemasData : public GlobalTableFunctionState {
12 DuckDBSchemasData() : offset(0) {
13 }
14
15 vector<reference<SchemaCatalogEntry>> entries;
16 idx_t offset;
17};
18
19static unique_ptr<FunctionData> DuckDBSchemasBind(ClientContext &context, TableFunctionBindInput &input,
20 vector<LogicalType> &return_types, vector<string> &names) {
21 names.emplace_back(args: "oid");
22 return_types.emplace_back(args: LogicalType::BIGINT);
23
24 names.emplace_back(args: "database_name");
25 return_types.emplace_back(args: LogicalType::VARCHAR);
26
27 names.emplace_back(args: "database_oid");
28 return_types.emplace_back(args: LogicalType::BIGINT);
29
30 names.emplace_back(args: "schema_name");
31 return_types.emplace_back(args: LogicalType::VARCHAR);
32
33 names.emplace_back(args: "internal");
34 return_types.emplace_back(args: LogicalType::BOOLEAN);
35
36 names.emplace_back(args: "sql");
37 return_types.emplace_back(args: LogicalType::VARCHAR);
38
39 return nullptr;
40}
41
42unique_ptr<GlobalTableFunctionState> DuckDBSchemasInit(ClientContext &context, TableFunctionInitInput &input) {
43 auto result = make_uniq<DuckDBSchemasData>();
44
45 // scan all the schemas and collect them
46 result->entries = Catalog::GetAllSchemas(context);
47
48 return std::move(result);
49}
50
51void DuckDBSchemasFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) {
52 auto &data = data_p.global_state->Cast<DuckDBSchemasData>();
53 if (data.offset >= data.entries.size()) {
54 // finished returning values
55 return;
56 }
57 // start returning values
58 // either fill up the chunk or return all the remaining columns
59 idx_t count = 0;
60 while (data.offset < data.entries.size() && count < STANDARD_VECTOR_SIZE) {
61 auto &entry = data.entries[data.offset].get();
62
63 // return values:
64 idx_t col = 0;
65 // "oid", PhysicalType::BIGINT
66 output.SetValue(col_idx: col++, index: count, val: Value::BIGINT(value: entry.oid));
67 // database_name, VARCHAR
68 output.SetValue(col_idx: col++, index: count, val: entry.catalog.GetName());
69 // database_oid, BIGINT
70 output.SetValue(col_idx: col++, index: count, val: Value::BIGINT(value: entry.catalog.GetOid()));
71 // "schema_name", PhysicalType::VARCHAR
72 output.SetValue(col_idx: col++, index: count, val: Value(entry.name));
73 // "internal", PhysicalType::BOOLEAN
74 output.SetValue(col_idx: col++, index: count, val: Value::BOOLEAN(value: entry.internal));
75 // "sql", PhysicalType::VARCHAR
76 output.SetValue(col_idx: col++, index: count, val: Value());
77
78 data.offset++;
79 count++;
80 }
81 output.SetCardinality(count);
82}
83
84void DuckDBSchemasFun::RegisterFunction(BuiltinFunctions &set) {
85 set.AddFunction(function: TableFunction("duckdb_schemas", {}, DuckDBSchemasFunction, DuckDBSchemasBind, DuckDBSchemasInit));
86}
87
88} // namespace duckdb
89