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
67
68
69
70
mod cmp_expr;
mod non_clustered;
mod primary_key;

pub use {
    crate::{ast::IndexItem, result::Result},
    cmp_expr::CmpExprNode,
    non_clustered::{non_clustered, NonClusteredNode},
    primary_key::{primary_key, PrimaryKeyNode},
};

use {
    super::{insert::Expr, select::Prebuild, ExprNode},
    crate::ast::IndexOperator,
};

#[derive(Clone, Debug)]
pub enum IndexItemNode<'a> {
    NonClustered {
        name: String,
        asc: Option<bool>,
        cmp_expr: Option<(IndexOperator, ExprNode<'a>)>,
    },
    PrimaryKey(ExprNode<'a>),
}

impl<'a> From<CmpExprNode<'a>> for IndexItemNode<'a> {
    fn from(cmp_expr: CmpExprNode<'a>) -> Self {
        IndexItemNode::NonClustered {
            name: cmp_expr.index_name,
            asc: None,
            cmp_expr: Some((cmp_expr.operator, cmp_expr.expr)),
        }
    }
}

impl<'a> From<NonClusteredNode> for IndexItemNode<'a> {
    fn from(non_clustered: NonClusteredNode) -> Self {
        IndexItemNode::NonClustered {
            name: non_clustered.index_name,
            asc: None,
            cmp_expr: None,
        }
    }
}

impl<'a> Prebuild<IndexItem> for IndexItemNode<'a> {
    fn prebuild(self) -> Result<IndexItem> {
        match self {
            IndexItemNode::NonClustered {
                name,
                asc,
                cmp_expr,
            } => {
                let (index_operator, expr) = cmp_expr.unzip();
                let expr_result: Option<Expr> = expr.map(ExprNode::try_into).transpose()?;
                let cmp_expr_result: Option<(IndexOperator, Expr)> = index_operator
                    .zip(expr_result)
                    .map(|(index_operator, expr)| (index_operator, expr));

                Ok(IndexItem::NonClustered {
                    name,
                    asc,
                    cmp_expr: cmp_expr_result,
                })
            }
            IndexItemNode::PrimaryKey(expr) => Ok(IndexItem::PrimaryKey(expr.try_into()?)),
        }
    }
}