1use {
2 super::{BigDecimalExt, StringExt},
3 crate::{
4 ast::{AstLiteral, BinaryOperator, ToSql},
5 result::{Error, Result},
6 },
7 Literal::*,
8 bigdecimal::BigDecimal,
9 serde::Serialize,
10 std::{borrow::Cow, cmp::Ordering, convert::TryFrom, fmt::Debug},
11 thiserror::Error,
12 utils::Tribool,
13};
14
15#[derive(Error, Serialize, Debug, PartialEq, Eq)]
16pub enum LiteralError {
17 #[error("unsupported literal binary operation {} {} {}", .left, .op.to_sql(), .right)]
18 UnsupportedBinaryOperation {
19 left: String,
20 op: BinaryOperator,
21 right: String,
22 },
23
24 #[error("a operand '{0}' is not integer type")]
25 BitwiseNonIntegerOperand(String),
26
27 #[error("given operands is not Number literal type")]
28 BitwiseNonNumberLiteral,
29
30 #[error("overflow occured while running bitwise operation")]
31 BitwiseOperationOverflow,
32
33 #[error("impossible conversion from {0} to {1} type")]
34 ImpossibleConversion(String, String),
35
36 #[error("the divisor should not be zero")]
37 DivisorShouldNotBeZero,
38
39 #[error("literal unary operation on non-numeric")]
40 UnaryOperationOnNonNumeric,
41
42 #[error("unreachable literal binary arithmetic")]
43 UnreachableBinaryArithmetic,
44
45 #[error("unreachable literal unary operation")]
46 UnreachableUnaryOperation,
47
48 #[error("failed to decode hex string: {0}")]
49 FailedToDecodeHexString(String),
50
51 #[error("operator doesn't exist: {base:?} {case} {pattern:?}", case = if *case_sensitive { "LIKE" } else { "ILIKE" })]
52 LikeOnNonString {
53 base: String,
54 pattern: String,
55 case_sensitive: bool,
56 },
57}
58
59#[derive(Clone, Debug, PartialEq)]
60pub enum Literal<'a> {
61 Boolean(bool),
62 Number(Cow<'a, BigDecimal>),
63 Text(Cow<'a, str>),
64 Bytea(Vec<u8>),
65 Null,
66}
67
68impl<'a> TryFrom<&'a AstLiteral> for Literal<'a> {
69 type Error = Error;
70
71 fn try_from(ast_literal: &'a AstLiteral) -> Result<Self> {
72 let literal = match ast_literal {
73 AstLiteral::Boolean(v) => Boolean(*v),
74 AstLiteral::Number(v) => Number(Cow::Borrowed(v)),
75 AstLiteral::QuotedString(v) => Text(Cow::Borrowed(v)),
76 AstLiteral::HexString(v) => {
77 Bytea(hex::decode(v).map_err(|_| LiteralError::FailedToDecodeHexString(v.clone()))?)
78 }
79 AstLiteral::Null => Null,
80 };
81
82 Ok(literal)
83 }
84}
85
86fn unsupported_binary_op(left: &Literal, op: BinaryOperator, right: &Literal) -> LiteralError {
87 LiteralError::UnsupportedBinaryOperation {
88 left: format!("{left:?}"),
89 op,
90 right: format!("{right:?}"),
91 }
92}
93
94impl<'a> Literal<'a> {
95 pub fn evaluate_eq(&self, other: &Literal<'_>) -> Tribool {
96 match (self, other) {
97 (Null, _) | (_, Null) => Tribool::Null,
98 _ => Tribool::from(self == other),
99 }
100 }
101
102 pub fn evaluate_cmp(&self, other: &Literal<'a>) -> Option<Ordering> {
103 match (self, other) {
104 (Boolean(l), Boolean(r)) => Some(l.cmp(r)),
105 (Number(l), Number(r)) => Some(l.cmp(r)),
106 (Text(l), Text(r)) => Some(l.cmp(r)),
107 (Bytea(l), Bytea(r)) => Some(l.cmp(r)),
108 _ => None,
109 }
110 }
111
112 pub fn unary_plus(&self) -> Result<Self> {
113 match self {
114 Number(v) => Ok(Number(v.clone())),
115 Null => Ok(Null),
116 _ => Err(LiteralError::UnaryOperationOnNonNumeric.into()),
117 }
118 }
119
120 pub fn unary_minus(&self) -> Result<Self> {
121 match self {
122 Number(v) => Ok(Number(Cow::Owned(-v.as_ref()))),
123 Null => Ok(Null),
124 _ => Err(LiteralError::UnaryOperationOnNonNumeric.into()),
125 }
126 }
127
128 pub fn concat(self, other: Literal<'_>) -> Self {
129 let convert = |literal| match literal {
130 Boolean(v) => Some(if v {
131 "TRUE".to_owned()
132 } else {
133 "FALSE".to_owned()
134 }),
135 Number(v) => Some(v.to_string()),
136 Text(v) => Some(v.into_owned()),
137 Bytea(_) | Null => None,
138 };
139
140 match (convert(self), convert(other)) {
141 (Some(l), Some(r)) => Literal::Text(Cow::Owned(l + &r)),
142 _ => Literal::Null,
143 }
144 }
145
146 pub fn add(&self, other: &Literal<'a>) -> Result<Literal<'static>> {
147 match (self, other) {
148 (Number(l), Number(r)) => Ok(Number(Cow::Owned(l.as_ref() + r.as_ref()))),
149 (Null, Number(_)) | (Number(_), Null) | (Null, Null) => Ok(Literal::Null),
150 _ => Err(unsupported_binary_op(self, BinaryOperator::Plus, other).into()),
151 }
152 }
153
154 pub fn subtract(&self, other: &Literal<'a>) -> Result<Literal<'static>> {
155 match (self, other) {
156 (Number(l), Number(r)) => Ok(Number(Cow::Owned(l.as_ref() - r.as_ref()))),
157 (Null, Number(_)) | (Number(_), Null) | (Null, Null) => Ok(Literal::Null),
158 _ => Err(unsupported_binary_op(self, BinaryOperator::Minus, other).into()),
159 }
160 }
161
162 pub fn multiply(&self, other: &Literal<'a>) -> Result<Literal<'static>> {
163 match (self, other) {
164 (Number(l), Number(r)) => Ok(Number(Cow::Owned(l.as_ref() * r.as_ref()))),
165 (Null, Number(_)) | (Number(_), Null) | (Null, Null) => Ok(Literal::Null),
166 _ => Err(unsupported_binary_op(self, BinaryOperator::Multiply, other).into()),
167 }
168 }
169
170 pub fn divide(&self, other: &Literal<'a>) -> Result<Literal<'static>> {
171 match (self, other) {
172 (Number(l), Number(r)) => {
173 if *r.as_ref() == 0.into() {
174 Err(LiteralError::DivisorShouldNotBeZero.into())
175 } else {
176 Ok(Number(Cow::Owned(l.as_ref() / r.as_ref())))
177 }
178 }
179 (Null, Number(_)) | (Number(_), Null) | (Null, Null) => Ok(Literal::Null),
180 _ => Err(unsupported_binary_op(self, BinaryOperator::Divide, other).into()),
181 }
182 }
183
184 pub fn bitwise_and(&self, other: &Literal<'a>) -> Result<Literal<'static>> {
185 match (self, other) {
186 (Number(l), Number(r)) => match (l.to_i64(), r.to_i64()) {
187 (Some(l), Some(r)) => Ok(Number(Cow::Owned(BigDecimal::from(l & r)))),
188 _ => Err(LiteralError::UnsupportedBinaryOperation {
189 left: format!("{self:?}"),
190 op: BinaryOperator::BitwiseAnd,
191 right: format!("{other:?}"),
192 }
193 .into()),
194 },
195 (Null, Number(_)) | (Number(_), Null) | (Null, Null) => Ok(Literal::Null),
196 _ => Err(unsupported_binary_op(self, BinaryOperator::BitwiseAnd, other).into()),
197 }
198 }
199
200 pub fn modulo(&self, other: &Literal<'a>) -> Result<Literal<'static>> {
201 match (self, other) {
202 (Number(l), Number(r)) => {
203 if *r.as_ref() == 0.into() {
204 Err(LiteralError::DivisorShouldNotBeZero.into())
205 } else {
206 Ok(Number(Cow::Owned(l.as_ref() % r.as_ref())))
207 }
208 }
209 (Null, Number(_)) | (Number(_), Null) | (Null, Null) => Ok(Literal::Null),
210 _ => Err(unsupported_binary_op(self, BinaryOperator::Modulo, other).into()),
211 }
212 }
213
214 pub fn bitwise_shift_left(&self, other: &Literal<'a>) -> Result<Literal<'static>> {
215 match (self, other) {
216 (Number(l), Number(r)) => {
217 let l = l
218 .to_i64()
219 .ok_or(LiteralError::BitwiseNonIntegerOperand(l.to_string()))?;
220 if !r.is_integer_representation() {
221 return Err(LiteralError::BitwiseNonIntegerOperand(r.to_string()).into());
222 }
223 let r = r.to_u32().ok_or(LiteralError::ImpossibleConversion(
224 r.to_string(),
225 "u32".to_owned(),
226 ))?;
227 let res = l
228 .checked_shl(r)
229 .ok_or(LiteralError::BitwiseOperationOverflow)?;
230 Ok(Number(Cow::Owned(BigDecimal::from(res))))
231 }
232 (Null, Number(_)) | (Number(_), Null) | (Null, Null) => Ok(Literal::Null),
233 _ => Err(LiteralError::BitwiseNonNumberLiteral.into()),
234 }
235 }
236
237 pub fn bitwise_shift_right(&self, other: &Literal<'a>) -> Result<Literal<'static>> {
238 match (self, other) {
239 (Number(l), Number(r)) => {
240 let l = l
241 .to_i64()
242 .ok_or(LiteralError::BitwiseNonIntegerOperand(l.to_string()))?;
243 if !r.is_integer_representation() {
244 return Err(LiteralError::BitwiseNonIntegerOperand(r.to_string()).into());
245 }
246 let r = r.to_u32().ok_or(LiteralError::ImpossibleConversion(
247 r.to_string(),
248 "u32".to_owned(),
249 ))?;
250 let res = l
251 .checked_shr(r)
252 .ok_or(LiteralError::BitwiseOperationOverflow)?;
253 Ok(Number(Cow::Owned(BigDecimal::from(res))))
254 }
255 (Null, Number(_)) | (Number(_), Null) | (Null, Null) => Ok(Literal::Null),
256 _ => Err(LiteralError::BitwiseNonNumberLiteral.into()),
257 }
258 }
259
260 pub fn like(&self, other: &Literal<'a>, case_sensitive: bool) -> Result<Self> {
261 match (self, other) {
262 (Text(l), Text(r)) => l.like(r, case_sensitive).map(Boolean),
263 _ => Err(LiteralError::LikeOnNonString {
264 base: format!("{self:?}"),
265 pattern: format!("{other:?}"),
266 case_sensitive,
267 }
268 .into()),
269 }
270 }
271}
272
273#[cfg(test)]
274mod tests {
275 use utils::Tribool;
276 use {
277 super::Literal::*,
278 crate::ast::BinaryOperator,
279 bigdecimal::BigDecimal,
280 std::{borrow::Cow, str::FromStr},
281 };
282
283 #[test]
284 fn try_from_ast_literal() {
285 use {
286 super::{Literal, LiteralError},
287 crate::{ast::AstLiteral, result::Result},
288 };
289
290 fn test(ast_literal: AstLiteral, literal: Result<Literal>) {
291 assert_eq!((&ast_literal).try_into(), literal);
292 }
293
294 test(AstLiteral::Boolean(true), Ok(Boolean(true)));
295 test(
296 AstLiteral::Number(BigDecimal::from(123)),
297 Ok(Number(Cow::Borrowed(&BigDecimal::from(123)))),
298 );
299 test(
300 AstLiteral::QuotedString("abc".to_owned()),
301 Ok(Text(Cow::Borrowed("abc"))),
302 );
303 test(
304 AstLiteral::HexString("1A2B".to_owned()),
305 Ok(Bytea(hex::decode("1A2B").unwrap())),
306 );
307 test(
308 AstLiteral::HexString("!*@Q".to_owned()),
309 Err(LiteralError::FailedToDecodeHexString("!*@Q".to_owned()).into()),
310 );
311 assert_eq!(Literal::try_from(&AstLiteral::Null).unwrap(), Null);
312 }
313
314 #[test]
315 fn arithmetic() {
316 use crate::data::LiteralError;
317
318 let num = |n: i32| Number(Cow::Owned(BigDecimal::from(n)));
319
320 assert_eq!(Null.add(&num(1)), Ok(Null));
321 assert_eq!(num(1).add(&Null), Ok(Null));
322
323 assert_eq!(Null.subtract(&num(2)), Ok(Null));
325 assert_eq!(num(2).subtract(&Null), Ok(Null));
326 assert_eq!(Null.subtract(&Null), Ok(Null));
327 assert_eq!(
328 Boolean(true).subtract(&num(3)),
329 Err(LiteralError::UnsupportedBinaryOperation {
330 left: format!("{:?}", Boolean(true)),
331 op: BinaryOperator::Minus,
332 right: format!("{:?}", num(3)),
333 }
334 .into()),
335 );
336
337 assert_eq!(Null.multiply(&num(2)), Ok(Null));
339 assert_eq!(num(2).multiply(&Null), Ok(Null));
340 assert_eq!(Null.multiply(&Null), Ok(Null));
341 assert_eq!(
342 Boolean(true).multiply(&num(3)),
343 Err(LiteralError::UnsupportedBinaryOperation {
344 left: format!("{:?}", Boolean(true)),
345 op: BinaryOperator::Multiply,
346 right: format!("{:?}", num(3))
347 }
348 .into()),
349 );
350
351 assert_eq!(num(2).unary_plus(), Ok(num(2)));
352 assert_eq!(Null.unary_plus(), Ok(Null));
353 assert_eq!(num(1).unary_minus(), Ok(num(-1)));
354 assert_eq!(Null.unary_minus(), Ok(Null));
355 }
356
357 #[test]
358 fn bitwise_shift_left() {
359 use crate::data::LiteralError;
360
361 let num = |n: i32| Number(Cow::Owned(BigDecimal::from(n)));
362 macro_rules! num {
363 ($num: expr) => {
364 Number(Cow::Owned(BigDecimal::from_str($num).unwrap()))
365 };
366 }
367
368 assert_eq!(
369 num(1).bitwise_shift_left(&num(2)),
370 Ok(Number(Cow::Borrowed(&BigDecimal::from(4))))
371 );
372
373 assert_eq!(
374 num(1).bitwise_shift_left(&num(65)),
375 Err(LiteralError::BitwiseOperationOverflow.into())
376 );
377
378 assert_eq!(num(2).bitwise_shift_left(&Null), Ok(Null));
379 assert_eq!(Null.bitwise_shift_left(&num(2)), Ok(Null));
380 assert_eq!(Null.bitwise_shift_left(&Null), Ok(Null));
381
382 assert_eq!(
383 Boolean(true).bitwise_shift_left(&num(2)),
384 Err(LiteralError::BitwiseNonNumberLiteral.into())
385 );
386 assert_eq!(
387 num(1).bitwise_shift_left(&num(-1)),
388 Err(LiteralError::ImpossibleConversion("-1".to_owned(), "u32".to_owned()).into())
389 );
390 assert_eq!(
391 num!("1.1").bitwise_shift_left(&num(2)),
392 Err(LiteralError::BitwiseNonIntegerOperand("1.1".to_owned()).into())
393 );
394 assert_eq!(
395 num(1).bitwise_shift_left(&num!("2.1")),
396 Err(LiteralError::BitwiseNonIntegerOperand("2.1".to_owned()).into())
397 );
398 }
399
400 #[test]
401 fn bitwise_shift_right() {
402 use crate::data::LiteralError;
403
404 let num = |n: i32| Number(Cow::Owned(BigDecimal::from(n)));
405 macro_rules! num {
406 ($num: expr) => {
407 Number(Cow::Owned(BigDecimal::from_str($num).unwrap()))
408 };
409 }
410
411 assert_eq!(
412 num(4).bitwise_shift_right(&num(2)),
413 Ok(Number(Cow::Borrowed(&BigDecimal::from(1))))
414 );
415
416 assert_eq!(
417 num(1).bitwise_shift_right(&num(65)),
418 Err(LiteralError::BitwiseOperationOverflow.into())
419 );
420
421 assert_eq!(num(2).bitwise_shift_right(&Null), Ok(Null));
422 assert_eq!(Null.bitwise_shift_right(&num(2)), Ok(Null));
423 assert_eq!(Null.bitwise_shift_right(&Null), Ok(Null));
424
425 assert_eq!(
426 Boolean(true).bitwise_shift_right(&num(2)),
427 Err(LiteralError::BitwiseNonNumberLiteral.into())
428 );
429 assert_eq!(
430 num(1).bitwise_shift_right(&num(-1)),
431 Err(LiteralError::ImpossibleConversion("-1".to_owned(), "u32".to_owned()).into())
432 );
433 assert_eq!(
434 num!("1.1").bitwise_shift_right(&num(2)),
435 Err(LiteralError::BitwiseNonIntegerOperand("1.1".to_owned()).into())
436 );
437 assert_eq!(
438 num(1).bitwise_shift_right(&num!("2.1")),
439 Err(LiteralError::BitwiseNonIntegerOperand("2.1".to_owned()).into())
440 );
441 }
442
443 #[test]
444 fn concat() {
445 macro_rules! text {
446 ($text: expr) => {
447 Text(Cow::Owned($text.to_owned()))
448 };
449 }
450
451 let num = || Number(Cow::Owned(BigDecimal::from(123)));
452 let text = || text!("Foo");
453
454 assert_eq!(Boolean(true).concat(num()), text!("TRUE123"));
455 assert_eq!(Boolean(false).concat(text()), text!("FALSEFoo"));
456 assert_eq!(num().concat(num()), text!("123123"));
457 assert_eq!(text().concat(num()), text!("Foo123"));
458 assert_eq!(text().concat(Null), Null);
459 assert_eq!(Null.concat(Boolean(true)), Null);
460 assert_eq!(Null.concat(Null), Null);
461 }
462
463 #[test]
464 fn div_mod() {
465 use crate::data::LiteralError;
466
467 macro_rules! num {
468 ($num: expr) => {
469 Number(Cow::Owned(BigDecimal::from_str($num).unwrap()))
470 };
471 }
472
473 let num_divisor = |x| Number(Cow::Owned(BigDecimal::from_str(x).unwrap()));
474
475 assert_eq!(num!("12").divide(&num_divisor("2")).unwrap(), num!("6"));
477 assert_eq!(num!("12").divide(&num_divisor("2.0")).unwrap(), num!("6"));
478 assert_eq!(num!("12.0").divide(&num_divisor("2")).unwrap(), num!("6"));
479 assert_eq!(num!("12.0").divide(&num_divisor("2.0")).unwrap(), num!("6"));
480 assert_eq!(num!("12").divide(&Null).unwrap(), Null);
481 assert_eq!(num!("12.5").divide(&Null).unwrap(), Null);
482 assert_eq!(Null.divide(&num_divisor("2")).unwrap(), Null);
483 assert_eq!(Null.divide(&num_divisor("2.5")).unwrap(), Null);
484 assert_eq!(Null.divide(&Null).unwrap(), Null);
485 assert_eq!(
486 Boolean(true).divide(&num!("3")),
487 Err(LiteralError::UnsupportedBinaryOperation {
488 left: format!("{:?}", Boolean(true)),
489 op: BinaryOperator::Divide,
490 right: format!("{:?}", num!("3"))
491 }
492 .into()),
493 );
494
495 assert_eq!(num!("12").modulo(&num_divisor("2")).unwrap(), num!("0"));
497 assert_eq!(num!("12").modulo(&num_divisor("2.0")).unwrap(), num!("0"));
498 assert_eq!(num!("12.0").modulo(&num_divisor("2")).unwrap(), num!("0"));
499 assert_eq!(num!("12.0").modulo(&num_divisor("2.0")).unwrap(), num!("0"));
500 assert_eq!(num!("12").modulo(&Null).unwrap(), Null);
501 assert_eq!(Null.modulo(&num_divisor("2")).unwrap(), Null);
502 assert_eq!(Null.modulo(&Null).unwrap(), Null);
503
504 let text = Text(Cow::Owned("some".to_owned()));
505 assert_eq!(
506 num!("12").modulo(&text),
507 Err(LiteralError::UnsupportedBinaryOperation {
508 left: format!("{:?}", num!("12")),
509 op: BinaryOperator::Modulo,
510 right: format!("{text:?}")
511 }
512 .into())
513 )
514 }
515
516 #[test]
517 fn evaluate_eq() {
518 macro_rules! text {
519 ($text: expr) => {
520 Text(Cow::Owned($text.to_owned()))
521 };
522 }
523 macro_rules! num {
524 ($num: expr) => {
525 Number(Cow::Owned(BigDecimal::from_str($num).unwrap()))
526 };
527 }
528 macro_rules! bytea {
529 ($val: expr) => {
530 Bytea(hex::decode($val).unwrap())
531 };
532 }
533
534 assert_eq!(Tribool::True, Boolean(true).evaluate_eq(&Boolean(true)));
535 assert_eq!(Tribool::False, Boolean(true).evaluate_eq(&Boolean(false)));
536 assert_eq!(Tribool::True, num!("123").evaluate_eq(&num!("123")));
538 assert_eq!(Tribool::True, num!("12.0").evaluate_eq(&num!("12.0")));
539 assert_eq!(Tribool::True, num!("12.0").evaluate_eq(&num!("12")));
540 assert_eq!(Tribool::False, num!("12.0").evaluate_eq(&num!("12.123")));
541 assert_eq!(Tribool::False, num!("123").evaluate_eq(&num!("12.3")));
542 assert_eq!(Tribool::False, num!("123").evaluate_eq(&text!("Foo")));
543 assert_eq!(Tribool::Null, num!("123").evaluate_eq(&Null));
544 assert_eq!(Tribool::True, text!("Foo").evaluate_eq(&text!("Foo")));
546 assert_eq!(Tribool::False, text!("Foo").evaluate_eq(&text!("Bar")));
547 assert_eq!(Tribool::Null, text!("Foo").evaluate_eq(&Null));
548 assert_eq!(
550 Tribool::True,
551 bytea!("12A456").evaluate_eq(&bytea!("12A456"))
552 );
553 assert_eq!(Tribool::False, bytea!("1230").evaluate_eq(&num!("1230")));
554 assert_eq!(Tribool::Null, bytea!("12").evaluate_eq(&Null));
555 assert_eq!(Tribool::Null, Null.evaluate_eq(&Null));
557 }
558
559 #[test]
560 fn evaluate_cmp() {
561 use std::cmp::Ordering;
562 macro_rules! text {
563 ($text: expr) => {
564 Text(Cow::Owned($text.to_owned()))
565 };
566 }
567 macro_rules! num {
568 ($num: expr) => {
569 Number(Cow::Owned(BigDecimal::from_str($num).unwrap()))
570 };
571 }
572 macro_rules! bytea {
573 ($val: expr) => {
574 Bytea(hex::decode($val).unwrap())
575 };
576 }
577
578 assert_eq!(
580 Boolean(false).evaluate_cmp(&Boolean(true)),
581 Some(Ordering::Less)
582 );
583 assert_eq!(
584 Boolean(true).evaluate_cmp(&Boolean(true)),
585 Some(Ordering::Equal)
586 );
587 assert_eq!(
588 Boolean(true).evaluate_cmp(&Boolean(false)),
589 Some(Ordering::Greater)
590 );
591 assert_eq!(Boolean(true).evaluate_cmp(&num!("1")), None);
592 assert_eq!(Boolean(true).evaluate_cmp(&text!("Foo")), None);
593 assert_eq!(Boolean(true).evaluate_cmp(&Null), None);
594 assert_eq!(
596 num!("123").evaluate_cmp(&num!("1234")),
597 Some(Ordering::Less)
598 );
599 assert_eq!(
600 num!("12.0").evaluate_cmp(&num!("123")),
601 Some(Ordering::Less)
602 );
603 assert_eq!(
604 num!("123").evaluate_cmp(&num!("123.1")),
605 Some(Ordering::Less)
606 );
607 assert_eq!(
608 num!("12.0").evaluate_cmp(&num!("12.1")),
609 Some(Ordering::Less)
610 );
611 assert_eq!(
612 num!("123").evaluate_cmp(&num!("123")),
613 Some(Ordering::Equal)
614 );
615 assert_eq!(
616 num!("1234").evaluate_cmp(&num!("123")),
617 Some(Ordering::Greater)
618 );
619 assert_eq!(num!("123").evaluate_cmp(&text!("123")), None);
620 assert_eq!(num!("123").evaluate_cmp(&Null), None);
621 assert_eq!(text!("a").evaluate_cmp(&text!("b")), Some(Ordering::Less));
623 assert_eq!(text!("a").evaluate_cmp(&text!("a")), Some(Ordering::Equal));
624 assert_eq!(
625 text!("b").evaluate_cmp(&text!("a")),
626 Some(Ordering::Greater)
627 );
628 assert_eq!(text!("a").evaluate_cmp(&Null), None);
629 assert_eq!(
631 bytea!("12").evaluate_cmp(&bytea!("20")),
632 Some(Ordering::Less)
633 );
634 assert_eq!(
635 bytea!("31").evaluate_cmp(&bytea!("31")),
636 Some(Ordering::Equal)
637 );
638 assert_eq!(
639 bytea!("9A").evaluate_cmp(&bytea!("2A")),
640 Some(Ordering::Greater)
641 );
642 assert_eq!(bytea!("345D").evaluate_cmp(&Null), None);
643 assert_eq!(Null.evaluate_cmp(&Null), None);
644 }
645
646 #[test]
647 fn bitwise_and() {
648 use crate::data::LiteralError;
649
650 let num = |val: i32| Number(Cow::Owned(BigDecimal::from(val)));
651 let text = |val: &str| Text(Cow::Owned(String::from(val)));
652
653 macro_rules! ok {
654 ($left: expr, $right: expr, $expected: expr) => {
655 assert_eq!(($left).bitwise_and(&$right), Ok($expected))
656 };
657 }
658
659 macro_rules! err {
660 ($left: expr, $right: expr) => {
661 assert_eq!(
662 ($left).bitwise_and(&$right),
663 Err(LiteralError::UnsupportedBinaryOperation {
664 left: format!("{:?}", $left),
665 op: BinaryOperator::BitwiseAnd,
666 right: format!("{:?}", $right)
667 }
668 .into())
669 )
670 };
671 }
672
673 ok!(num(11), num(12), num(8));
674 err!(text("11"), num(12));
675 err!(num(11), text("12"));
676 err!(text("11"), text("12"));
677 }
678}