datasources-postgres 0.1.53

Postgres datasource provider
Documentation
use datasources::{DatasourceError, FieldSize, Mapping, Result, SpecField};
use std::collections::HashMap;

pub struct TypeMap {
    dictionary: HashMap<String, String>,
    reverse: HashMap<String, String>,
}

impl TypeMap {
    pub fn new(dictionary: HashMap<String, String>) -> Self {
        let mut reverse = HashMap::new();
        for (spec, native) in &dictionary {
            reverse.entry(native.clone()).or_insert_with(|| spec.clone());
        }
        Self { dictionary, reverse }
    }

    pub fn convert_field(&self, field: &SpecField) -> Result<String> {
        match field.type_name.as_str() {
            "string" => Ok(match field.size {
                None | Some(FieldSize::Unlimited) => "TEXT".into(),
                Some(FieldSize::Length(n)) | Some(FieldSize::Decimal(n, _)) => format!("VARCHAR({n})"),
            }),
            "character" => Ok(format!(
                "CHAR({})",
                match field.size {
                    None | Some(FieldSize::Unlimited) => 1,
                    Some(FieldSize::Length(n)) | Some(FieldSize::Decimal(n, _)) => n,
                }
            )),
            "decimal" => match field.size {
                None | Some(FieldSize::Unlimited) => Ok("NUMERIC".into()),
                Some(FieldSize::Decimal(p, s)) => Ok(format!("NUMERIC({p}, {s})")),
                Some(FieldSize::Length(_)) => Err(DatasourceError::message(format!(
                    "decimal field \"{}\" size must be [precision, scale] tuple; got {:?}",
                    field.name.as_deref().unwrap_or(""),
                    field.size
                ))),
            },
            _ => Mapping::convert(self, &field.type_name),
        }
    }
}

impl Mapping<String, String> for TypeMap {
    fn convert(&self, from: &String) -> Result<String> {
        self.dictionary
            .get(from)
            .cloned()
            .ok_or_else(|| DatasourceError::message(format!("Unknown spec field type: {from}")))
    }

    fn reverse_convert(&self, native: &String) -> Result<String> {
        self.reverse
            .get(native)
            .cloned()
            .ok_or_else(|| DatasourceError::message(format!("Unknown native field type: {native}")))
    }
}