1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use diesel::*;
use diesel::backend::Backend;
use diesel::types::{FromSqlRow, HasSqlType};
use std::fmt;
use std::str::FromStr;

#[derive(Debug, Clone, PartialEq)]
pub struct TableData {
    pub name: String,
    pub schema: Option<String>,
}

impl TableData {
    pub fn from_name<T: Into<String>>(name: T) -> Self {
        TableData {
            name: name.into(),
            schema: None,
        }
    }

    pub fn new<T, U>(name: T, schema: U) -> Self where
        T: Into<String>,
        U: Into<String>,
    {
        TableData {
            name: name.into(),
            schema: Some(schema.into()),
        }
    }
}

impl<ST, DB> Queryable<ST, DB> for TableData where
    DB: Backend + HasSqlType<ST>,
    (String, String): FromSqlRow<ST, DB>,
{
    type Row = (String, String);

    fn build((name, schema): Self::Row) -> Self {
        TableData::new(name, schema)
    }
}

impl fmt::Display for TableData {
    fn fmt(&self, out: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.schema {
            Some(ref schema_name) => write!(out, "{}.{}", schema_name, self.name),
            None => write!(out, "{}", self.name)
        }
    }
}

#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Never {}

impl FromStr for TableData {
    type Err = Never;

    fn from_str(table_name: &str) -> Result<Self, Self::Err> {
        let mut parts = table_name.split('.');
        match (parts.next(), parts.next()) {
            (Some(schema), Some(name)) => Ok(TableData::new(name, schema)),
            _ => Ok(TableData::from_name(table_name)),
        }
    }
}