canyon_observer/migrations/
information_schema.rs

1#[cfg(feature = "mssql")]
2use canyon_connection::tiberius::ColumnType as TIB_TY;
3#[cfg(feature = "postgres")]
4use canyon_connection::tokio_postgres::types::Type as TP_TYP;
5use 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)]
13pub 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)]
20pub 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)]
37pub enum ColumnMetadataTypeValue {
38    StringValue(Option<String>),
39    IntValue(Option<i32>),
40    NoneValue,
41}
42impl 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        }
71    }
72}