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