gluesql_core/ast_builder/
insert.rs1use {
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}