dbui-database 0.0.64

Database access and schema introspection for dbui
Documentation
use anyhow::Result;
use dbui_core::database::column::Column;
use dbui_core::field_type::FieldType;

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())
  }
}