risingwave_common/types/
struct_type.rs1use std::fmt::{Debug, Display, Formatter};
16use std::iter::empty;
17use std::str::FromStr;
18use std::sync::Arc;
19
20use anyhow::anyhow;
21use either::Either;
22use itertools::{Itertools, repeat_n};
23
24use super::DataType;
25use crate::catalog::ColumnId;
26use crate::util::iter_util::ZipEqFast;
27use crate::util::quote_ident::QuoteIdent;
28
29#[derive(Clone, PartialEq, Eq, Hash)]
31pub struct StructType(Arc<StructTypeInner>);
32
33impl Debug for StructType {
34 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
35 let alternate = f.alternate();
36
37 let mut d = f.debug_struct("StructType");
38 d.field("fields", &self.0.fields);
39 if let Some(ids) = &self.0.field_ids
40 && alternate
43 {
44 d.field("field_ids", ids);
45 }
46 d.finish()
47 }
48}
49
50#[derive(Clone, Debug, educe::Educe)]
51#[educe(PartialEq, Eq, Hash)] struct StructTypeInner {
53 fields: Box<[(String, DataType)]>,
57
58 #[educe(PartialEq(ignore), Hash(ignore))]
63 field_ids: Option<Box<[ColumnId]>>,
64
65 #[educe(PartialEq(ignore), Hash(ignore))]
67 is_unnamed: bool,
68}
69
70impl StructType {
71 pub fn new(named_fields: impl IntoIterator<Item = (impl Into<String>, DataType)>) -> Self {
73 let fields = named_fields
74 .into_iter()
75 .map(|(name, ty)| (name.into(), ty))
76 .collect();
77
78 Self(Arc::new(StructTypeInner {
79 fields,
80 field_ids: None,
81 is_unnamed: false,
82 }))
83 }
84
85 #[cfg(test)]
87 pub fn empty() -> Self {
88 Self::unnamed(Vec::new())
89 }
90
91 pub fn unnamed(fields: impl IntoIterator<Item = DataType>) -> Self {
93 let fields = fields
94 .into_iter()
95 .enumerate()
96 .map(|(i, ty)| (format!("f{}", i + 1), ty))
97 .collect();
98
99 Self(Arc::new(StructTypeInner {
100 fields,
101 field_ids: None,
102 is_unnamed: true,
103 }))
104 }
105
106 pub fn row_expr_type(fields: impl IntoIterator<Item = DataType>) -> Self {
108 Self::unnamed(fields)
109 }
110
111 pub fn with_ids(self, ids: impl IntoIterator<Item = ColumnId>) -> Self {
116 let ids: Box<[ColumnId]> = ids.into_iter().collect();
117
118 assert_eq!(ids.len(), self.len(), "ids length mismatches");
119 assert!(
120 ids.iter().all(|id| *id != ColumnId::placeholder()),
121 "ids should not contain placeholder value"
122 );
123
124 if self.is_empty() {
126 return self;
127 }
128
129 let mut inner = Arc::unwrap_or_clone(self.0);
130 inner.field_ids = Some(ids);
131 Self(Arc::new(inner))
132 }
133
134 pub fn has_ids(&self) -> bool {
138 self.is_empty() || self.0.field_ids.is_some()
139 }
140
141 pub fn is_unnamed(&self) -> bool {
143 self.0.is_unnamed
144 }
145
146 pub fn len(&self) -> usize {
148 self.0.fields.len()
149 }
150
151 pub fn is_empty(&self) -> bool {
153 self.0.fields.is_empty()
154 }
155
156 pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
160 self.0.fields.iter().map(|(name, _)| name.as_str())
161 }
162
163 pub fn types(&self) -> impl ExactSizeIterator<Item = &DataType> {
165 self.0.fields.iter().map(|(_, ty)| ty)
166 }
167
168 pub fn type_at(&self, index: usize) -> &DataType {
170 &self.0.fields[index].1
171 }
172
173 pub fn iter(&self) -> impl ExactSizeIterator<Item = (&str, &DataType)> {
177 self.0.fields.iter().map(|(name, ty)| (name.as_str(), ty))
178 }
179
180 pub fn ids(&self) -> Option<impl ExactSizeIterator<Item = ColumnId> + '_> {
185 if self.is_empty() {
186 Some(Either::Left(empty()))
187 } else {
188 (self.0.field_ids.as_ref())
189 .map(|field_ids| field_ids.iter().copied())
190 .map(Either::Right)
191 }
192 }
193
194 pub fn id_at(&self, index: usize) -> Option<ColumnId> {
199 self.ids().map(|mut ids| ids.nth(index).unwrap())
200 }
201
202 pub fn ids_or_placeholder(&self) -> impl ExactSizeIterator<Item = ColumnId> + '_ {
204 match self.ids() {
205 Some(ids) => Either::Left(ids),
206 None => Either::Right(repeat_n(ColumnId::placeholder(), self.len())),
207 }
208 }
209
210 pub fn equals_datatype(&self, other: &StructType) -> bool {
212 if self.len() != other.len() {
213 return false;
214 }
215
216 (self.types())
217 .zip_eq_fast(other.types())
218 .all(|(a, b)| a.equals_datatype(b))
219 }
220}
221
222impl Display for StructType {
223 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
224 if self.is_unnamed() {
225 write!(f, "record")
227 } else {
228 write!(
229 f,
230 "struct<{}>",
231 self.iter()
232 .map(|(name, ty)| format!("{} {}", QuoteIdent(name), ty))
233 .join(", ")
234 )
235 }
236 }
237}
238
239impl FromStr for StructType {
240 type Err = anyhow::Error;
241
242 fn from_str(s: &str) -> Result<Self, Self::Err> {
243 if s == "record" {
244 return Ok(StructType::unnamed(Vec::new()));
245 }
246 if !(s.starts_with("struct<") && s.ends_with('>')) {
247 return Err(anyhow!("expect struct<...>"));
248 };
249 let mut fields = Vec::new();
250 for field in s[7..s.len() - 1].split(',') {
251 let field = field.trim();
252 let mut iter = field.split_whitespace();
253 let field_name = iter.next().unwrap().to_owned();
254 let field_type = DataType::from_str(iter.next().unwrap())?;
255 fields.push((field_name, field_type));
256 }
257 Ok(Self::new(fields))
258 }
259}