sea_schema/postgres/query/
column.rs

1use super::{InformationSchema, SchemaQueryBuilder};
2use crate::sqlx_types::postgres::PgRow;
3use sea_query::{BinOper, Expr, Iden, Query, SeaRc, SelectStatement};
4
5#[derive(Debug, sea_query::Iden)]
6/// Ref: https://www.postgresql.org/docs/13/infoschema-columns.html
7pub enum ColumnsField {
8    TableCatalog,
9    TableSchema,
10    TableName,
11    ColumnName,
12    OrdinalPosition,
13    ColumnDefault,
14    IsNullable,
15    DataType,
16    CharacterMaximumLength,
17    CharacterOctetLength,
18    NumericPrecision,
19    NumericPrecisionRadix,
20    NumericScale,
21    DatetimePrecision,
22    IntervalType,
23    IntervalPrecision,
24    CollationCatalog,
25    CollationSchema,
26    CollationName,
27    DomainCatalog,
28    DomainSchema,
29    DomainName,
30    UdtCatalog,
31    UdtSchema,
32    UdtName,
33    DtdIdentifier,
34    IsIdentity,
35    IdentityGeneration,
36    IdentityStart,
37    IdentityIncrement,
38    IdentityMaximum,
39    IdentityMinimum,
40    IdentityCycle,
41    IsGenerated,
42    GenerationExpression,
43    IsUpdatable,
44}
45
46#[derive(Debug, Default)]
47pub struct ColumnQueryResult {
48    pub column_name: String,
49    pub column_type: String,
50    pub column_default: Option<String>,
51    pub column_generated: Option<String>,
52    pub is_nullable: String,
53    pub is_identity: String,
54
55    // Declared or implicit parameters of numeric types; null for other data types
56    pub numeric_precision: Option<i32>,
57    pub numeric_precision_radix: Option<i32>,
58    pub numeric_scale: Option<i32>,
59
60    pub character_maximum_length: Option<i32>,
61    pub character_octet_length: Option<i32>,
62
63    pub datetime_precision: Option<i32>,
64
65    pub interval_type: Option<String>,
66    pub interval_precision: Option<i32>,
67
68    pub udt_name: Option<String>,
69    pub udt_name_regtype: Option<String>,
70}
71
72impl SchemaQueryBuilder {
73    pub fn query_columns(
74        &self,
75        schema: SeaRc<dyn Iden>,
76        table: SeaRc<dyn Iden>,
77    ) -> SelectStatement {
78        Query::select()
79            .columns([
80                ColumnsField::ColumnName,
81                ColumnsField::DataType,
82                ColumnsField::ColumnDefault,
83                ColumnsField::GenerationExpression,
84                ColumnsField::IsNullable,
85                ColumnsField::IsIdentity,
86                ColumnsField::NumericPrecision,
87                ColumnsField::NumericPrecisionRadix,
88                ColumnsField::NumericScale,
89                ColumnsField::CharacterMaximumLength,
90                ColumnsField::CharacterOctetLength,
91                ColumnsField::DatetimePrecision,
92                ColumnsField::IntervalType,
93                ColumnsField::IntervalPrecision,
94                ColumnsField::UdtName,
95            ])
96            .expr(
97                // The double quotes are required to correctly handle user types containing
98                // upper case letters.
99                Expr::expr(Expr::cust("CONCAT('\"', udt_name, '\"')::regtype").cast_as(Text))
100                    .binary(BinOper::As, Expr::col(UdtNameRegtype)),
101            )
102            .from((InformationSchema::Schema, InformationSchema::Columns))
103            .and_where(Expr::col(ColumnsField::TableSchema).eq(schema.to_string()))
104            .and_where(Expr::col(ColumnsField::TableName).eq(table.to_string()))
105            .take()
106    }
107}
108
109#[cfg(feature = "sqlx-postgres")]
110impl From<&PgRow> for ColumnQueryResult {
111    fn from(row: &PgRow) -> Self {
112        use crate::sqlx_types::Row;
113        Self {
114            column_name: row.get(0),
115            column_type: row.get(1),
116            column_default: row.get(2),
117            column_generated: row.get(3),
118            is_nullable: row.get(4),
119            is_identity: row.get(5),
120            numeric_precision: row.get(6),
121            numeric_precision_radix: row.get(7),
122            numeric_scale: row.get(8),
123            character_maximum_length: row.get(9),
124            character_octet_length: row.get(10),
125            datetime_precision: row.get(11),
126            interval_type: row.get(12),
127            interval_precision: row.get(13),
128            udt_name: row.get(14),
129            udt_name_regtype: row.get(15),
130        }
131    }
132}
133
134#[cfg(not(feature = "sqlx-postgres"))]
135impl From<&PgRow> for ColumnQueryResult {
136    fn from(_: &PgRow) -> Self {
137        Self::default()
138    }
139}
140
141#[derive(Iden)]
142struct Text;
143#[derive(Iden)]
144struct UdtNameRegtype;