Skip to main content

gluesql_core/executor/context/
row_context.rs

1use {
2    crate::data::{Row, Value},
3    std::{borrow::Cow, fmt::Debug, rc::Rc},
4};
5
6#[derive(Debug)]
7pub enum RowContext<'a> {
8    Data {
9        table_alias: &'a str,
10        row: Cow<'a, Row>,
11        next: Option<Rc<RowContext<'a>>>,
12    },
13    RefVecData {
14        columns: &'a [String],
15        values: &'a [Value],
16    },
17    Bridge {
18        left: Rc<RowContext<'a>>,
19        right: Rc<RowContext<'a>>,
20    },
21}
22
23impl<'a> RowContext<'a> {
24    pub fn new(table_alias: &'a str, row: Cow<'a, Row>, next: Option<Rc<RowContext<'a>>>) -> Self {
25        Self::Data {
26            table_alias,
27            row,
28            next,
29        }
30    }
31
32    pub fn concat(left: Rc<RowContext<'a>>, right: Rc<RowContext<'a>>) -> Self {
33        Self::Bridge { left, right }
34    }
35
36    pub fn get_value(&'a self, target: &str) -> Option<&'a Value> {
37        match self {
38            Self::Data {
39                row, next: None, ..
40            } => row.get_value(target),
41            Self::Data {
42                row,
43                next: Some(next),
44                ..
45            } => row.get_value(target).or_else(|| next.get_value(target)),
46            Self::Bridge { left, right } => {
47                left.get_value(target).or_else(|| right.get_value(target))
48            }
49            Self::RefVecData { columns, values } => columns
50                .iter()
51                .position(|column| column == target)
52                .and_then(|index| values.get(index)),
53        }
54    }
55
56    pub fn get_alias_value(&'a self, target_table_alias: &str, target: &str) -> Option<&'a Value> {
57        match self {
58            Self::Data {
59                table_alias,
60                row,
61                next,
62            } if *table_alias == target_table_alias => {
63                let value = row.get_value(target);
64
65                if value.is_some() {
66                    value
67                } else {
68                    next.as_ref()
69                        .and_then(|context| context.get_alias_value(target_table_alias, target))
70                }
71            }
72            Self::Data {
73                next: Some(next), ..
74            } => next.get_alias_value(target_table_alias, target),
75            Self::Bridge { left, right } => left
76                .get_alias_value(target_table_alias, target)
77                .or_else(|| right.get_alias_value(target_table_alias, target)),
78            _ => None,
79        }
80    }
81
82    pub fn get_alias_entries(&self, alias: &str) -> Option<Vec<(&String, Value)>> {
83        match self {
84            Self::Data {
85                table_alias, row, ..
86            } if *table_alias == alias => Some(row.iter().map(|(k, v)| (k, v.clone())).collect()),
87            Self::Data {
88                next: Some(next), ..
89            } => next.get_alias_entries(alias),
90            Self::Bridge { left, right } => left
91                .get_alias_entries(alias)
92                .or_else(|| right.get_alias_entries(alias)),
93            _ => None,
94        }
95    }
96
97    pub fn get_all_entries(&self) -> Vec<(&String, Value)> {
98        match self {
99            Self::Data {
100                row, next: None, ..
101            } => row.iter().map(|(k, v)| (k, v.clone())).collect(),
102            Self::Data {
103                row,
104                next: Some(next),
105                ..
106            } => next
107                .get_all_entries()
108                .into_iter()
109                .chain(row.iter().map(|(k, v)| (k, v.clone())))
110                .collect(),
111            Self::Bridge { left, right } => {
112                [left.get_all_entries(), right.get_all_entries()].concat()
113            }
114            _ => vec![],
115        }
116    }
117}