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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use {
    super::{join::JoinOperatorType, NodeData, Prebuild},
    crate::{
        ast::{SelectItem, TableAlias, TableFactor},
        ast_builder::{
            ExprList, ExprNode, FilterNode, GroupByNode, JoinNode, LimitNode, OffsetNode,
            OrderByExprList, OrderByNode, ProjectNode, SelectItemList,
        },
        result::Result,
    },
};
#[derive(Clone)]
pub struct SelectNode {
    table_name: String,
    table_alias: Option<String>,
}
impl SelectNode {
    pub fn new(table_name: String, table_alias: Option<String>) -> Self {
        Self {
            table_name,
            table_alias,
        }
    }
    pub fn filter<T: Into<ExprNode>>(self, expr: T) -> FilterNode {
        FilterNode::new(self, expr)
    }
    pub fn group_by<T: Into<ExprList>>(self, expr_list: T) -> GroupByNode {
        GroupByNode::new(self, expr_list)
    }
    pub fn offset<T: Into<ExprNode>>(self, expr: T) -> OffsetNode {
        OffsetNode::new(self, expr)
    }
    pub fn limit<T: Into<ExprNode>>(self, expr: T) -> LimitNode {
        LimitNode::new(self, expr)
    }
    pub fn project<T: Into<SelectItemList>>(self, select_items: T) -> ProjectNode {
        ProjectNode::new(self, select_items)
    }
    pub fn order_by<T: Into<OrderByExprList>>(self, order_by_exprs: T) -> OrderByNode {
        OrderByNode::new(self, order_by_exprs)
    }
    pub fn join(self, table_name: &str) -> JoinNode {
        JoinNode::new(self, table_name.to_owned(), None, JoinOperatorType::Inner)
    }
    pub fn join_as(self, table_name: &str, alias: &str) -> JoinNode {
        JoinNode::new(
            self,
            table_name.to_owned(),
            Some(alias.to_owned()),
            JoinOperatorType::Inner,
        )
    }
    pub fn left_join(self, table_name: &str) -> JoinNode {
        JoinNode::new(self, table_name.to_owned(), None, JoinOperatorType::Left)
    }
    pub fn left_join_as(self, table_name: &str, alias: &str) -> JoinNode {
        JoinNode::new(
            self,
            table_name.to_owned(),
            Some(alias.to_owned()),
            JoinOperatorType::Left,
        )
    }
}
impl Prebuild for SelectNode {
    fn prebuild(self) -> Result<NodeData> {
        let relation = TableFactor::Table {
            name: self.table_name,
            alias: self.table_alias.map(|name| TableAlias {
                name,
                columns: Vec::new(),
            }),
            index: None,
        };
        Ok(NodeData {
            projection: vec![SelectItem::Wildcard],
            relation,
            filter: None,
            group_by: vec![],
            having: None,
            order_by: vec![],
            offset: None,
            limit: None,
            joins: vec![],
        })
    }
}
#[cfg(test)]
mod tests {
    use crate::ast_builder::{table, test, Build};
    #[test]
    fn select() {
        let actual = table("App").select().build();
        let expected = "SELECT * FROM App";
        test(actual, expected);
        let actual = table("Item").alias_as("i").select().build();
        let expected = "SELECT * FROM Item i";
        test(actual, expected);
    }
}