use rudb_catalog::{Catalog, DEFAULT_CATALOG, DEFAULT_SCHEMA};
use rudb_common::{LogicalType, Result, Value};
use rudb_functions::{TYPE_NAMES, canonical, type_category, type_fields, type_size};
use rudb_plan::{Plan, Slice};
use crate::metadata::{Metadata, text};
pub(crate) fn typenames(
catalog: &Catalog,
plan: &Plan,
index: u32,
columns: Slice,
) -> Result<Metadata> {
let mut rows = Vec::with_capacity(TYPE_NAMES.len());
for entry in TYPE_NAMES {
for (position, signature) in entry.signatures.iter().enumerate() {
let parameters = signature.iter().map(|(name, _)| text(name)).collect();
let types = signature.iter().map(|(_, ty)| text(ty)).collect();
rows.push(vec![
text(DEFAULT_CATALOG),
Value::Null,
text(DEFAULT_SCHEMA),
Value::Null,
match entry.oid {
Some(oid) if position == 0 => Value::BigInt(oid),
_ => Value::Null,
},
text(entry.name),
type_size(entry.logical_type).map_or(Value::Null, Value::BigInt),
text(entry.logical_type),
type_category(entry.logical_type).map_or(Value::Null, text),
Value::Null,
Value::map(LogicalType::Varchar, LogicalType::Varchar, Vec::new()),
Value::Boolean(true),
Value::Null,
Value::Null,
Value::List { element: LogicalType::Varchar, values: parameters },
Value::List { element: LogicalType::Varchar, values: types },
entry.varargs.map_or(Value::Null, text),
]);
}
}
for database in catalog.databases() {
for schema in database.schemas() {
let mut made: Vec<_> = catalog
.types()
.filter(|held| {
held.name().catalog == database.name() && held.name().schema == schema.name()
})
.collect();
made.sort_by_key(|held| held.name().table.to_lowercase());
for held in made {
let logical_type = canonical(held.ty());
let (size, labels) = match held.ty().labels() {
Some(labels) => (
i64::try_from(held.ty().physical().size()).ok(),
Value::List {
element: LogicalType::Varchar,
values: labels.iter().map(|label| text(label)).collect(),
},
),
None => (type_size(&logical_type), Value::Null),
};
rows.push(vec![
text(database.name()),
Value::BigInt(database.oid()),
text(schema.name()),
Value::BigInt(schema.oid()),
Value::BigInt(held.oid()),
text(&held.name().table),
size.map_or(Value::Null, Value::BigInt),
text(&logical_type),
type_category(&logical_type).map_or(Value::Null, text),
Value::Null,
Value::map(LogicalType::Varchar, LogicalType::Varchar, Vec::new()),
Value::Boolean(false),
Value::Null,
labels,
Value::List { element: LogicalType::Varchar, values: Vec::new() },
Value::List { element: LogicalType::Varchar, values: Vec::new() },
Value::Null,
]);
}
}
}
Metadata::new("duckdb_types", &type_fields(), &rows, plan, index, columns)
}