use dbui_core::database::column::Column;
use dbui_core::field_type::FieldType;
use dbui_core::Result;
use postgres::Row;
#[derive(Debug)]
pub(crate) struct ColumnDefinition {
table_schema: String,
table_name: String,
column_name: String,
ordinal_position: i32,
column_default: Option<String>,
is_nullable: bool,
data_type: String,
array_type: Option<String>,
character_maximum_length: Option<i32>,
character_octet_length: Option<i32>,
numeric_precision: Option<i32>,
numeric_precision_radix: Option<i32>,
numeric_scale: Option<i32>,
datetime_precision: Option<i32>,
interval_type: Option<String>,
domain_schema: Option<String>,
domain_name: Option<String>,
udt_schema: String,
udt_name: String,
dtd_identifier: String,
is_updatable: bool
}
impl ColumnDefinition {
pub(crate) fn from_row(row: &Row) -> Result<Self> {
Ok(ColumnDefinition {
table_schema: crate::get(&row, "table_schema")?,
table_name: crate::get(&row, "table_name")?,
column_name: crate::get(&row, "column_name")?,
ordinal_position: crate::get(&row, "ordinal_position")?,
column_default: crate::get(&row, "column_default")?,
is_nullable: crate::get::<String>(&row, "is_nullable")? == "YES",
data_type: crate::get(&row, "data_type")?,
array_type: crate::get(&row, "array_type")?,
character_maximum_length: crate::get(&row, "character_maximum_length")?,
character_octet_length: crate::get(&row, "character_octet_length")?,
numeric_precision: crate::get(&row, "numeric_precision")?,
numeric_precision_radix: crate::get(&row, "numeric_precision_radix")?,
numeric_scale: crate::get(&row, "numeric_scale")?,
datetime_precision: crate::get(&row, "datetime_precision")?,
interval_type: crate::get(&row, "interval_type")?,
domain_schema: crate::get(&row, "domain_schema")?,
domain_name: crate::get(&row, "domain_name")?,
udt_schema: crate::get(&row, "udt_schema")?,
udt_name: crate::get(&row, "udt_name")?,
dtd_identifier: crate::get(&row, "dtd_identifier")?,
is_updatable: crate::get::<String>(&row, "is_updatable")? == "YES"
})
}
pub(crate) fn table_schema(&self) -> &String {
&self.table_schema
}
pub(crate) fn table_name(&self) -> &String {
&self.table_name
}
pub(crate) fn typ(&self) -> FieldType {
match self.data_type.as_ref() {
"text" | "character varying" => FieldType::String,
"boolean" => FieldType::Boolean,
"character" => FieldType::Char,
"smallint" => FieldType::I16,
"integer" | "serial" => FieldType::I32,
"bigint" | "bigserial" | "int8" => FieldType::I64,
"real" => FieldType::F32,
"double precision" => FieldType::F64,
"numeric" | "money" => FieldType::Numeric,
"oid" => FieldType::U32,
"date" => FieldType::Date,
"time" | "time without time zone" => FieldType::Time,
"timetz" | "time with time zone" => FieldType::TimeZoned,
"timestamp" | "timestamp without time zone" => FieldType::Timestamp,
"timestamptz" | "timestamp with time zone" => FieldType::TimestampZoned,
"uuid" => FieldType::Uuid,
"json" | "jsonb" => FieldType::Json,
"xml" => FieldType::Xml,
"hstore" => FieldType::StringMap,
"bytea" => FieldType::ByteArray,
"but" | "bit varying" => FieldType::BitArray,
"cidr" => FieldType::Cidr,
"inet" => FieldType::InetAddr,
"macaddr" => FieldType::MacAddr,
"box" => FieldType::Box,
"circle" => FieldType::Circle,
"path" => FieldType::Path,
"polygon" => FieldType::Polygon,
"point" => FieldType::Point,
"tsquery" => FieldType::TsQuery,
"tsvector" => FieldType::TsVector,
"USER-DEFINED" => match self.udt_name.as_ref() {
"hstore" => FieldType::StringMap,
_ => {
println!("Unhandled UDT [{}]: {:?}", self.data_type, self);
FieldType::Unknown { t: self.data_type.clone() }
}
},
"ARRAY" => FieldType::List {
t: Box::new(FieldType::String)
},
_ => {
println!("Unhandled column type [{}]: {:?}", self.data_type, self);
FieldType::Unknown { t: self.data_type.clone() }
}
}
}
pub(crate) fn column(&self) -> Column {
Column::new(self.column_name.clone(), self.typ())
}
}