1
#[cfg(feature = "mssql")]
2
use canyon_connection::tiberius::ColumnType as TIB_TY;
3
#[cfg(feature = "postgres")]
4
use canyon_connection::tokio_postgres::types::Type as TP_TYP;
5
use canyon_crud::bounds::{Column, ColumnType, Row, RowOperations};
6

            
7
/// Model that represents the database entities that belongs to the current schema.
8
///
9
/// Basically, it's an agrupation of rows of results when Canyon queries the `information schema`
10
/// table, grouping by table name (one [`TableMetadata`] is the rows that contains the information
11
/// of a table)
12
#[derive(Debug)]
13
pub struct TableMetadata {
14
    pub table_name: String,
15
    pub columns: Vec<ColumnMetadata>,
16
}
17

            
18
/// Represents the *metadata* associated with a column that belongs to a `PostgreSQL` table.
19
#[derive(Debug, Default)]
20
pub struct ColumnMetadata {
21
    pub column_name: String,
22
    pub datatype: String,
23
    pub character_maximum_length: Option<i32>,
24
    pub is_nullable: bool, // Care, postgres type is varchar
25
    pub column_default: Option<String>,
26
    pub foreign_key_info: Option<String>,
27
    pub foreign_key_name: Option<String>,
28
    pub primary_key_info: Option<String>,
29
    pub primary_key_name: Option<String>,
30
    pub is_identity: bool, // Care, postgres type is varchar
31
    pub identity_generation: Option<String>,
32
}
33

            
34
/// Represents the relation between a real value stored inside a [`ColumnMetadata`]
35
/// and the datatype of that value
36
#[derive(Debug)]
37
pub enum ColumnMetadataTypeValue {
38
    StringValue(Option<String>),
39
    IntValue(Option<i32>),
40
    NoneValue,
41
}
42
impl ColumnMetadataTypeValue {
43
    /// Retrieves the value stored in a [`Column`] for a passed [`Row`]
44
    pub fn get_value(row: &dyn Row, col: &Column) -> Self {
45
        match col.column_type() {
46
            #[cfg(feature = "postgres")]
47
            ColumnType::Postgres(v) => {
48
                match *v {
49
                    TP_TYP::NAME | TP_TYP::VARCHAR | TP_TYP::TEXT => Self::StringValue(
50
                        row.get_postgres_opt::<&str>(col.name())
51
                            .map(|opt| opt.to_owned()),
52
                    ),
53
                    TP_TYP::INT4 => Self::IntValue(row.get_postgres_opt::<i32>(col.name())),
54
                    _ => Self::NoneValue, // TODO watchout this one
55
                }
56
            }
57
            #[cfg(feature = "mssql")]
58
            ColumnType::SqlServer(v) => match v {
59
                TIB_TY::NChar | TIB_TY::NVarchar | TIB_TY::BigChar | TIB_TY::BigVarChar => {
60
                    Self::StringValue(
61
                        row.get_mssql_opt::<&str>(col.name())
62
                            .map(|opt| opt.to_owned()),
63
                    )
64
                }
65
                TIB_TY::Int2 | TIB_TY::Int4 | TIB_TY::Int8 | TIB_TY::Intn => {
66
                    Self::IntValue(row.get_mssql_opt::<i32>(col.name()))
67
                }
68
                _ => Self::NoneValue,
69
            },
70
            #[cfg(feature = "mysql")]
71
            ColumnType::MySQL(_) => todo!(),
72
        }
73
    }
74
}