1mod boolean;
2mod data_set;
3mod date_time;
4mod decimal;
5mod fixed_char;
6mod float;
7mod integer;
8mod interval_day_to_second;
9mod interval_year_to_month;
10mod ip_address;
11mod map;
12mod option;
13mod row;
14mod seq;
15mod string;
16pub(self) mod util;
17pub mod uuid;
18
19pub use self::uuid::*;
20pub use boolean::*;
21pub use data_set::*;
22pub use date_time::*;
23pub use decimal::*;
24pub use fixed_char::*;
25pub use float::*;
26pub use integer::*;
27pub use integer::*;
28pub use interval_day_to_second::*;
29pub use interval_year_to_month::*;
30pub use ip_address::*;
31pub use map::*;
32pub use option::*;
33pub use row::*;
34pub use seq::*;
35pub use string::*;
36
37use std::borrow::Cow;
41use std::collections::HashMap;
42use std::iter::FromIterator;
43use std::sync::Arc;
44
45use derive_more::Display;
46use iterable::*;
47use serde::de::DeserializeSeed;
48use serde::Serialize;
49
50use crate::{
51 ClientTypeSignatureParameter, Column, NamedTypeSignature, RawPrestoTy, RowFieldName,
52 TypeSignature,
53};
54
55#[derive(Display, Debug)]
57pub enum Error {
58 InvalidPrestoType,
59 InvalidColumn,
60 InvalidTypeSignature,
61 ParseDecimalFailed(String),
62 ParseIntervalMonthFailed,
63 ParseIntervalDayFailed,
64 EmptyInPrestoRow,
65 NonePrestoRow,
66}
67
68pub trait Presto {
69 type ValueType<'a>: Serialize
70 where
71 Self: 'a;
72 type Seed<'a, 'de>: DeserializeSeed<'de, Value = Self>;
73
74 fn value(&self) -> Self::ValueType<'_>;
75
76 fn ty() -> PrestoTy;
77
78 fn seed<'a, 'de>(ctx: &'a Context<'a>) -> Self::Seed<'a, 'de>;
80
81 fn empty() -> Self;
82}
83
84pub trait PrestoMapKey: Presto {}
85
86#[derive(Debug)]
87pub struct Context<'a> {
88 ty: &'a PrestoTy,
89 map: Arc<HashMap<usize, Vec<usize>>>,
90}
91
92impl<'a> Context<'a> {
93 pub fn new<T: Presto>(provided: &'a PrestoTy) -> Result<Self, Error> {
94 let target = T::ty();
95 let ret = extract(&target, provided)?;
96 let map = HashMap::from_iter(ret.into_iter());
97 Ok(Context {
98 ty: provided,
99 map: Arc::new(map),
100 })
101 }
102
103 pub fn with_ty(&'a self, ty: &'a PrestoTy) -> Context<'a> {
104 Context {
105 ty,
106 map: self.map.clone(),
107 }
108 }
109
110 pub fn ty(&self) -> &PrestoTy {
111 self.ty
112 }
113
114 pub fn row_map(&self) -> Option<&[usize]> {
115 let key = self.ty as *const PrestoTy as usize;
116 self.map.get(&key).map(|r| &**r)
117 }
118}
119
120fn extract(target: &PrestoTy, provided: &PrestoTy) -> Result<Vec<(usize, Vec<usize>)>, Error> {
121 use PrestoTy::*;
122
123 match (target, provided) {
124 (Unknown, _) => Ok(vec![]),
125 (Decimal(p1, s1), Decimal(p2, s2)) if p1 == p2 && s1 == s2 => Ok(vec![]),
126 (Option(ty), provided) => extract(ty, provided),
127 (Boolean, Boolean) => Ok(vec![]),
128 (Date, Date) => Ok(vec![]),
129 (Time, Time) => Ok(vec![]),
130 (Timestamp, Timestamp) => Ok(vec![]),
131 (IntervalYearToMonth, IntervalYearToMonth) => Ok(vec![]),
132 (IntervalDayToSecond, IntervalDayToSecond) => Ok(vec![]),
133 (PrestoInt(_), PrestoInt(_)) => Ok(vec![]),
134 (PrestoFloat(_), PrestoFloat(_)) => Ok(vec![]),
135 (Varchar, Varchar) => Ok(vec![]),
136 (Char(a), Char(b)) if a == b => Ok(vec![]),
137 (Tuple(t1), Tuple(t2)) => {
138 if t1.len() != t2.len() {
139 Err(Error::InvalidPrestoType)
140 } else {
141 t1.lazy_zip(t2).try_flat_map(|(l, r)| extract(l, r))
142 }
143 }
144 (Row(t1), Row(t2)) => {
145 if t1.len() != t2.len() {
146 Err(Error::InvalidPrestoType)
147 } else {
148 let t1k = t1.sorted_by(|t1, t2| Ord::cmp(&t1.0, &t2.0));
150 let t2k = t2.sorted_by(|t1, t2| Ord::cmp(&t1.0, &t2.0));
151
152 let ret = t1k.lazy_zip(t2k).try_flat_map(|(l, r)| {
153 if l.0 == r.0 {
154 extract(&l.1, &r.1)
155 } else {
156 Err(Error::InvalidPrestoType)
157 }
158 })?;
159
160 let map = t2.map(|provided| t1.position(|target| provided.0 == target.0).unwrap());
161 let key = provided as *const PrestoTy as usize;
162 Ok(ret.add_one((key, map)))
163 }
164 }
165 (Array(t1), Array(t2)) => extract(t1, t2),
166 (Map(t1k, t1v), Map(t2k, t2v)) => Ok(extract(t1k, t2k)?.chain(extract(t1v, t2v)?)),
167 (IpAddress, IpAddress) => Ok(vec![]),
168 (Uuid, Uuid) => Ok(vec![]),
169 _ => Err(Error::InvalidPrestoType),
170 }
171}
172
173#[derive(Clone, Debug, Eq, PartialEq)]
179pub enum PrestoTy {
180 Date,
181 Time,
182 Timestamp,
183 Uuid,
184 IntervalYearToMonth,
185 IntervalDayToSecond,
186 Option(Box<PrestoTy>),
187 Boolean,
188 PrestoInt(PrestoInt),
189 PrestoFloat(PrestoFloat),
190 Varchar,
191 Char(usize),
192 Tuple(Vec<PrestoTy>),
193 Row(Vec<(String, PrestoTy)>),
194 Array(Box<PrestoTy>),
195 Map(Box<PrestoTy>, Box<PrestoTy>),
196 Decimal(usize, usize),
197 IpAddress,
198 Unknown,
199}
200
201#[derive(Clone, Debug, Eq, PartialEq)]
202pub enum PrestoInt {
203 I8,
204 I16,
205 I32,
206 I64,
207}
208
209#[derive(Clone, Debug, Eq, PartialEq)]
210pub enum PrestoFloat {
211 F32,
212 F64,
213}
214
215impl PrestoTy {
216 pub fn from_type_signature(mut sig: TypeSignature) -> Result<Self, Error> {
217 use PrestoFloat::*;
218 use PrestoInt::*;
219
220 let ty = match sig.raw_type {
221 RawPrestoTy::Date => PrestoTy::Date,
222 RawPrestoTy::Time => PrestoTy::Time,
223 RawPrestoTy::Timestamp => PrestoTy::Timestamp,
224 RawPrestoTy::IntervalYearToMonth => PrestoTy::IntervalYearToMonth,
225 RawPrestoTy::IntervalDayToSecond => PrestoTy::IntervalDayToSecond,
226 RawPrestoTy::Unknown => PrestoTy::Unknown,
227 RawPrestoTy::Decimal if sig.arguments.len() == 2 => {
228 let s_sig = sig.arguments.pop().unwrap();
229 let p_sig = sig.arguments.pop().unwrap();
230 if let (
231 ClientTypeSignatureParameter::LongLiteral(p),
232 ClientTypeSignatureParameter::LongLiteral(s),
233 ) = (p_sig, s_sig)
234 {
235 PrestoTy::Decimal(p as usize, s as usize)
236 } else {
237 return Err(Error::InvalidTypeSignature);
238 }
239 }
240 RawPrestoTy::Boolean => PrestoTy::Boolean,
241 RawPrestoTy::TinyInt => PrestoTy::PrestoInt(I8),
242 RawPrestoTy::SmallInt => PrestoTy::PrestoInt(I16),
243 RawPrestoTy::Integer => PrestoTy::PrestoInt(I32),
244 RawPrestoTy::BigInt => PrestoTy::PrestoInt(I64),
245 RawPrestoTy::Real => PrestoTy::PrestoFloat(F32),
246 RawPrestoTy::Double => PrestoTy::PrestoFloat(F64),
247 RawPrestoTy::VarChar => PrestoTy::Varchar,
248 RawPrestoTy::Char if sig.arguments.len() == 1 => {
249 if let ClientTypeSignatureParameter::LongLiteral(p) = sig.arguments.pop().unwrap() {
250 PrestoTy::Char(p as usize)
251 } else {
252 return Err(Error::InvalidTypeSignature);
253 }
254 }
255 RawPrestoTy::Array if sig.arguments.len() == 1 => {
256 let sig = sig.arguments.pop().unwrap();
257 if let ClientTypeSignatureParameter::TypeSignature(sig) = sig {
258 let inner = Self::from_type_signature(sig)?;
259 PrestoTy::Array(Box::new(inner))
260 } else {
261 return Err(Error::InvalidTypeSignature);
262 }
263 }
264 RawPrestoTy::Map if sig.arguments.len() == 2 => {
265 let v_sig = sig.arguments.pop().unwrap();
266 let k_sig = sig.arguments.pop().unwrap();
267 if let (
268 ClientTypeSignatureParameter::TypeSignature(k_sig),
269 ClientTypeSignatureParameter::TypeSignature(v_sig),
270 ) = (k_sig, v_sig)
271 {
272 let k_inner = Self::from_type_signature(k_sig)?;
273 let v_inner = Self::from_type_signature(v_sig)?;
274 PrestoTy::Map(Box::new(k_inner), Box::new(v_inner))
275 } else {
276 return Err(Error::InvalidTypeSignature);
277 }
278 }
279 RawPrestoTy::Row if !sig.arguments.is_empty() => {
280 let ir = sig.arguments.try_map(|arg| match arg {
281 ClientTypeSignatureParameter::NamedTypeSignature(sig) => {
282 let name = sig.field_name.map(|n| n.name);
283 let ty = Self::from_type_signature(sig.type_signature)?;
284 Ok((name, ty))
285 }
286 _ => Err(Error::InvalidTypeSignature),
287 })?;
288
289 let is_named = ir[0].0.is_some();
290
291 if is_named {
292 let row = ir.try_map(|(name, ty)| match name {
293 Some(n) => Ok((n, ty)),
294 None => Err(Error::InvalidTypeSignature),
295 })?;
296 PrestoTy::Row(row)
297 } else {
298 let tuple = ir.try_map(|(name, ty)| match name {
299 Some(_) => Err(Error::InvalidTypeSignature),
300 None => Ok(ty),
301 })?;
302 PrestoTy::Tuple(tuple)
303 }
304 }
305 RawPrestoTy::IpAddress => PrestoTy::IpAddress,
306 RawPrestoTy::Uuid => PrestoTy::Uuid,
307 _ => return Err(Error::InvalidTypeSignature),
308 };
309
310 Ok(ty)
311 }
312
313 pub fn from_column(column: Column) -> Result<(String, Self), Error> {
314 let name = column.name;
315 if let Some(sig) = column.type_signature {
316 let ty = Self::from_type_signature(sig)?;
317 Ok((name, ty))
318 } else {
319 Err(Error::InvalidColumn)
320 }
321 }
322
323 pub fn from_columns(columns: Vec<Column>) -> Result<Self, Error> {
324 let row = columns.try_map(Self::from_column)?;
325 Ok(PrestoTy::Row(row))
326 }
327
328 pub fn into_type_signature(self) -> TypeSignature {
329 use PrestoTy::*;
330
331 let raw_ty = self.raw_type();
332
333 let params = match self {
334 Unknown => vec![],
335 Decimal(p, s) => vec![
336 ClientTypeSignatureParameter::LongLiteral(p as u64),
337 ClientTypeSignatureParameter::LongLiteral(s as u64),
338 ],
339 Date => vec![],
340 Time => vec![],
341 Timestamp => vec![],
342 IntervalYearToMonth => vec![],
343 IntervalDayToSecond => vec![],
344 Option(t) => return t.into_type_signature(),
345 Boolean => vec![],
346 PrestoInt(_) => vec![],
347 PrestoFloat(_) => vec![],
348 Varchar => vec![ClientTypeSignatureParameter::LongLiteral(2147483647)],
349 Char(a) => vec![ClientTypeSignatureParameter::LongLiteral(a as u64)],
350 Tuple(ts) => ts.map(|ty| {
351 ClientTypeSignatureParameter::NamedTypeSignature(NamedTypeSignature {
352 field_name: None,
353 type_signature: ty.into_type_signature(),
354 })
355 }),
356 Row(ts) => ts.map(|(name, ty)| {
357 ClientTypeSignatureParameter::NamedTypeSignature(NamedTypeSignature {
358 field_name: Some(RowFieldName::new(name)),
359 type_signature: ty.into_type_signature(),
360 })
361 }),
362 Array(t) => vec![ClientTypeSignatureParameter::TypeSignature(
363 t.into_type_signature(),
364 )],
365 Map(t1, t2) => vec![
366 ClientTypeSignatureParameter::TypeSignature(t1.into_type_signature()),
367 ClientTypeSignatureParameter::TypeSignature(t2.into_type_signature()),
368 ],
369 IpAddress => vec![],
370 Uuid => vec![],
371 };
372
373 TypeSignature::new(raw_ty, params)
374 }
375
376 pub fn full_type(&self) -> Cow<'static, str> {
377 use PrestoTy::*;
378
379 match self {
380 Unknown => RawPrestoTy::Unknown.to_str().into(),
381 Decimal(p, s) => format!("{}({},{})", RawPrestoTy::Decimal.to_str(), p, s).into(),
382 Option(t) => t.full_type(),
383 Date => RawPrestoTy::Date.to_str().into(),
384 Time => RawPrestoTy::Time.to_str().into(),
385 Timestamp => RawPrestoTy::Timestamp.to_str().into(),
386 IntervalYearToMonth => RawPrestoTy::IntervalYearToMonth.to_str().into(),
387 IntervalDayToSecond => RawPrestoTy::IntervalDayToSecond.to_str().into(),
388 Boolean => RawPrestoTy::Boolean.to_str().into(),
389 PrestoInt(ty) => ty.raw_type().to_str().into(),
390 PrestoFloat(ty) => ty.raw_type().to_str().into(),
391 Varchar => RawPrestoTy::VarChar.to_str().into(),
392 Char(a) => format!("{}({})", RawPrestoTy::Char.to_str(), a).into(),
393 Tuple(ts) => format!(
394 "{}({})",
395 RawPrestoTy::Row.to_str(),
396 ts.lazy_map(|ty| ty.full_type()).join(",")
397 )
398 .into(),
399 Row(ts) => format!(
400 "{}({})",
401 RawPrestoTy::Row.to_str(),
402 ts.lazy_map(|(name, ty)| format!("{} {}", name, ty.full_type()))
403 .join(",")
404 )
405 .into(),
406 Array(t) => format!("{}({})", RawPrestoTy::Array.to_str(), t.full_type()).into(),
407 Map(t1, t2) => format!(
408 "{}({},{})",
409 RawPrestoTy::Map.to_str(),
410 t1.full_type(),
411 t2.full_type()
412 )
413 .into(),
414 IpAddress => RawPrestoTy::IpAddress.to_str().into(),
415 Uuid => RawPrestoTy::Uuid.to_str().into(),
416 }
417 }
418
419 pub fn raw_type(&self) -> RawPrestoTy {
420 use PrestoTy::*;
421
422 match self {
423 Unknown => RawPrestoTy::Unknown,
424 Date => RawPrestoTy::Date,
425 Time => RawPrestoTy::Time,
426 Timestamp => RawPrestoTy::Timestamp,
427 IntervalYearToMonth => RawPrestoTy::IntervalYearToMonth,
428 IntervalDayToSecond => RawPrestoTy::IntervalDayToSecond,
429 Decimal(_, _) => RawPrestoTy::Decimal,
430 Option(ty) => ty.raw_type(),
431 Boolean => RawPrestoTy::Boolean,
432 PrestoInt(ty) => ty.raw_type(),
433 PrestoFloat(ty) => ty.raw_type(),
434 Varchar => RawPrestoTy::VarChar,
435 Char(_) => RawPrestoTy::Char,
436 Tuple(_) => RawPrestoTy::Row,
437 Row(_) => RawPrestoTy::Row,
438 Array(_) => RawPrestoTy::Array,
439 Map(_, _) => RawPrestoTy::Map,
440 IpAddress => RawPrestoTy::IpAddress,
441 Uuid => RawPrestoTy::Uuid,
442 }
443 }
444}
445
446impl PrestoInt {
447 pub fn raw_type(&self) -> RawPrestoTy {
448 use PrestoInt::*;
449 match self {
450 I8 => RawPrestoTy::TinyInt,
451 I16 => RawPrestoTy::SmallInt,
452 I32 => RawPrestoTy::Integer,
453 I64 => RawPrestoTy::BigInt,
454 }
455 }
456}
457
458impl PrestoFloat {
459 pub fn raw_type(&self) -> RawPrestoTy {
460 use PrestoFloat::*;
461 match self {
462 F32 => RawPrestoTy::Real,
463 F64 => RawPrestoTy::Double,
464 }
465 }
466}