gluesql_core/data/
row.rs

1use {
2    crate::{data::Value, executor::RowContext, result::Result},
3    serde::Serialize,
4    std::{collections::BTreeMap, fmt::Debug, sync::Arc},
5    thiserror::Error,
6};
7
8#[derive(Error, Serialize, Debug, PartialEq, Eq)]
9pub enum RowError {
10    #[error("conflict - vec expected but map row found")]
11    ConflictOnUnexpectedMapRowFound,
12
13    #[error("conflict - map expected but vec row found")]
14    ConflictOnUnexpectedVecRowFound,
15}
16
17#[derive(Clone, Debug, PartialEq)]
18pub enum Row {
19    Vec {
20        columns: Arc<[String]>,
21        values: Vec<Value>,
22    },
23    Map(BTreeMap<String, Value>),
24}
25
26impl Row {
27    pub fn get_value(&self, ident: &str) -> Option<&Value> {
28        match self {
29            Self::Vec { columns, values } => columns
30                .iter()
31                .position(|column| column == ident)
32                .and_then(|index| values.get(index)),
33            Self::Map(values) => Some(values.get(ident).unwrap_or(&Value::Null)),
34        }
35    }
36
37    pub fn iter(&self) -> impl Iterator<Item = (&String, &Value)> {
38        #[derive(iter_enum::Iterator)]
39        enum Entries<I1, I2> {
40            Vec(I1),
41            Map(I2),
42        }
43
44        match self {
45            Self::Vec { columns, values } => Entries::Vec(columns.iter().zip(values.iter())),
46            Self::Map(values) => Entries::Map(values.iter()),
47        }
48    }
49
50    pub fn try_into_vec(self) -> Result<Vec<Value>> {
51        match self {
52            Self::Vec { values, .. } => Ok(values),
53            Self::Map(_) => Err(RowError::ConflictOnUnexpectedMapRowFound.into()),
54        }
55    }
56
57    pub fn try_into_map(self) -> Result<BTreeMap<String, Value>> {
58        match self {
59            Self::Vec { .. } => Err(RowError::ConflictOnUnexpectedVecRowFound.into()),
60            Self::Map(values) => Ok(values),
61        }
62    }
63
64    pub fn as_context(&self) -> RowContext<'_> {
65        match self {
66            Self::Vec { columns, values } => RowContext::RefVecData { columns, values },
67            Self::Map(values) => RowContext::RefMapData(values),
68        }
69    }
70}