easy_sqlx_core/sql/builder/
insert_builder.rs

1use sqlx::{Database, Executor, FromRow, Postgres};
2
3use crate::sql::{
4    dialects::schema::{self, schema::Schema as _},
5    schema::table::TableSchema,
6    utils::pair::Pair,
7};
8
9use super::builder::ExecuteBuilder;
10
11#[derive(Debug)]
12pub struct InsertBuilder<'a> {
13    table: TableSchema,
14    default_schema: &'a str,
15    columns: Vec<Pair>,
16}
17
18impl<'a> InsertBuilder<'a> {
19    pub fn new(table: TableSchema) -> Self {
20        Self {
21            table,
22            default_schema: "",
23            columns: vec![],
24        }
25    }
26
27    pub fn with_default_schema(mut self, schema: &'a str) -> Self {
28        self.default_schema = schema;
29        self
30    }
31
32    pub fn set(mut self, pair: Pair) -> Self {
33        self.columns.push(pair);
34        self
35    }
36}
37
38impl<'a> ExecuteBuilder for InsertBuilder<'a>
39// <DB as sqlx::Database>::Arguments<'a>: IntoArguments<'a, DB>,
40{
41    #[cfg(feature = "postgres")]
42    type DB = Postgres;
43
44    async fn execute<C>(
45        &self,
46        conn: &mut C,
47    ) -> Result<<Self::DB as Database>::QueryResult, sqlx::Error>
48    where
49        for<'e> &'e mut C: Executor<'e, Database = Self::DB>,
50    {
51        let schema = schema::new(self.default_schema.to_string());
52        let cols: Vec<String> = self.columns.iter().map(|c| c.name.to_string()).collect();
53        let sql = schema.sql_insert_columns(&self.table, &cols, false);
54
55        let mut query: sqlx::query::Query<'_, Self::DB, <Self::DB as Database>::Arguments<'_>> =
56            sqlx::query::<Self::DB>(&sql);
57
58        for col in &self.columns {
59            query = col.value.bind_to_query(query);
60        }
61
62        // tracing::debug!("easy-sqlx: {}", query.sql());
63
64        let result = query.execute(conn).await.map_err(|err| {
65            tracing::error!(
66                "easy-sqlx: {} [{}]\n{:?}",
67                sql,
68                &self
69                    .columns
70                    .iter()
71                    .map(|c| { c.value.as_string() })
72                    .collect::<Vec<String>>()
73                    .join(","),
74                err
75            );
76            err
77        })?;
78
79        #[cfg(feature = "logsql")]
80        {
81            tracing::info!(
82                "easy-sqlx: {sql} [{}]\nnrows_affected: {}",
83                &self
84                    .columns
85                    .iter()
86                    .map(|c| { c.value.as_string() })
87                    .collect::<Vec<String>>()
88                    .join(","),
89                result.rows_affected()
90            );
91        }
92
93        Ok(result)
94    }
95
96    #[cfg(feature = "postgres")]
97    async fn execute_return<'e, 'c: 'e, C, O>(&self, executor: C) -> sqlx::Result<Vec<O>>
98    where
99        C: 'e + Executor<'c, Database = Self::DB>,
100        O: 'e,
101        for<'r> O: FromRow<'r, <Self::DB as Database>::Row>,
102        O: std::marker::Send,
103        O: Unpin,
104    {
105        let schema = schema::new(self.default_schema.to_string());
106        let cols: Vec<String> = self.columns.iter().map(|c| c.name.to_string()).collect();
107        let sql = schema.sql_insert_columns(&self.table, &cols, true);
108
109        let mut query = sqlx::query_as::<Self::DB, O>(&sql);
110
111        for col in &self.columns {
112            query = col.value.bind_to_query_as(query);
113        }
114
115        // tracing::debug!("easy-sqlx: {}", query.sql());
116
117        let result: Result<Vec<O>, sqlx::Error> = query.fetch_all(executor).await.map_err(|err| {
118            tracing::error!(
119                "easy-sqlx: {} [{}]\n{:?}",
120                sql,
121                &self
122                    .columns
123                    .iter()
124                    .map(|c| { c.value.as_string() })
125                    .collect::<Vec<String>>()
126                    .join(","),
127                err
128            );
129            err
130        });
131
132        #[cfg(feature = "logsql")]
133        {
134            tracing::info!(
135                "easy-sqlx: {sql} [{}]",
136                &self
137                    .columns
138                    .iter()
139                    .map(|c| { c.value.as_string() })
140                    .collect::<Vec<String>>()
141                    .join(",")
142            );
143        }
144
145        result
146    }
147}