gluesql_core/executor/context/
row_context.rs

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