gluesql_core/ast_builder/
insert.rs

1use {
2    super::{Build, ColumnList, ExprList, QueryNode},
3    crate::{ast::Statement, result::Result},
4};
5
6#[derive(Clone, Debug)]
7pub struct InsertNode {
8    table_name: String,
9    columns: Option<ColumnList>,
10}
11
12impl InsertNode {
13    pub fn new(table_name: String) -> Self {
14        Self {
15            table_name,
16            columns: None,
17        }
18    }
19
20    pub fn columns<T: Into<ColumnList>>(mut self, columns: T) -> Self {
21        self.columns = Some(columns.into());
22        self
23    }
24
25    pub fn values<'a, T: Into<ExprList<'a>>>(self, values: Vec<T>) -> InsertSourceNode<'a> {
26        let values: Vec<ExprList> = values.into_iter().map(Into::into).collect();
27
28        InsertSourceNode {
29            insert_node: self,
30            source: QueryNode::Values(values),
31        }
32    }
33
34    pub fn as_select<'a, T: Into<QueryNode<'a>>>(self, query: T) -> InsertSourceNode<'a> {
35        InsertSourceNode {
36            insert_node: self,
37            source: query.into(),
38        }
39    }
40}
41
42#[derive(Clone, Debug)]
43pub struct InsertSourceNode<'a> {
44    insert_node: InsertNode,
45    source: QueryNode<'a>,
46}
47
48impl<'a> Build for InsertSourceNode<'a> {
49    fn build(self) -> Result<Statement> {
50        let table_name = self.insert_node.table_name;
51        let columns = self.insert_node.columns;
52        let columns = columns.map_or_else(|| Ok(vec![]), |v| v.try_into())?;
53        let source = self.source.try_into()?;
54
55        Ok(Statement::Insert {
56            table_name,
57            columns,
58            source,
59        })
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use crate::ast_builder::{Build, num, table, test};
66
67    #[test]
68    fn insert() {
69        let actual = table("Foo").insert().values(vec!["1, 5", "2, 3"]).build();
70        let expected = r#"INSERT INTO Foo VALUES (1, 5), (2, 3)"#;
71        test(actual, expected);
72
73        let actual = table("Foo")
74            .insert()
75            .columns("id, name")
76            .values(vec![vec![num(1), num(5)], vec![num(2), num(3)]])
77            .build();
78        let expected = r#"INSERT INTO Foo (id, name) VALUES (1, 5), (2, 3)"#;
79        test(actual, expected);
80
81        let actual = table("Foo")
82            .insert()
83            .columns(vec!["hi"])
84            .values(vec![vec![num(7)]])
85            .build();
86        let expected = r#"INSERT INTO Foo (hi) VALUES (7)"#;
87        test(actual, expected);
88
89        let actual = table("Foo")
90            .insert()
91            .as_select(table("Bar").select().project("id, name").limit(10))
92            .build();
93        let expected = r#"INSERT INTO Foo SELECT id, name FROM Bar LIMIT 10"#;
94        test(actual, expected);
95    }
96}