1use std::collections::{HashMap, HashSet};
2use std::fmt;
3use std::hash::{Hash, Hasher};
4use std::ops::Index;
5
6use crate::function::Param;
7use crate::types::*;
8
9#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct Field {
11 pub name: String,
12 pub kind: DataType,
13}
14
15impl Field {
16 pub fn new(name: &str, kind: DataType) -> Self {
17 Field {
18 name: name.to_string(),
19 kind,
20 }
21 }
22
23 pub fn new_owned(name: String, kind: DataType) -> Self {
24 Field { name, kind }
25 }
26
27 pub fn name(&self) -> &String {
28 &self.name
29 }
30
31 pub fn kind(&self) -> &DataType {
32 &self.kind
33 }
34}
35
36impl ::core::convert::From<Param> for Field {
37 #[allow(unused_variables)]
38 #[inline]
39 fn from(original: Param) -> Field {
40 Field::new(&original.name, original.kind)
41 }
42}
43
44#[derive(Debug, Clone, PartialOrd, Ord)]
45pub struct Schema {
46 pub pk: Option<usize>,
47 pub fields: Vec<Field>,
48}
49
50impl Schema {
51 pub fn new(fields: Vec<Field>, pk: Option<usize>) -> Self {
52 Schema { pk, fields }
53 }
54
55 pub fn new_single(name: &str, kind: DataType) -> Self {
56 let field = Field::new(name, kind);
57 Self::new(vec![field], None)
58 }
59
60 pub fn scalar_field(kind: DataType) -> Self {
61 Self::new_single("it", kind)
62 }
63
64 pub fn named(&self, name: &str) -> Option<(usize, &Field)> {
65 self.fields
66 .iter()
67 .enumerate()
68 .find(|&(_, field)| field.name == name)
69 }
70
71 pub fn len(&self) -> usize {
72 self.fields.len()
73 }
74 pub fn is_empty(&self) -> bool {
75 self.len() == 0
76 }
77
78 pub fn pk_field(&self) -> Option<Field> {
79 if let Some(pos) = self.pk {
80 self.fields
81 .get(self.resolve_pos(&Column::Pos(pos)))
82 .cloned()
83 } else {
84 None
85 }
86 }
87
88 pub fn resolve_name(&self, of: &Column) -> (usize, Field) {
89 match of {
90 Column::Pos(x) => (*x, self.fields[*x].clone()),
91 Column::Name(x) => {
92 let (pos, f) = self.named(x).unwrap();
93 (pos, f.clone())
94 }
95 Column::Alias(x) => {
96 let (pos, mut f) = self.resolve_name(&x.from);
97 f.name = x.to.clone();
98 (pos, f)
99 }
100 }
101 }
102
103 pub fn resolve_pos(&self, of: &Column) -> usize {
105 match of {
106 Column::Pos(x) => *x,
107 Column::Name(x) => {
108 let (pos, _f) = self.named(x).unwrap();
109 pos
110 }
111 Column::Alias(x) => self.resolve_pos(&x.from),
112 }
113 }
114
115 pub fn resolve_pos_many(&self, of: &[Column]) -> Pos {
116 of.iter().map(|x| self.resolve_pos(x)).collect()
117 }
118
119 pub fn pick_new_pk(&mut self, old: Option<Field>) {
120 if let Some(pk) = old {
121 if let Some((pos, _)) = self.named(&pk.name) {
122 self.pk = Some(pos);
123 } else {
124 self.pk = Some(0);
125 }
126 }
127 }
128
129 pub fn extend(&self, right: &Schema) -> Self {
130 let mut fields = Vec::with_capacity(self.len() + right.len());
131 fields.append(&mut self.fields.clone());
132
133 let mut find: HashMap<String, usize> =
134 self.fields.iter().map(|x| (x.name.clone(), 2)).collect();
135
136 for f in right.fields.clone() {
138 if find.contains_key(&f.name) {
139 let cont = find[&f.name];
140 find.insert(f.name.clone(), cont + 1);
141
142 let name = format!("{}_{}", f.name, cont);
143 fields.push(Field::new(&name, f.kind));
144 } else {
145 fields.push(f);
146 }
147 }
148
149 Self::new(fields, self.pk)
150 }
151
152 pub fn project(&self, select: &ProjectDef) -> (Schema, Pos) {
153 let pk = self.pk_field();
154 let mut selected: Vec<Field> = Vec::new();
155 let mut pos = Vec::new();
156 let resolved = select.columns().iter().map(|f| self.resolve_name(f));
157 let total = select.columns().len();
158 let mut to_select = HashSet::with_capacity(total);
159 let mut fields = Vec::with_capacity(total);
160
161 for (pos, f) in resolved {
162 to_select.insert(pos);
163 fields.push(f);
164 }
165
166 match select {
167 ProjectDef::Select(_) => {
168 for (i, _) in self.fields.iter().enumerate() {
169 if to_select.contains(&i) {
170 selected.push(fields[i].clone());
171 pos.push(i);
172 }
173 }
174 }
175 ProjectDef::Deselect(_) => {
176 for (i, f) in self.fields.iter().enumerate() {
177 if !to_select.contains(&i) {
178 selected.push(f.clone());
179 pos.push(i);
180 }
181 }
182 }
183 };
184
185 let mut schema = Schema::new(selected, None);
186 schema.pick_new_pk(pk);
187 (schema, pos)
188 }
189
190 pub fn kind(&self) -> Vec<DataType> {
191 self.fields.iter().map(|x| x.kind.clone()).collect()
192 }
193}
194
195pub(crate) fn check_pk(schema: &Schema) -> usize {
196 schema.pk.expect("Relation need a pk")
197}
198
199impl Index<usize> for Schema {
200 type Output = Field;
201
202 fn index(&self, pos: usize) -> &Field {
203 &self.fields[pos]
204 }
205}
206
207impl PartialEq for Schema {
208 fn eq(&self, other: &Schema) -> bool {
209 if self.fields.len() == other.fields.len() {
210 let mut a = self.fields.clone();
211 let mut b = other.fields.clone();
212 a.sort();
213 b.sort();
214 a == b
215 } else {
216 false
217 }
218 }
219}
220
221impl Eq for Schema {}
222
223impl Hash for Schema {
224 fn hash<H: Hasher>(&self, state: &mut H) {
225 let mut a = self.fields.clone();
226 a.sort();
227 a.hash(state);
228 }
229}
230
231impl fmt::Display for Field {
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 write!(f, "{}:{}", self.name, self.kind)
234 }
235}
236
237impl fmt::Display for Schema {
238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239 for i in 0..self.len() {
240 let item = &self.fields[i];
241 if Some(i) == self.pk {
242 if i > 0 {
243 write!(f, ", pk {}", item)?;
244 } else {
245 write!(f, "pk {}", item)?;
246 }
247 } else if i > 0 {
248 write!(f, ", {}", item)?;
249 } else {
250 write!(f, "{}", item)?;
251 }
252 }
253
254 Ok(())
255 }
256}