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::SmallInteger => f.write_str("smallint"),
107 ColumnType::Integer => f.write_str("integer"),
108 ColumnType::BigInteger => f.write_str("bigint"),
109 ColumnType::Oid => f.write_str("oid"),
110 ColumnType::Xid => f.write_str("xid"),
111 ColumnType::Boolean => f.write_str("boolean"),
112 ColumnType::Void => f.write_str("void"),
113 ColumnType::Text => f.write_str("text"),
114 ColumnType::RefCursor => f.write_str("refcursor"),
115 ColumnType::Name => f.write_str("name"),
116 ColumnType::Uuid => f.write_str("uuid"),
117 ColumnType::Varchar(Some(length)) => write!(f, "character varying({length})"),
118 ColumnType::Varchar(None) => f.write_str("character varying"),
119 ColumnType::Bpchar => f.write_str("bpchar"),
120 ColumnType::Character(length) => write!(f, "character({length})"),
121 ColumnType::Real => f.write_str("real"),
122 ColumnType::DoublePrecision => f.write_str("double precision"),
123 ColumnType::Numeric {
124 precision: Some(precision),
125 scale: Some(scale),
126 } => write!(f, "numeric({precision},{scale})"),
127 ColumnType::Numeric { .. } => f.write_str("numeric"),
128 ColumnType::Json => f.write_str("json"),
129 ColumnType::JsonB => f.write_str("jsonb"),
130 ColumnType::Bytea => f.write_str("bytea"),
131 ColumnType::InternalChar => f.write_str("\"char\""),
132 ColumnType::Regproc => f.write_str("regproc"),
133 ColumnType::Regprocedure => f.write_str("regprocedure"),
134 ColumnType::Regclass => f.write_str("regclass"),
135 ColumnType::Regnamespace => f.write_str("regnamespace"),
136 ColumnType::Regrole => f.write_str("regrole"),
137 ColumnType::Regtype => f.write_str("regtype"),
138 ColumnType::PgNodeTree => f.write_str("pg_node_tree"),
139 ColumnType::AclItem => f.write_str("aclitem"),
140 ColumnType::Int2Vector => f.write_str("int2vector"),
141 ColumnType::OidVector => f.write_str("oidvector"),
142 ColumnType::AnyArray => f.write_str("anyarray"),
143 ColumnType::Record => f.write_str("record"),
144 ColumnType::Array(element) => write!(
145 f,
146 "{}[]",
147 TypeName {
148 ty: element,
149 regtype: false
150 }
151 ),
152 ColumnType::Date => f.write_str("date"),
153 ColumnType::Time => f.write_str("time without time zone"),
154 ColumnType::TimePrecision(p) => write!(f, "time({p}) without time zone"),
155 ColumnType::TimeTz => f.write_str("time with time zone"),
156 ColumnType::TimeTzPrecision(p) => write!(f, "time({p}) with time zone"),
157 ColumnType::Timestamp => f.write_str("timestamp without time zone"),
158 ColumnType::TimestampPrecision(p) => write!(f, "timestamp({p}) without time zone"),
159 ColumnType::TimestampTz => f.write_str("timestamp with time zone"),
160 ColumnType::TimestampTzPrecision(p) => write!(f, "timestamp({p}) with time zone"),
161 ColumnType::Interval => f.write_str("interval"),
162 ColumnType::IntervalWithFields { fields, precision } => {
163 write!(f, "interval{}", fields.sql_suffix())?;
164 if let Some(precision) = precision {
165 write!(f, "({precision})")?;
166 }
167 Ok(())
168 }
169 ColumnType::Range(subtype) => f.write_str(subtype.range_name()),
170 ColumnType::Multirange(subtype) => f.write_str(subtype.multirange_name()),
171 ColumnType::Vector(dimension) => write!(f, "vector({dimension})"),
172 ColumnType::Tensor(dimension) => write!(f, "tensor({dimension})"),
173 ColumnType::Domain { schema, name, .. } => {
174 crate::compiler::write_relation_component(schema, f)?;
175 f.write_str(".")?;
176 crate::compiler::write_relation_component(name, f)
177 }
178 }
179 }
180}
181
182#[cfg(test)]
183mod tests;