Skip to main content

gitql_core/values/
row.rs

1use std::any::Any;
2use std::cmp::Ordering;
3
4use gitql_ast::types::row::RowType;
5use gitql_ast::types::DataType;
6
7use crate::values::boolean::BoolValue;
8
9use super::base::Value;
10
11#[derive(Clone)]
12pub struct RowValue {
13    pub columns: Vec<Box<dyn Value>>,
14    pub row_type: RowType,
15}
16
17impl RowValue {
18    pub fn new(columns: Vec<Box<dyn Value>>, row_type: RowType) -> Self {
19        RowValue { columns, row_type }
20    }
21}
22
23impl Value for RowValue {
24    fn literal(&self) -> String {
25        let mut str = String::new();
26        str += "(";
27        for (pos, element) in self.columns.iter().enumerate() {
28            str += &element.literal();
29            if pos + 1 != self.columns.len() {
30                str += ", ";
31            }
32        }
33        str += ")";
34        str
35    }
36
37    fn equals(&self, other: &Box<dyn Value>) -> bool {
38        if let Some(other_row) = other.as_any().downcast_ref::<RowValue>() {
39            let data_type: Box<dyn DataType> = Box::new(other_row.row_type.clone());
40            if !self.row_type.equals(&data_type) {
41                return false;
42            }
43
44            let len = self.row_type.tuple.len();
45            for i in 0..len {
46                if !self.columns[i].eq(&other_row.columns[i]) {
47                    return false;
48                }
49            }
50
51            return true;
52        }
53        false
54    }
55
56    fn compare(&self, _other: &Box<dyn Value>) -> Option<Ordering> {
57        None
58    }
59
60    fn data_type(&self) -> Box<dyn DataType> {
61        Box::new(self.row_type.clone())
62    }
63
64    fn as_any(&self) -> &dyn Any {
65        self
66    }
67
68    fn eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
69        if other.as_any().downcast_ref::<RowValue>().is_none() {
70            return Err("Unexpected type to perform `=` with".to_string());
71        }
72        Ok(Box::new(BoolValue::new(self.equals(other))))
73    }
74
75    fn bang_eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
76        if other.as_any().downcast_ref::<RowValue>().is_none() {
77            return Err("Unexpected type to perform `!=` with".to_string());
78        }
79        Ok(Box::new(BoolValue::new(!self.equals(other))))
80    }
81}