1use {
2 super::{
3 date::{parse_date, parse_time, parse_timestamp},
4 error::ValueError,
5 Value,
6 },
7 crate::{
8 ast::DataType,
9 data::{value::uuid::parse_uuid, BigDecimalExt, Interval, Literal, Point},
10 result::{Error, Result},
11 },
12 bigdecimal::BigDecimal,
13 chrono::NaiveDate,
14 rust_decimal::Decimal,
15 std::{
16 cmp::Ordering,
17 net::{IpAddr, Ipv4Addr, Ipv6Addr},
18 str::FromStr,
19 },
20};
21
22impl TryFrom<&Literal<'_>> for Value {
23 type Error = Error;
24
25 fn try_from(literal: &Literal<'_>) -> Result<Self> {
26 match literal {
27 Literal::Number(v) => v
28 .to_i64()
29 .map(Value::I64)
30 .or_else(|| v.to_f64().map(Value::F64))
31 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
32 Literal::Boolean(v) => Ok(Value::Bool(*v)),
33 Literal::Text(v) => Ok(Value::Str(v.as_ref().to_owned())),
34 Literal::Bytea(v) => Ok(Value::Bytea(v.to_vec())),
35 Literal::Null => Ok(Value::Null),
36 }
37 }
38}
39
40impl TryFrom<Literal<'_>> for Value {
41 type Error = Error;
42
43 fn try_from(literal: Literal<'_>) -> Result<Self> {
44 match literal {
45 Literal::Text(v) => Ok(Value::Str(v.into_owned())),
46 _ => Value::try_from(&literal),
47 }
48 }
49}
50
51impl Value {
52 pub fn evaluate_eq_with_literal(&self, other: &Literal<'_>) -> bool {
53 match (self, other) {
54 (Value::Bool(l), Literal::Boolean(r)) => l == r,
55 (Value::I8(l), Literal::Number(r)) => r.to_i8().map(|r| *l == r).unwrap_or(false),
56 (Value::I16(l), Literal::Number(r)) => r.to_i16().map(|r| *l == r).unwrap_or(false),
57 (Value::I32(l), Literal::Number(r)) => r.to_i32().map(|r| *l == r).unwrap_or(false),
58 (Value::I64(l), Literal::Number(r)) => r.to_i64().map(|r| *l == r).unwrap_or(false),
59 (Value::I128(l), Literal::Number(r)) => r.to_i128().map(|r| *l == r).unwrap_or(false),
60 (Value::U8(l), Literal::Number(r)) => r.to_u8().map(|r| *l == r).unwrap_or(false),
61 (Value::U16(l), Literal::Number(r)) => r.to_u16().map(|r| *l == r).unwrap_or(false),
62 (Value::U32(l), Literal::Number(r)) => r.to_u32().map(|r| *l == r).unwrap_or(false),
63 (Value::U64(l), Literal::Number(r)) => r.to_u64().map(|r| *l == r).unwrap_or(false),
64 (Value::U128(l), Literal::Number(r)) => r.to_u128().map(|r| *l == r).unwrap_or(false),
65 (Value::F32(l), Literal::Number(r)) => r.to_f32().map(|r| *l == r).unwrap_or(false),
66 (Value::F64(l), Literal::Number(r)) => r.to_f64().map(|r| *l == r).unwrap_or(false),
67 (Value::Str(l), Literal::Text(r)) => l == r.as_ref(),
68 (Value::Bytea(l), Literal::Bytea(r)) => l == r,
69 (Value::Date(l), Literal::Text(r)) => match r.parse::<NaiveDate>() {
70 Ok(r) => l == &r,
71 Err(_) => false,
72 },
73 (Value::Timestamp(l), Literal::Text(r)) => match parse_timestamp(r) {
74 Some(r) => l == &r,
75 None => false,
76 },
77 (Value::Time(l), Literal::Text(r)) => match parse_time(r) {
78 Some(r) => l == &r,
79 None => false,
80 },
81 (Value::Uuid(l), Literal::Text(r)) => parse_uuid(r).map(|r| l == &r).unwrap_or(false),
82 (Value::Inet(l), Literal::Text(r)) => match IpAddr::from_str(r) {
83 Ok(x) => l == &x,
84 Err(_) => false,
85 },
86 (Value::Inet(l), Literal::Number(r)) => {
87 if let Some(x) = r.to_u32() {
88 l == &Ipv4Addr::from(x)
89 } else if let Some(x) = r.to_u128() {
90 l == &Ipv6Addr::from(x)
91 } else {
92 false
93 }
94 }
95 (Value::Null, Literal::Null) => false,
96 _ => false,
97 }
98 }
99
100 pub fn evaluate_cmp_with_literal(&self, other: &Literal<'_>) -> Option<Ordering> {
101 match (self, other) {
102 (Value::I8(l), Literal::Number(r)) => l.partial_cmp(&r.to_i8()?),
103 (Value::I16(l), Literal::Number(r)) => l.partial_cmp(&r.to_i16()?),
104 (Value::I32(l), Literal::Number(r)) => l.partial_cmp(&r.to_i32()?),
105 (Value::I64(l), Literal::Number(r)) => l.partial_cmp(&r.to_i64()?),
106 (Value::I128(l), Literal::Number(r)) => l.partial_cmp(&r.to_i128()?),
107 (Value::U8(l), Literal::Number(r)) => l.partial_cmp(&r.to_u8()?),
108 (Value::U16(l), Literal::Number(r)) => l.partial_cmp(&r.to_u16()?),
109 (Value::U32(l), Literal::Number(r)) => l.partial_cmp(&r.to_u32()?),
110 (Value::U64(l), Literal::Number(r)) => l.partial_cmp(&r.to_u64()?),
111 (Value::U128(l), Literal::Number(r)) => l.partial_cmp(&r.to_u128()?),
112 (Value::F32(l), Literal::Number(r)) => l.partial_cmp(&r.to_f32()?),
113 (Value::F64(l), Literal::Number(r)) => l.partial_cmp(&r.to_f64()?),
114 (Value::Decimal(l), Literal::Number(r)) => {
115 BigDecimal::new(l.mantissa().into(), l.scale() as i64).partial_cmp(r)
116 }
117 (Value::Str(l), Literal::Text(r)) => Some(l.as_str().cmp(r)),
118 (Value::Date(l), Literal::Text(r)) => l.partial_cmp(&r.parse::<NaiveDate>().ok()?),
119 (Value::Timestamp(l), Literal::Text(r)) => l.partial_cmp(&parse_timestamp(r)?),
120 (Value::Time(l), Literal::Text(r)) => l.partial_cmp(&parse_time(r)?),
121 (Value::Uuid(l), Literal::Text(r)) => l.partial_cmp(&parse_uuid(r).ok()?),
122 (Value::Inet(l), Literal::Text(r)) => l.partial_cmp(&IpAddr::from_str(r).ok()?),
123 (Value::Inet(l), Literal::Number(r)) => {
124 if let Some(x) = r.to_u32() {
125 l.partial_cmp(&Ipv4Addr::from(x))
126 } else if let Some(x) = r.to_u128() {
127 l.partial_cmp(&Ipv6Addr::from(x))
128 } else {
129 None
130 }
131 }
132 _ => None,
133 }
134 }
135
136 pub fn try_from_literal(data_type: &DataType, literal: &Literal<'_>) -> Result<Value> {
137 match (data_type, literal) {
138 (DataType::Boolean, Literal::Boolean(v)) => Ok(Value::Bool(*v)),
139 (DataType::Int8, Literal::Number(v)) => v
140 .to_i8()
141 .map(Value::I8)
142 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
143 (DataType::Int16, Literal::Number(v)) => v
144 .to_i16()
145 .map(Value::I16)
146 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
147 (DataType::Int32, Literal::Number(v)) => v
148 .to_i32()
149 .map(Value::I32)
150 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
151 (DataType::Int, Literal::Number(v)) => v
152 .to_i64()
153 .map(Value::I64)
154 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
155 (DataType::Int128, Literal::Number(v)) => v
156 .to_i128()
157 .map(Value::I128)
158 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
159 (DataType::Uint8, Literal::Number(v)) => v
160 .to_u8()
161 .map(Value::U8)
162 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
163 (DataType::Uint16, Literal::Number(v)) => v
164 .to_u16()
165 .map(Value::U16)
166 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
167 (DataType::Uint32, Literal::Number(v)) => v
168 .to_u32()
169 .map(Value::U32)
170 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
171 (DataType::Uint64, Literal::Number(v)) => v
172 .to_u64()
173 .map(Value::U64)
174 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
175 (DataType::Uint128, Literal::Number(v)) => v
176 .to_u128()
177 .map(Value::U128)
178 .ok_or_else(|| ValueError::FailedToParseNumber.into()),
179 (DataType::Float32, Literal::Number(v)) => v
180 .to_f32()
181 .map(Value::F32)
182 .ok_or_else(|| ValueError::UnreachableNumberParsing.into()),
183 (DataType::Float, Literal::Number(v)) => v
184 .to_f64()
185 .map(Value::F64)
186 .ok_or_else(|| ValueError::UnreachableNumberParsing.into()),
187 (DataType::Text, Literal::Text(v)) => Ok(Value::Str(v.to_string())),
188 (DataType::Bytea, Literal::Bytea(v)) => Ok(Value::Bytea(v.to_vec())),
189 (DataType::Bytea, Literal::Text(v)) => hex::decode(v.as_ref())
190 .map(Value::Bytea)
191 .map_err(|_| ValueError::FailedToParseHexString(v.to_string()).into()),
192 (DataType::Inet, Literal::Text(v)) => IpAddr::from_str(v.as_ref())
193 .map(Value::Inet)
194 .map_err(|_| ValueError::FailedToParseInetString(v.to_string()).into()),
195 (DataType::Inet, Literal::Number(v)) => {
196 if let Some(x) = v.to_u32() {
197 Ok(Value::Inet(IpAddr::V4(Ipv4Addr::from(x))))
198 } else {
199 Ok(Value::Inet(IpAddr::V6(Ipv6Addr::from(
200 v.to_u128().unwrap(),
201 ))))
202 }
203 }
204 (DataType::Date, Literal::Text(v)) => v
205 .parse::<NaiveDate>()
206 .map(Value::Date)
207 .map_err(|_| ValueError::FailedToParseDate(v.to_string()).into()),
208 (DataType::Timestamp, Literal::Text(v)) => parse_timestamp(v)
209 .map(Value::Timestamp)
210 .ok_or_else(|| ValueError::FailedToParseTimestamp(v.to_string()).into()),
211 (DataType::Time, Literal::Text(v)) => parse_time(v)
212 .map(Value::Time)
213 .ok_or_else(|| ValueError::FailedToParseTime(v.to_string()).into()),
214 (DataType::Uuid, Literal::Text(v)) => parse_uuid(v).map(Value::Uuid),
215 (DataType::Uuid, Literal::Bytea(v)) => parse_uuid(&hex::encode(v)).map(Value::Uuid),
216 (DataType::Map, Literal::Text(v)) => Value::parse_json_map(v),
217 (DataType::List, Literal::Text(v)) => Value::parse_json_list(v),
218 (DataType::Decimal, Literal::Number(v)) => v
219 .to_string()
220 .parse::<Decimal>()
221 .map(Value::Decimal)
222 .map_err(|_| ValueError::FailedToParseDecimal(v.to_string()).into()),
223 (_, Literal::Null) => Ok(Value::Null),
224 _ => Err(ValueError::IncompatibleLiteralForDataType {
225 data_type: data_type.clone(),
226 literal: format!("{:?}", literal),
227 }
228 .into()),
229 }
230 }
231
232 pub fn try_cast_from_literal(data_type: &DataType, literal: &Literal<'_>) -> Result<Value> {
233 match (data_type, literal) {
234 (DataType::Boolean, Literal::Boolean(v)) => Ok(Value::Bool(*v)),
235 (DataType::Boolean, Literal::Text(v)) => match v.to_uppercase().as_str() {
236 "TRUE" | "1" => Ok(Value::Bool(true)),
237 "FALSE" | "0" => Ok(Value::Bool(false)),
238 _ => Err(ValueError::LiteralCastToBooleanFailed(v.to_string()).into()),
239 },
240 (DataType::Boolean, Literal::Number(v)) => match v.to_i64() {
241 Some(0) => Ok(Value::Bool(false)),
242 Some(1) => Ok(Value::Bool(true)),
243 _ => Err(ValueError::LiteralCastToBooleanFailed(v.to_string()).into()),
244 },
245 (DataType::Int8, Literal::Text(v)) => v
246 .parse::<i8>()
247 .map(Value::I8)
248 .map_err(|_| ValueError::LiteralCastFromTextToIntegerFailed(v.to_string()).into()),
249 (DataType::Int8, Literal::Number(v)) => match v.to_i8() {
250 Some(x) => Ok(Value::I8(x)),
251 None => Err(ValueError::LiteralCastToInt8Failed(v.to_string()).into()),
252 },
253 (DataType::Int8, Literal::Boolean(v)) => {
254 let v = i8::from(*v);
255
256 Ok(Value::I8(v))
257 }
258 (DataType::Int16, Literal::Text(v)) => v
259 .parse::<i16>()
260 .map(Value::I16)
261 .map_err(|_| ValueError::LiteralCastFromTextToIntegerFailed(v.to_string()).into()),
262 (DataType::Int16, Literal::Number(v)) => match v.to_i16() {
263 Some(x) => Ok(Value::I16(x)),
264 None => Err(ValueError::LiteralCastToInt8Failed(v.to_string()).into()),
265 },
266 (DataType::Int16, Literal::Boolean(v)) => {
267 let v = i16::from(*v);
268
269 Ok(Value::I16(v))
270 }
271 (DataType::Int32, Literal::Text(v)) => v
272 .parse::<i32>()
273 .map(Value::I32)
274 .map_err(|_| ValueError::LiteralCastFromTextToIntegerFailed(v.to_string()).into()),
275 (DataType::Int32, Literal::Number(v)) => match v.to_i32() {
276 Some(x) => Ok(Value::I32(x)),
277 None => Err(ValueError::LiteralCastToDataTypeFailed(
278 DataType::Int32,
279 v.to_string(),
280 )
281 .into()),
282 },
283 (DataType::Int32, Literal::Boolean(v)) => {
284 let v = i32::from(*v);
285
286 Ok(Value::I32(v))
287 }
288 (DataType::Int, Literal::Text(v)) => v
289 .parse::<i64>()
290 .map(Value::I64)
291 .map_err(|_| ValueError::LiteralCastFromTextToIntegerFailed(v.to_string()).into()),
292 (DataType::Int, Literal::Number(v)) => match v.to_i64() {
293 Some(x) => Ok(Value::I64(x)),
294 None => Err(
295 ValueError::LiteralCastToDataTypeFailed(DataType::Int, v.to_string()).into(),
296 ),
297 },
298 (DataType::Int, Literal::Boolean(v)) => {
299 let v = i64::from(*v);
300
301 Ok(Value::I64(v))
302 }
303 (DataType::Int128, Literal::Text(v)) => v
304 .parse::<i128>()
305 .map(Value::I128)
306 .map_err(|_| ValueError::LiteralCastFromTextToIntegerFailed(v.to_string()).into()),
307 (DataType::Int128, Literal::Number(v)) => match v.to_i128() {
308 Some(x) => Ok(Value::I128(x)),
309 None => Err(ValueError::LiteralCastToDataTypeFailed(
310 DataType::Int128,
311 v.to_string(),
312 )
313 .into()),
314 },
315 (DataType::Int128, Literal::Boolean(v)) => {
316 let v = i128::from(*v);
317
318 Ok(Value::I128(v))
319 }
320 (DataType::Uint8, Literal::Text(v)) => v.parse::<u8>().map(Value::U8).map_err(|_| {
321 ValueError::LiteralCastFromTextToUnsignedInt8Failed(v.to_string()).into()
322 }),
323 (DataType::Uint8, Literal::Number(v)) => match v.to_u8() {
324 Some(x) => Ok(Value::U8(x)),
325 None => Err(ValueError::LiteralCastToUnsignedInt8Failed(v.to_string()).into()),
326 },
327 (DataType::Uint8, Literal::Boolean(v)) => {
328 let v = u8::from(*v);
329
330 Ok(Value::U8(v))
331 }
332 (DataType::Uint16, Literal::Text(v)) => v
333 .parse::<u16>()
334 .map(Value::U16)
335 .map_err(|_| ValueError::LiteralCastFromTextToUint16Failed(v.to_string()).into()),
336 (DataType::Uint16, Literal::Number(v)) => match v.to_u16() {
337 Some(x) => Ok(Value::U16(x)),
338 None => Err(ValueError::LiteralCastToUint16Failed(v.to_string()).into()),
339 },
340 (DataType::Uint16, Literal::Boolean(v)) => {
341 let v = u16::from(*v);
342
343 Ok(Value::U16(v))
344 }
345 (DataType::Uint32, Literal::Text(v)) => v
346 .parse::<u32>()
347 .map(Value::U32)
348 .map_err(|_| ValueError::LiteralCastFromTextToUint32Failed(v.to_string()).into()),
349 (DataType::Uint32, Literal::Number(v)) => match v.to_u32() {
350 Some(x) => Ok(Value::U32(x)),
351 None => Err(ValueError::LiteralCastToUint32Failed(v.to_string()).into()),
352 },
353 (DataType::Uint32, Literal::Boolean(v)) => {
354 let v = u32::from(*v);
355
356 Ok(Value::U32(v))
357 }
358
359 (DataType::Uint64, Literal::Text(v)) => v
360 .parse::<u64>()
361 .map(Value::U64)
362 .map_err(|_| ValueError::LiteralCastFromTextToUint64Failed(v.to_string()).into()),
363 (DataType::Uint64, Literal::Number(v)) => match v.to_u64() {
364 Some(x) => Ok(Value::U64(x)),
365 None => Err(ValueError::LiteralCastToUint64Failed(v.to_string()).into()),
366 },
367 (DataType::Uint64, Literal::Boolean(v)) => {
368 let v = u64::from(*v);
369
370 Ok(Value::U64(v))
371 }
372
373 (DataType::Uint128, Literal::Text(v)) => v
374 .parse::<u128>()
375 .map(Value::U128)
376 .map_err(|_| ValueError::LiteralCastFromTextToUint128Failed(v.to_string()).into()),
377 (DataType::Uint128, Literal::Number(v)) => match v.to_u128() {
378 Some(x) => Ok(Value::U128(x)),
379 None => Err(ValueError::LiteralCastToUint128Failed(v.to_string()).into()),
380 },
381 (DataType::Uint128, Literal::Boolean(v)) => {
382 let v = u128::from(*v);
383
384 Ok(Value::U128(v))
385 }
386
387 (DataType::Float32, Literal::Text(v)) => v
388 .parse::<f32>()
389 .map(Value::F32)
390 .map_err(|_| ValueError::LiteralCastFromTextToFloatFailed(v.to_string()).into()),
391 (DataType::Float32, Literal::Number(v)) => {
392 v.to_f32().map(Value::F32).ok_or_else(|| {
393 ValueError::UnreachableLiteralCastFromNumberToFloat(v.to_string()).into()
394 })
395 }
396 (DataType::Float32, Literal::Boolean(v)) => {
397 let v = if *v { 1.0 } else { 0.0 };
398
399 Ok(Value::F32(v))
400 }
401 (DataType::Float, Literal::Text(v)) => v
402 .parse::<f64>()
403 .map(Value::F64)
404 .map_err(|_| ValueError::LiteralCastFromTextToFloatFailed(v.to_string()).into()),
405 (DataType::Float, Literal::Number(v)) => v.to_f64().map(Value::F64).ok_or_else(|| {
406 ValueError::UnreachableLiteralCastFromNumberToFloat(v.to_string()).into()
407 }),
408 (DataType::Float, Literal::Boolean(v)) => {
409 let v = if *v { 1.0 } else { 0.0 };
410
411 Ok(Value::F64(v))
412 }
413 (DataType::Decimal, Literal::Text(v)) => v
414 .parse::<Decimal>()
415 .map(Value::Decimal)
416 .map_err(|_| ValueError::LiteralCastFromTextToDecimalFailed(v.to_string()).into()),
417 (DataType::Decimal, Literal::Number(v)) => v
418 .to_string()
419 .parse::<Decimal>()
420 .map(Value::Decimal)
421 .map_err(|_| ValueError::LiteralCastFromTextToDecimalFailed(v.to_string()).into()),
422 (DataType::Decimal, Literal::Boolean(v)) => {
423 let v = if *v { Decimal::ONE } else { Decimal::ZERO };
424
425 Ok(Value::Decimal(v))
426 }
427
428 (DataType::Text, Literal::Number(v)) => Ok(Value::Str(v.to_string())),
429 (DataType::Text, Literal::Text(v)) => Ok(Value::Str(v.to_string())),
430 (DataType::Text, Literal::Boolean(v)) => {
431 let v = if *v { "TRUE" } else { "FALSE" };
432
433 Ok(Value::Str(v.to_owned()))
434 }
435 (DataType::Interval, Literal::Text(v)) => {
436 Interval::parse(v.as_ref()).map(Value::Interval)
437 }
438 (DataType::Uuid, Literal::Text(v)) => parse_uuid(v).map(Value::Uuid),
439 (DataType::Boolean, Literal::Null)
440 | (DataType::Int8, Literal::Null)
441 | (DataType::Int16, Literal::Null)
442 | (DataType::Int32, Literal::Null)
443 | (DataType::Int, Literal::Null)
444 | (DataType::Int128, Literal::Null)
445 | (DataType::Uint8, Literal::Null)
446 | (DataType::Uint16, Literal::Null)
447 | (DataType::Uint32, Literal::Null)
448 | (DataType::Uint64, Literal::Null)
449 | (DataType::Uint128, Literal::Null)
450 | (DataType::Float32, Literal::Null)
451 | (DataType::Float, Literal::Null)
452 | (DataType::Decimal, Literal::Null)
453 | (DataType::Text, Literal::Null) => Ok(Value::Null),
454 (DataType::Date, Literal::Text(v)) => parse_date(v)
455 .map(Value::Date)
456 .ok_or_else(|| ValueError::LiteralCastToDateFailed(v.to_string()).into()),
457 (DataType::Time, Literal::Text(v)) => parse_time(v)
458 .map(Value::Time)
459 .ok_or_else(|| ValueError::LiteralCastToTimeFailed(v.to_string()).into()),
460 (DataType::Timestamp, Literal::Text(v)) => parse_timestamp(v)
461 .map(Value::Timestamp)
462 .ok_or_else(|| ValueError::LiteralCastToTimestampFailed(v.to_string()).into()),
463 (DataType::Inet, Literal::Number(v)) => {
464 if let Some(x) = v.to_u32() {
465 Ok(Value::Inet(IpAddr::V4(Ipv4Addr::from(x))))
466 } else if let Some(x) = v.to_u128() {
467 Ok(Value::Inet(IpAddr::V6(Ipv6Addr::from(x))))
468 } else {
469 Err(ValueError::FailedToParseInetString(v.to_string()).into())
470 }
471 }
472 (DataType::Inet, Literal::Text(v)) => IpAddr::from_str(v)
473 .map(Value::Inet)
474 .map_err(|_| ValueError::FailedToParseInetString(v.to_string()).into()),
475 (DataType::Point, Literal::Text(v)) => Point::from_wkt(v)
476 .map(Value::Point)
477 .map_err(|_| ValueError::FailedToParsePoint(v.to_string()).into()),
478 (DataType::Map, Literal::Text(v)) => Value::parse_json_map(v),
479 (DataType::List, Literal::Text(v)) => Value::parse_json_list(v),
480 _ => Err(ValueError::UnimplementedLiteralCast {
481 data_type: data_type.clone(),
482 literal: format!("{:?}", literal),
483 }
484 .into()),
485 }
486 }
487}
488
489#[cfg(test)]
490mod tests {
491 use {
492 super::parse_uuid,
493 crate::data::{Literal, Value},
494 bigdecimal::BigDecimal,
495 chrono::{NaiveDate, NaiveDateTime, NaiveTime},
496 rust_decimal::Decimal,
497 std::{
498 borrow::Cow,
499 cmp::Ordering,
500 net::{IpAddr, Ipv4Addr, Ipv6Addr},
501 str::FromStr,
502 },
503 };
504
505 fn date(year: i32, month: u32, day: u32) -> NaiveDate {
506 chrono::NaiveDate::from_ymd_opt(year, month, day).unwrap()
507 }
508
509 fn date_time(y: i32, m: u32, d: u32, hh: u32, mm: u32, ss: u32, ms: u32) -> NaiveDateTime {
510 chrono::NaiveDate::from_ymd_opt(y, m, d)
511 .unwrap()
512 .and_hms_milli_opt(hh, mm, ss, ms)
513 .unwrap()
514 }
515
516 fn time(hour: u32, min: u32, sec: u32, milli: u32) -> NaiveTime {
517 chrono::NaiveTime::from_hms_milli_opt(hour, min, sec, milli).unwrap()
518 }
519
520 #[test]
521 fn evaluate_eq_with_literal() {
522 macro_rules! num {
523 ($num: expr) => {
524 &Literal::Number(Cow::Owned(BigDecimal::from_str($num).unwrap()))
525 };
526 }
527
528 macro_rules! text {
529 ($text: expr) => {
530 &Literal::Text(Cow::Owned($text.to_owned()))
531 };
532 }
533
534 let uuid_text = "936DA01F9ABD4d9d80C702AF85C822A8";
535 let uuid = parse_uuid(uuid_text).unwrap();
536
537 let bytea = || hex::decode("123456").unwrap();
538 let inet = |v: &str| Value::Inet(IpAddr::from_str(v).unwrap());
539
540 assert!(Value::Bool(true).evaluate_eq_with_literal(&Literal::Boolean(true)));
541 assert!(Value::I8(8).evaluate_eq_with_literal(num!("8")));
542 assert!(Value::I32(32).evaluate_eq_with_literal(num!("32")));
543 assert!(Value::I16(16).evaluate_eq_with_literal(num!("16")));
544 assert!(Value::I32(32).evaluate_eq_with_literal(num!("32")));
545 assert!(Value::I64(64).evaluate_eq_with_literal(num!("64")));
546 assert!(Value::I128(128).evaluate_eq_with_literal(num!("128")));
547 assert!(Value::U8(7).evaluate_eq_with_literal(num!("7")));
548 assert!(Value::U16(64).evaluate_eq_with_literal(num!("64")));
549 assert!(Value::U32(64).evaluate_eq_with_literal(num!("64")));
550 assert!(Value::U64(64).evaluate_eq_with_literal(num!("64")));
551 assert!(Value::U128(64).evaluate_eq_with_literal(num!("64")));
552 assert!(Value::F32(7.123).evaluate_eq_with_literal(num!("7.123")));
553 assert!(Value::F64(7.123).evaluate_eq_with_literal(num!("7.123")));
554 assert!(Value::Str("Hello".to_owned()).evaluate_eq_with_literal(text!("Hello")));
555 assert!(Value::Bytea(bytea()).evaluate_eq_with_literal(&Literal::Bytea(bytea())));
556 assert!(inet("127.0.0.1").evaluate_eq_with_literal(text!("127.0.0.1")));
557 assert!(inet("::1").evaluate_eq_with_literal(text!("::1")));
558 assert!(inet("0.0.0.0").evaluate_eq_with_literal(num!("0")));
559 assert!(!inet("::1").evaluate_eq_with_literal(num!("0")));
560 assert!(inet("::2:4cb0:16ea").evaluate_eq_with_literal(num!("9876543210")));
561 assert!(!inet("::1").evaluate_eq_with_literal(text!("-1")));
562 assert!(!inet("::1").evaluate_eq_with_literal(num!("-1")));
563 assert!(Value::Date(date(2021, 11, 20)).evaluate_eq_with_literal(text!("2021-11-20")));
564 assert!(!Value::Date(date(2021, 11, 20)).evaluate_eq_with_literal(text!("202=abcdef")));
565 assert!(Value::Timestamp(date_time(2021, 11, 20, 10, 0, 0, 0))
566 .evaluate_eq_with_literal(text!("2021-11-20T10:00:00Z")));
567 assert!(!Value::Timestamp(date_time(2021, 11, 20, 10, 0, 0, 0))
568 .evaluate_eq_with_literal(text!("2021-11-Hello")));
569 assert!(Value::Time(time(10, 0, 0, 0)).evaluate_eq_with_literal(text!("10:00:00")));
570 assert!(!Value::Time(time(10, 0, 0, 0)).evaluate_eq_with_literal(text!("FALSE")));
571 assert!(Value::Uuid(uuid).evaluate_eq_with_literal(text!(uuid_text)));
572 }
573
574 #[test]
575 fn evaluate_cmp_with_literal() {
576 let num = |n| Literal::Number(Cow::Owned(BigDecimal::from(n)));
577 let text = |v: &str| Literal::Text(Cow::Owned(v.to_owned()));
578
579 let test = |value: Value, literal, expected| {
580 assert_eq!(value.evaluate_cmp_with_literal(&literal), expected);
581 };
582
583 test(Value::I8(1), num(1), Some(Ordering::Equal));
584 test(Value::I16(1), num(2), Some(Ordering::Less));
585 test(Value::I32(10), num(3), Some(Ordering::Greater));
586 test(Value::I64(10), num(10), Some(Ordering::Equal));
587 test(Value::I128(10), num(10), Some(Ordering::Equal));
588 test(Value::U8(1), num(1), Some(Ordering::Equal));
589 test(Value::U16(1), num(2), Some(Ordering::Less));
590 test(Value::U32(10), num(3), Some(Ordering::Greater));
591 test(Value::U64(10), num(10), Some(Ordering::Equal));
592 test(Value::U128(10), num(10), Some(Ordering::Equal));
593 test(Value::F32(10.0), num(10), Some(Ordering::Equal));
594 test(Value::F64(10.0), num(10), Some(Ordering::Equal));
595 test(
596 Value::Decimal(Decimal::new(215, 2)),
597 num(3),
598 Some(Ordering::Less),
599 );
600 test(
601 Value::Str("Hello".to_owned()),
602 text("Hello"),
603 Some(Ordering::Equal),
604 );
605 test(
606 Value::Date(date(2021, 11, 21)),
607 text("2021-11-21"),
608 Some(Ordering::Equal),
609 );
610 test(
611 Value::Timestamp(date_time(2021, 11, 21, 10, 0, 0, 0)),
612 text("2021-11-21T10:00:00Z"),
613 Some(Ordering::Equal),
614 );
615 test(
616 Value::Time(time(10, 0, 0, 0)),
617 text("10:00:00"),
618 Some(Ordering::Equal),
619 );
620 test(
621 Value::Uuid(parse_uuid("936DA01F9ABD4d9d80C702AF85C822A8").unwrap()),
622 text("936DA01F9ABD4d9d80C702AF85C822A8"),
623 Some(Ordering::Equal),
624 );
625 test(
626 Value::Inet(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))),
627 text("215.87.1.1"),
628 Some(Ordering::Less),
629 );
630 test(
631 Value::Inet(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))),
632 text("215.87.1.1"),
633 Some(Ordering::Less),
634 );
635 test(
636 Value::Inet(IpAddr::V4(Ipv4Addr::new(255, 255, 255, 255))),
637 Literal::Number(Cow::Owned(BigDecimal::new(4294967295u32.into(), 0))),
638 Some(Ordering::Equal),
639 );
640 test(
641 Value::Inet(IpAddr::from_str("::2:4cb0:16ea").unwrap()),
642 Literal::Number(Cow::Owned(BigDecimal::new(9876543210u128.into(), 0))),
643 Some(Ordering::Equal),
644 );
645 test(Value::Null, num(1), None);
646 }
647
648 #[test]
649 fn timestamp_literal() {
650 macro_rules! test (
651 ($timestamp: literal, $result: expr) => {
652 assert_eq!(super::parse_timestamp($timestamp), Some($result));
653 }
654 );
655
656 test!("2022-12-20T10:00:00Z", date_time(2022, 12, 20, 10, 0, 0, 0));
657 test!(
658 "2022-12-20T10:00:00.132Z",
659 date_time(2022, 12, 20, 10, 0, 0, 132)
660 );
661 test!(
662 "2022-12-20T10:00:00.132+09:00",
663 date_time(2022, 12, 20, 1, 0, 0, 132)
664 );
665 test!("2022-11-21", date_time(2022, 11, 21, 0, 0, 0, 0));
666 test!("2022-12-20T10:00:00", date_time(2022, 12, 20, 10, 0, 0, 0));
667 test!("2022-12-20 10:00:00Z", date_time(2022, 12, 20, 10, 0, 0, 0));
668 test!("2022-12-20 10:00:00", date_time(2022, 12, 20, 10, 0, 0, 0));
669 test!(
670 "2022-12-20 10:00:00.987",
671 date_time(2022, 12, 20, 10, 0, 0, 987)
672 );
673 }
674
675 #[test]
676 fn time_literal() {
677 macro_rules! test (
678 ($time: literal, $result: expr) => {
679 assert_eq!(super::parse_time($time), Some($result));
680 }
681 );
682
683 test!("12:00:35", time(12, 0, 35, 0));
684 test!("12:00:35.917", time(12, 0, 35, 917));
685 test!("AM 08:00", time(8, 0, 0, 0));
686 test!("PM 8:00", time(20, 0, 0, 0));
687 test!("AM 09:30:37", time(9, 30, 37, 0));
688 test!("PM 3:30:37", time(15, 30, 37, 0));
689 test!("PM 03:30:37.123", time(15, 30, 37, 123));
690 test!("AM 9:30:37.917", time(9, 30, 37, 917));
691 test!("08:00 AM", time(8, 0, 0, 0));
692 test!("8:00 PM", time(20, 0, 0, 0));
693 test!("09:30:37 AM", time(9, 30, 37, 0));
694 test!("3:30:37 PM", time(15, 30, 37, 0));
695 test!("03:30:37.123 PM", time(15, 30, 37, 123));
696 test!("9:30:37.917 AM", time(9, 30, 37, 917));
697 }
698
699 #[test]
700 fn try_from_literal() {
701 use {
702 crate::{ast::DataType, data::ValueError},
703 chrono::NaiveDate,
704 rust_decimal::Decimal,
705 std::{borrow::Cow, str::FromStr},
706 };
707
708 macro_rules! num {
709 ($num: expr) => {
710 Literal::Number(Cow::Owned(BigDecimal::from_str($num).unwrap()))
711 };
712 }
713
714 macro_rules! text {
715 ($text: expr) => {
716 Literal::Text(Cow::Owned($text.to_owned()))
717 };
718 }
719
720 macro_rules! test {
721 ($to: expr, $from: expr, $expected: expr) => {
722 assert_eq!(Value::try_from_literal(&$to, &$from), Ok($expected));
723 };
724 }
725
726 let bytea = |v| hex::decode(v).unwrap();
727 let inet = |v| IpAddr::from_str(v).unwrap();
728
729 test!(DataType::Boolean, Literal::Boolean(true), Value::Bool(true));
730 test!(DataType::Int, num!("123456789"), Value::I64(123456789));
731 test!(DataType::Int8, num!("64"), Value::I8(64));
732 test!(DataType::Int16, num!("64"), Value::I16(64));
733 test!(DataType::Int32, num!("64"), Value::I32(64));
734 test!(DataType::Int, num!("64"), Value::I64(64));
735 test!(DataType::Int128, num!("64"), Value::I128(64));
736 test!(DataType::Uint8, num!("8"), Value::U8(8));
737 test!(DataType::Uint16, num!("64"), Value::U16(64));
738 test!(DataType::Uint32, num!("64"), Value::U32(64));
739 test!(DataType::Uint64, num!("64"), Value::U64(64));
740 test!(DataType::Uint128, num!("64"), Value::U128(64));
741 test!(
742 DataType::Float32,
743 num!("123456789"),
744 Value::F32(123456789.0_f32)
745 );
746 test!(DataType::Float, num!("123456789"), Value::F64(123456789.0));
747 test!(
748 DataType::Text,
749 text!("Good!"),
750 Value::Str("Good!".to_owned())
751 );
752 test!(
753 DataType::Bytea,
754 Literal::Bytea(bytea("1234")),
755 Value::Bytea(bytea("1234"))
756 );
757 test!(DataType::Bytea, text!("1234"), Value::Bytea(bytea("1234")));
758 assert_eq!(
759 Value::try_from_literal(&DataType::Bytea, &text!("123")),
760 Err(ValueError::FailedToParseHexString("123".to_owned()).into())
761 );
762 test!(DataType::Inet, text!("::1"), Value::Inet(inet("::1")));
763 test!(
764 DataType::Inet,
765 num!("4294967295"),
766 Value::Inet(inet("255.255.255.255"))
767 );
768 test!(
769 DataType::Inet,
770 num!("9876543210"),
771 Value::Inet(inet("::2:4cb0:16ea"))
772 );
773 test!(
774 DataType::Inet,
775 num!("9876543210"),
776 Value::Inet(inet("::2:4cb0:16ea"))
777 );
778 assert_eq!(
779 Value::try_from_literal(&DataType::Inet, &text!("123")),
780 Err(ValueError::FailedToParseInetString("123".to_owned()).into())
781 );
782 test!(
783 DataType::Date,
784 text!("2015-09-05"),
785 Value::Date(NaiveDate::from_ymd_opt(2015, 9, 5).unwrap())
786 );
787 test!(
788 DataType::Timestamp,
789 text!("2022-12-20 10:00:00.987"),
790 Value::Timestamp(date_time(2022, 12, 20, 10, 0, 0, 987))
791 );
792 test!(
793 DataType::Time,
794 text!("12:00:35"),
795 Value::Time(chrono::NaiveTime::from_hms_milli_opt(12, 0, 35, 0).unwrap())
796 );
797 test!(
798 DataType::Uuid,
799 text!("936DA01F9ABD4d9d80C702AF85C822A8"),
800 Value::Uuid(195965723427462096757863453463987888808)
801 );
802 test!(
803 DataType::Uuid,
804 Literal::Bytea(bytea("936DA01F9ABD4d9d80C702AF85C822A8")),
805 Value::Uuid(195965723427462096757863453463987888808)
806 );
807
808 assert_eq!(
809 Value::try_from_literal(
810 &DataType::Map,
811 &text!(
812 r#"{
813 "name": "John Doe",
814 "age": 43
815 }"#
816 )
817 ),
818 Value::parse_json_map(
819 r#"{
820 "name": "John Doe",
821 "age": 43
822 }"#
823 )
824 );
825 assert_eq!(
826 Value::try_from_literal(
827 &DataType::List,
828 &text!(
829 r#"[
830 "+44 1234567",
831 "+44 2345678"
832 ]"#
833 )
834 ),
835 Value::parse_json_list(
836 r#"[
837 "+44 1234567",
838 "+44 2345678"
839 ]"#
840 )
841 );
842 test!(
843 DataType::Decimal,
844 num!("200"),
845 Value::Decimal(Decimal::new(200, 0))
846 );
847 }
848
849 #[test]
850 fn try_from() {
851 use std::{borrow::Cow, str::FromStr};
852
853 macro_rules! text {
854 ($text: expr) => {
855 Literal::Text(Cow::Owned($text.to_owned()))
856 };
857 }
858
859 macro_rules! num {
860 ($num: expr) => {
861 &Literal::Number(Cow::Owned(BigDecimal::from_str($num).unwrap()))
862 };
863 }
864
865 let bytea = |v| hex::decode(v).unwrap();
866
867 macro_rules! test {
868 ($from: expr, $expected: expr) => {
869 assert!(Value::try_from($from).unwrap().evaluate_eq(&$expected));
870 };
871 }
872
873 test!(text!("hello"), Value::Str("hello".to_owned()));
874 test!(&text!("hallo"), Value::Str("hallo".to_owned()));
875 test!(Literal::Bytea(bytea("1234")), Value::Bytea(bytea("1234")));
876 test!(&Literal::Bytea(bytea("1234")), Value::Bytea(bytea("1234")));
877 test!(num!("1234567890"), Value::I64(1234567890));
878 test!(num!("1.0"), Value::F32(1.0_f32));
879 test!(num!("1.0"), Value::F64(1.0));
880 test!(&Literal::Boolean(false), Value::Bool(false));
881 assert!(matches!(Value::try_from(&Literal::Null), Ok(Value::Null)))
882 }
883
884 #[test]
885 fn try_cast_from_literal() {
886 use {
887 crate::{ast::DataType, data::Interval as I},
888 chrono::NaiveDate,
889 std::{borrow::Cow, str::FromStr},
890 };
891
892 macro_rules! text {
893 ($text: expr) => {
894 Literal::Text(Cow::Owned($text.to_owned()))
895 };
896 }
897
898 macro_rules! num {
899 ($num: expr) => {
900 &Literal::Number(Cow::Owned(BigDecimal::from_str($num).unwrap()))
901 };
902 }
903
904 macro_rules! test {
905 ($to: expr, $from: expr, $expected: expr) => {
906 let actual = Value::try_cast_from_literal(&$to, &$from);
907
908 assert_eq!(actual, Ok($expected))
909 };
910 }
911
912 macro_rules! test_null {
913 ($to: expr, $from: expr) => {
914 assert!(matches!(
915 Value::try_cast_from_literal(&$to, &$from),
916 Ok(Value::Null)
917 ))
918 };
919 }
920
921 let timestamp = |y, m, d, hh, mm, ss, ms| {
922 chrono::NaiveDate::from_ymd_opt(y, m, d)
923 .unwrap()
924 .and_hms_milli_opt(hh, mm, ss, ms)
925 .unwrap()
926 };
927
928 test!(
929 DataType::Boolean,
930 Literal::Boolean(false),
931 Value::Bool(false)
932 );
933 test!(DataType::Boolean, text!("false"), Value::Bool(false));
934 test!(DataType::Boolean, text!("true"), Value::Bool(true));
935 test!(DataType::Boolean, num!("0"), Value::Bool(false));
936 test!(DataType::Boolean, num!("1"), Value::Bool(true));
937
938 test!(DataType::Int8, text!("127"), Value::I8(127));
939 test!(DataType::Int8, num!("125"), Value::I8(125));
940 test!(DataType::Int8, Literal::Boolean(true), Value::I8(1));
941 test!(DataType::Int8, Literal::Boolean(false), Value::I8(0));
942
943 test!(DataType::Int16, text!("127"), Value::I16(127));
944 test!(DataType::Int16, num!("125"), Value::I16(125));
945 test!(DataType::Int16, Literal::Boolean(true), Value::I16(1));
946 test!(DataType::Int16, Literal::Boolean(false), Value::I16(0));
947
948 test!(DataType::Int32, text!("127"), Value::I32(127));
949 test!(DataType::Int32, num!("125"), Value::I32(125));
950 test!(DataType::Int32, Literal::Boolean(true), Value::I32(1));
951 test!(DataType::Int32, Literal::Boolean(false), Value::I32(0));
952
953 test!(DataType::Int, text!("1234567890"), Value::I64(1234567890));
954 test!(DataType::Int, num!("1234567890"), Value::I64(1234567890));
955 test!(DataType::Int, Literal::Boolean(true), Value::I64(1));
956 test!(DataType::Int, Literal::Boolean(false), Value::I64(0));
957 test!(DataType::Int128, text!("127"), Value::I128(127));
958 test!(DataType::Int128, num!("125"), Value::I128(125));
959 test!(DataType::Int128, Literal::Boolean(true), Value::I128(1));
960 test!(DataType::Int128, Literal::Boolean(false), Value::I128(0));
961
962 test!(DataType::Uint8, text!("127"), Value::U8(127));
963 test!(DataType::Uint8, num!("125"), Value::U8(125));
964 test!(DataType::Uint8, Literal::Boolean(true), Value::U8(1));
965 test!(DataType::Uint8, Literal::Boolean(false), Value::U8(0));
966
967 test!(DataType::Uint16, text!("127"), Value::U16(127));
968 test!(DataType::Uint16, num!("125"), Value::U16(125));
969 test!(DataType::Uint16, Literal::Boolean(true), Value::U16(1));
970 test!(DataType::Uint16, Literal::Boolean(false), Value::U16(0));
971
972 test!(DataType::Uint32, text!("127"), Value::U32(127));
973 test!(DataType::Uint32, num!("125"), Value::U32(125));
974 test!(DataType::Uint32, Literal::Boolean(true), Value::U32(1));
975 test!(DataType::Uint32, Literal::Boolean(false), Value::U32(0));
976
977 test!(DataType::Uint64, text!("127"), Value::U64(127));
978 test!(DataType::Uint64, num!("125"), Value::U64(125));
979 test!(DataType::Uint64, Literal::Boolean(true), Value::U64(1));
980 test!(DataType::Uint64, Literal::Boolean(false), Value::U64(0));
981
982 test!(DataType::Uint128, text!("127"), Value::U128(127));
983 test!(DataType::Uint128, num!("125"), Value::U128(125));
984 test!(DataType::Uint128, Literal::Boolean(true), Value::U128(1));
985 test!(DataType::Uint128, Literal::Boolean(false), Value::U128(0));
986
987 test!(
988 DataType::Float32,
989 text!("12345.67"),
990 Value::F32(12345.67_f32)
991 );
992 test!(
993 DataType::Float32,
994 num!("123456.78"),
995 Value::F32(123456.78_f32)
996 );
997 test!(
998 DataType::Float32,
999 Literal::Boolean(true),
1000 Value::F32(1.0_f32)
1001 );
1002 test!(
1003 DataType::Float32,
1004 Literal::Boolean(false),
1005 Value::F32(0.0_f32)
1006 );
1007
1008 test!(DataType::Float, text!("12345.6789"), Value::F64(12345.6789));
1009 test!(DataType::Float, num!("123456.789"), Value::F64(123456.789));
1010 test!(DataType::Float, Literal::Boolean(true), Value::F64(1.0));
1011 test!(DataType::Float, Literal::Boolean(false), Value::F64(0.0));
1012 test!(
1013 DataType::Text,
1014 num!("1234567890"),
1015 Value::Str("1234567890".to_owned())
1016 );
1017 test!(DataType::Text, text!("Cow"), Value::Str("Cow".to_owned()));
1018 test!(
1019 DataType::Text,
1020 Literal::Boolean(true),
1021 Value::Str("TRUE".to_owned())
1022 );
1023 test!(
1024 DataType::Text,
1025 Literal::Boolean(false),
1026 Value::Str("FALSE".to_owned())
1027 );
1028 test!(
1029 DataType::Interval,
1030 text!("'+22-10' YEAR TO MONTH"),
1031 Value::Interval(I::Month(274))
1032 );
1033 test!(
1034 DataType::Uuid,
1035 text!("936DA01F9ABD4d9d80C702AF85C822A8"),
1036 Value::Uuid(195965723427462096757863453463987888808)
1037 );
1038 test_null!(DataType::Boolean, Literal::Null);
1039 test_null!(DataType::Int, Literal::Null);
1040 test_null!(DataType::Int8, Literal::Null);
1041 test_null!(DataType::Uint8, Literal::Null);
1042 test_null!(DataType::Uint16, Literal::Null);
1043 test_null!(DataType::Uint32, Literal::Null);
1044 test_null!(DataType::Uint64, Literal::Null);
1045 test_null!(DataType::Uint128, Literal::Null);
1046 test_null!(DataType::Float32, Literal::Null);
1047 test_null!(DataType::Float, Literal::Null);
1048 test_null!(DataType::Text, Literal::Null);
1049 test!(
1050 DataType::Date,
1051 text!("2015-09-05"),
1052 Value::Date(NaiveDate::from_ymd_opt(2015, 9, 5).unwrap())
1053 );
1054 test!(
1055 DataType::Time,
1056 text!("12:00:35"),
1057 Value::Time(chrono::NaiveTime::from_hms_milli_opt(12, 0, 35, 0).unwrap())
1058 );
1059 test!(
1060 DataType::Timestamp,
1061 text!("2022-12-20 10:00:00.987"),
1062 Value::Timestamp(timestamp(2022, 12, 20, 10, 0, 0, 987))
1063 );
1064 test!(
1065 DataType::Inet,
1066 num!("1234567890"),
1067 Value::Inet(IpAddr::from(Ipv4Addr::from(1234567890)))
1068 );
1069 test!(
1070 DataType::Inet,
1071 num!("91234567890"),
1072 Value::Inet(IpAddr::from(Ipv6Addr::from(91234567890)))
1073 );
1074 test!(
1075 DataType::Inet,
1076 text!("::1"),
1077 Value::Inet(IpAddr::from_str("::1").unwrap())
1078 );
1079 test!(
1080 DataType::Map,
1081 text!(r#"{ "a": 1 }"#),
1082 Value::parse_json_map(r#"{ "a": 1 }"#).unwrap()
1083 );
1084 test!(
1085 DataType::List,
1086 text!(r#"[ 1, 2, 3 ]"#),
1087 Value::parse_json_list(r#"[ 1, 2, 3 ]"#).unwrap()
1088 );
1089 }
1090}