1use super::ColumnType;
10use std::fmt;
11use uqa_core::{
12 memory::{Produced, ProductionControl},
13 ValueRetentionError,
14};
15
16impl ColumnType {
17 #[must_use]
18 pub fn sql_name(&self) -> String {
19 TypeName {
20 ty: self,
21 regtype: false,
22 }
23 .to_string()
24 }
25
26 #[must_use]
28 pub fn regtype_name(&self) -> String {
29 TypeName {
30 ty: self,
31 regtype: true,
32 }
33 .to_string()
34 }
35
36 pub fn sql_name_with_control(
37 &self,
38 control: &ProductionControl<'_>,
39 ) -> Result<Produced<String>, ValueRetentionError> {
40 control.format(format_args!(
41 "{}",
42 TypeName {
43 ty: self,
44 regtype: false
45 }
46 ))
47 }
48
49 pub fn regtype_name_with_control(
50 &self,
51 control: &ProductionControl<'_>,
52 ) -> Result<Produced<String>, ValueRetentionError> {
53 control.format(format_args!(
54 "{}",
55 TypeName {
56 ty: self,
57 regtype: true
58 }
59 ))
60 }
61}
62
63struct TypeName<'a> {
64 ty: &'a ColumnType,
65 regtype: bool,
66}
67
68impl fmt::Display for TypeName<'_> {
69 #[expect(
70 clippy::too_many_lines,
71 reason = "one formatter preserves exhaustive SQL and regtype spellings"
72 )]
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 if self.regtype {
75 if matches!(self.ty, ColumnType::IntervalWithFields { .. }) {
76 return f.write_str("interval");
77 }
78 if self.ty.temporal_precision().is_some() {
79 return TypeName {
80 ty: self.ty.without_temporal_modifiers(),
81 regtype: true,
82 }
83 .fmt(f);
84 }
85 match self.ty {
86 ColumnType::Varchar(_) => return f.write_str("character varying"),
87 ColumnType::Bpchar | ColumnType::Character(_) => return f.write_str("character"),
88 ColumnType::Numeric { .. } => return f.write_str("numeric"),
89 ColumnType::Vector(_) => return f.write_str("vector"),
90 ColumnType::Tensor(_) => return f.write_str("tensor"),
91 ColumnType::Array(element) => {
92 return write!(
93 f,
94 "{}[]",
95 TypeName {
96 ty: element,
97 regtype: true
98 }
99 )
100 }
101 _ => {}
102 }
103 }
104 match self.ty {
105 ColumnType::Named(name) => f.write_str(name),
106 ColumnType::Enum(reference) if self.regtype => f.write_str(
108 &super::display::visible_type_name(&reference.schema, &reference.name),
109 ),
110 ColumnType::Enum(reference) => f.write_str(&crate::expr::quote_ident(&reference.name)),
111 ColumnType::Composite(reference) if self.regtype => f.write_str(
112 &super::display::visible_type_name(&reference.schema, &reference.name),
113 ),
114 ColumnType::Composite(reference) => {
115 f.write_str(&crate::expr::quote_ident(&reference.name))
116 }
117 ColumnType::SmallInteger => f.write_str("smallint"),
118 ColumnType::Integer => f.write_str("integer"),
119 ColumnType::BigInteger => f.write_str("bigint"),
120 ColumnType::Oid => f.write_str("oid"),
121 ColumnType::Xid => f.write_str("xid"),
122 ColumnType::Boolean => f.write_str("boolean"),
123 ColumnType::Void => f.write_str("void"),
124 ColumnType::Text => f.write_str("text"),
125 ColumnType::RefCursor => f.write_str("refcursor"),
126 ColumnType::Name => f.write_str("name"),
127 ColumnType::Uuid => f.write_str("uuid"),
128 ColumnType::Varchar(Some(length)) => write!(f, "character varying({length})"),
129 ColumnType::Varchar(None) => f.write_str("character varying"),
130 ColumnType::Bpchar => f.write_str("bpchar"),
131 ColumnType::Character(length) => write!(f, "character({length})"),
132 ColumnType::Real => f.write_str("real"),
133 ColumnType::DoublePrecision => f.write_str("double precision"),
134 ColumnType::Numeric {
135 precision: Some(precision),
136 scale: Some(scale),
137 } => write!(f, "numeric({precision},{scale})"),
138 ColumnType::Numeric { .. } => f.write_str("numeric"),
139 ColumnType::Json => f.write_str("json"),
140 ColumnType::JsonB => f.write_str("jsonb"),
141 ColumnType::Bytea => f.write_str("bytea"),
142 ColumnType::InternalChar => f.write_str("\"char\""),
143 ColumnType::Regproc => f.write_str("regproc"),
144 ColumnType::Regprocedure => f.write_str("regprocedure"),
145 ColumnType::Regclass => f.write_str("regclass"),
146 ColumnType::Regcollation => f.write_str("regcollation"),
147 ColumnType::Regnamespace => f.write_str("regnamespace"),
148 ColumnType::Regrole => f.write_str("regrole"),
149 ColumnType::Regtype => f.write_str("regtype"),
150 ColumnType::PgNodeTree => f.write_str("pg_node_tree"),
151 ColumnType::AclItem => f.write_str("aclitem"),
152 ColumnType::Int2Vector => f.write_str("int2vector"),
153 ColumnType::OidVector => f.write_str("oidvector"),
154 ColumnType::AnyArray => f.write_str("anyarray"),
155 ColumnType::Record => f.write_str("record"),
156 ColumnType::Array(element) => write!(
157 f,
158 "{}[]",
159 TypeName {
160 ty: element,
161 regtype: false
162 }
163 ),
164 ColumnType::Date => f.write_str("date"),
165 ColumnType::Time => f.write_str("time without time zone"),
166 ColumnType::TimePrecision(p) => write!(f, "time({p}) without time zone"),
167 ColumnType::TimeTz => f.write_str("time with time zone"),
168 ColumnType::TimeTzPrecision(p) => write!(f, "time({p}) with time zone"),
169 ColumnType::Timestamp => f.write_str("timestamp without time zone"),
170 ColumnType::TimestampPrecision(p) => write!(f, "timestamp({p}) without time zone"),
171 ColumnType::TimestampTz => f.write_str("timestamp with time zone"),
172 ColumnType::TimestampTzPrecision(p) => write!(f, "timestamp({p}) with time zone"),
173 ColumnType::Interval => f.write_str("interval"),
174 ColumnType::IntervalWithFields { fields, precision } => {
175 write!(f, "interval{}", fields.sql_suffix())?;
176 if let Some(precision) = precision {
177 write!(f, "({precision})")?;
178 }
179 Ok(())
180 }
181 ColumnType::Range(subtype) => f.write_str(subtype.range_name()),
182 ColumnType::Multirange(subtype) => f.write_str(subtype.multirange_name()),
183 ColumnType::Vector(dimension) => write!(f, "vector({dimension})"),
184 ColumnType::Tensor(dimension) => write!(f, "tensor({dimension})"),
185 ColumnType::Domain { schema, name, .. } if self.regtype => {
186 f.write_str(&super::display::visible_type_name(schema, name))
187 }
188 ColumnType::Domain { schema, name, .. } => {
189 crate::compiler::write_relation_component(schema, f)?;
190 f.write_str(".")?;
191 crate::compiler::write_relation_component(name, f)
192 }
193 }
194 }
195}
196
197#[cfg(test)]
198mod tests;