1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use crate::catalog::{ColumnCatalog, ColumnRef};
use crate::types::errors::TypeError;
use crate::types::tuple::Tuple;
use crate::types::value::{DataValue, ValueRef};
use std::sync::Arc;

pub struct TupleBuilder {
    columns: Vec<ColumnRef>,
}

impl TupleBuilder {
    pub fn new(columns: Vec<ColumnRef>) -> Self {
        TupleBuilder { columns }
    }

    pub fn build_result(header: String, message: String) -> Result<Tuple, TypeError> {
        let columns: Vec<ColumnRef> = vec![Arc::new(ColumnCatalog::new_dummy(header))];
        let values: Vec<ValueRef> = vec![Arc::new(DataValue::Utf8(Some(message)))];

        Ok(Tuple {
            id: None,
            columns,
            values,
        })
    }

    pub fn build_with_row<'a>(
        &self,
        row: impl IntoIterator<Item = &'a str>,
    ) -> Result<Tuple, TypeError> {
        let mut values = Vec::with_capacity(self.columns.len());
        let mut primary_key = None;

        for (i, value) in row.into_iter().enumerate() {
            let data_value = Arc::new(
                DataValue::Utf8(Some(value.to_string())).cast(self.columns[i].datatype())?,
            );

            if primary_key.is_none() && self.columns[i].desc.is_primary {
                primary_key = Some(data_value.clone());
            }
            values.push(data_value);
        }
        if values.len() != self.columns.len() {
            return Err(TypeError::MisMatch(
                "types".to_string(),
                "values".to_string(),
            ));
        }

        Ok(Tuple {
            id: primary_key,
            columns: self.columns.clone(),
            values,
        })
    }
}