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
58
59
60
61
62
63
64
65
66
use std::{fmt::Debug, sync::Arc};

use serde_json::Value;
use sqlx_core::{column::ColumnIndex, database::Database, row::Row, Error as SqlxError, HashMap};

use crate::{column::ExaColumn, database::Exasol, value::ExaValueRef};

/// Struct representing a result set row.
#[derive(Debug)]
pub struct ExaRow {
    column_names: Arc<HashMap<Arc<str>, usize>>,
    columns: Arc<[ExaColumn]>,
    data: Vec<Value>,
}

impl ExaRow {
    pub fn new(
        data: Vec<Value>,
        columns: Arc<[ExaColumn]>,
        column_names: Arc<HashMap<Arc<str>, usize>>,
    ) -> Self {
        Self {
            column_names,
            columns,
            data,
        }
    }
}

impl Row for ExaRow {
    type Database = Exasol;

    fn columns(&self) -> &[<Self::Database as Database>::Column] {
        &self.columns
    }

    fn try_get_raw<I>(
        &self,
        index: I,
    ) -> Result<<Self::Database as Database>::ValueRef<'_>, SqlxError>
    where
        I: ColumnIndex<Self>,
    {
        let col_idx = index.index(self)?;
        let err_fn = || SqlxError::ColumnIndexOutOfBounds {
            index: col_idx,
            len: self.columns.len(),
        };

        let value = self.data.get(col_idx).ok_or_else(err_fn)?;
        let type_info = &self.columns.get(col_idx).ok_or_else(err_fn)?.data_type;
        let val = ExaValueRef { value, type_info };

        Ok(val)
    }
}

impl ColumnIndex<ExaRow> for &'_ str {
    fn index(&self, container: &ExaRow) -> Result<usize, SqlxError> {
        container
            .column_names
            .get(*self)
            .copied()
            .ok_or_else(|| SqlxError::ColumnNotFound((*self).to_string()))
    }
}