gluesql_core/data/
literal.rs

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        // subtract test
324        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        // multiply test
338        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        // Divide Test
476        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        // Modulo Test
496        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        //Number
537        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        //Text
545        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        //Bytea
549        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        // Null
556        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        //Boolean
579        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        //Number - valid format -> (int, int), (float, int), (int, float), (float, float)
595        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        //text
622        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        //Bytea
630        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}