sea_schema/postgres/parser/
column.rs1use crate::postgres::{
2 def::*, discovery::EnumVariantMap, parser::yes_or_no_to_bool, query::ColumnQueryResult,
3};
4use sea_query::RcOrArc;
5
6impl ColumnQueryResult {
7 pub fn parse(self, enums: &EnumVariantMap) -> ColumnInfo {
8 parse_column_query_result(self, enums)
9 }
10}
11
12pub fn parse_column_query_result(result: ColumnQueryResult, enums: &EnumVariantMap) -> ColumnInfo {
13 ColumnInfo {
14 name: result.column_name.clone(),
15 col_type: parse_column_type(&result, enums),
16 default: ColumnExpression::from_option_string(result.column_default),
17 generated: ColumnExpression::from_option_string(result.column_generated),
18 not_null: NotNull::from_bool(!yes_or_no_to_bool(&result.is_nullable)),
19 is_identity: yes_or_no_to_bool(&result.is_identity),
20 }
21}
22
23pub fn parse_column_type(result: &ColumnQueryResult, enums: &EnumVariantMap) -> ColumnType {
24 let is_enum = result
25 .udt_name
26 .as_ref()
27 .map_or(false, |udt_name| enums.contains_key(udt_name));
28 let mut ctype = Type::from_str(
29 result.column_type.as_str(),
30 result.udt_name.as_deref(),
31 is_enum,
32 );
33
34 if ctype.has_numeric_attr() {
35 ctype = parse_numeric_attributes(
36 result.numeric_precision,
37 result.numeric_precision_radix,
38 result.numeric_scale,
39 ctype,
40 );
41 }
42 if ctype.has_string_attr() {
43 ctype = parse_string_attributes(result.character_maximum_length, ctype);
44 }
45 if ctype.has_time_attr() {
46 ctype = parse_time_attributes(result.datetime_precision, ctype);
47 }
48 if ctype.has_interval_attr() {
49 ctype = parse_interval_attributes(&result.interval_type, result.interval_precision, ctype);
50 }
51 if ctype.has_bit_attr() {
52 ctype = parse_bit_attributes(result.character_maximum_length, ctype);
53 }
54 if ctype.has_enum_attr() {
55 ctype = parse_enum_attributes(result.udt_name.as_deref(), ctype, enums);
56 }
57 if ctype.has_array_attr() {
58 ctype = parse_array_attributes(result.udt_name_regtype.as_deref(), ctype, enums);
59 }
60 #[cfg(feature = "postgres-vector")]
61 if ctype.has_vector_attr() {
62 ctype = parse_vector_attributes(result.character_maximum_length, ctype);
63 }
64
65 ctype
66}
67
68pub fn parse_numeric_attributes(
69 num_precision: Option<i32>,
70 num_precision_radix: Option<i32>,
71 num_scale: Option<i32>,
72 mut ctype: ColumnType,
73) -> ColumnType {
74 let numeric_precision: Option<u16> = match num_precision {
75 None => None,
76 Some(num) => u16::try_from(num).ok(),
77 };
78 let _numeric_precision_radix: Option<u16> = match num_precision_radix {
79 None => None,
80 Some(num) => u16::try_from(num).ok(),
81 };
82 let numeric_scale: Option<u16> = match num_scale {
83 None => None,
84 Some(num) => u16::try_from(num).ok(),
85 };
86
87 match ctype {
88 Type::Decimal(ref mut attr) | Type::Numeric(ref mut attr) => {
89 attr.precision = numeric_precision;
90 attr.scale = numeric_scale;
91 }
92 _ => panic!("parse_numeric_attributes(_) received a type other than Decimal or Numeric"),
93 };
94
95 ctype
96}
97
98pub fn parse_string_attributes(
99 character_maximum_length: Option<i32>,
100 mut ctype: ColumnType,
101) -> ColumnType {
102 match ctype {
103 Type::Varchar(ref mut attr) | Type::Char(ref mut attr) => {
104 attr.length = match character_maximum_length {
105 None => None,
106 Some(num) => u16::try_from(num).ok(),
107 };
108 }
109 _ => panic!("parse_string_attributes(_) received a type that does not have StringAttr"),
110 };
111
112 ctype
113}
114
115pub fn parse_time_attributes(datetime_precision: Option<i32>, mut ctype: ColumnType) -> ColumnType {
116 match ctype {
117 Type::Timestamp(ref mut attr)
118 | Type::TimestampWithTimeZone(ref mut attr)
119 | Type::Time(ref mut attr)
120 | Type::TimeWithTimeZone(ref mut attr) => {
121 attr.precision = match datetime_precision {
122 None => None,
123 Some(num) => u16::try_from(num).ok(),
124 };
125 }
126 _ => panic!("parse_time_attributes(_) received a type that does not have TimeAttr"),
127 };
128
129 ctype
130}
131
132pub fn parse_interval_attributes(
133 interval_type: &Option<String>,
134 interval_precision: Option<i32>,
135 mut ctype: ColumnType,
136) -> ColumnType {
137 match ctype {
138 Type::Interval(ref mut attr) => {
139 attr.field.clone_from(interval_type);
140 attr.precision = match interval_precision {
141 None => None,
142 Some(num) => u16::try_from(num).ok(),
143 };
144 }
145 _ => panic!("parse_interval_attributes(_) received a type that does not have IntervalAttr"),
146 };
147
148 ctype
149}
150
151pub fn parse_bit_attributes(
152 character_maximum_length: Option<i32>,
153 mut ctype: ColumnType,
154) -> ColumnType {
155 match ctype {
156 Type::Bit(ref mut attr) => {
157 attr.length = match character_maximum_length {
158 None => None,
159 Some(num) => u16::try_from(num).ok(),
160 };
161 }
162 Type::VarBit(ref mut attr) => {
163 attr.length = match character_maximum_length {
164 None => None,
165 Some(num) => u16::try_from(num).ok(),
166 };
167 }
168 _ => panic!("parse_bit_attributes(_) received a type that does not have BitAttr"),
169 };
170
171 ctype
172}
173
174pub fn parse_enum_attributes(
175 udt_name: Option<&str>,
176 mut ctype: ColumnType,
177 enums: &EnumVariantMap,
178) -> ColumnType {
179 match ctype {
180 Type::Enum(ref mut def) => {
181 def.typename = match udt_name {
182 None => panic!("parse_enum_attributes(_) received an empty udt_name"),
183 Some(typename) => typename.to_string(),
184 };
185 if let Some(variants) = enums.get(&def.typename) {
186 def.values.clone_from(variants);
187 }
188 }
189 _ => panic!("parse_enum_attributes(_) received a type that does not have EnumDef"),
190 };
191
192 ctype
193}
194
195pub fn parse_array_attributes(
196 udt_name_regtype: Option<&str>,
197 mut ctype: ColumnType,
198 enums: &EnumVariantMap,
199) -> ColumnType {
200 match ctype {
201 Type::Array(ref mut def) => {
202 def.col_type = match udt_name_regtype {
203 None => panic!("parse_array_attributes(_) received an empty udt_name_regtype"),
204 Some(typename) => {
205 let typename = &typename.replacen('"', "", 2).replacen("[]", "", 1);
206 let arr_col_type = if let Some(variants) = enums.get(typename) {
207 Type::Enum(EnumDef {
208 typename: typename.to_string(),
209 values: variants.clone(),
210 })
211 } else {
212 Type::from_str(typename, Some(typename), false)
213 };
214 Some(RcOrArc::new(arr_col_type))
215 }
216 };
217 }
218 _ => panic!("parse_array_attributes(_) received a type that does not have EnumDef"),
219 };
220
221 ctype
222}
223
224#[cfg(feature = "postgres-vector")]
225pub fn parse_vector_attributes(
226 character_maximum_length: Option<i32>,
227 mut ctype: ColumnType,
228) -> ColumnType {
229 match ctype {
230 Type::Vector(ref mut attr) => {
231 attr.length = match character_maximum_length {
232 None => None,
233 Some(num) => match u32::try_from(num) {
234 Ok(num) => Some(num),
235 Err(_) => None,
236 },
237 };
238 }
239 _ => panic!("parse_vector_attributes(_) received a type that does not have StringAttr"),
240 };
241
242 ctype
243}