ormlite_core/insert.rs
1use crate::Result;
2use futures::future::BoxFuture;
3pub use sqlmo::query::OnConflict;
4use sqlmo::{Dialect, Insert, ToSql};
5
6/// Represents an insert query.
7/// We had to turn this into a model because we need to pass in the on_conflict configuration.
8pub struct Insertion<'a, Acquire, Model, DB: sqlx::Database> {
9 pub acquire: Acquire,
10 pub model: Model,
11 pub closure: Box<dyn 'static + Send + FnOnce(Acquire, Model, String) -> BoxFuture<'a, Result<Model>>>,
12 pub insert: Insert,
13 pub _db: std::marker::PhantomData<DB>,
14}
15
16impl<'a, Acquire, Model, DB: sqlx::Database> Insertion<'a, Acquire, Model, DB> {
17 pub fn on_conflict(mut self, c: OnConflict) -> Self {
18 self.insert.on_conflict = c;
19 self
20 }
21}
22
23impl<'a, Acquire, Model: crate::model::Model<DB>, DB: sqlx::Database> std::future::IntoFuture
24 for Insertion<'a, Acquire, Model, DB>
25{
26 type Output = Result<Model>;
27 type IntoFuture = BoxFuture<'a, Self::Output>;
28
29 fn into_future(self) -> Self::IntoFuture {
30 // hack to get around the fact that postgres drops the return
31 // value in ON CONFLICT DO NOTHING case
32 // let q = if matches!(self.insert.on_conflict, OnConflict::Ignore) {
33 // let insert_as_select = Select {
34 // ctes: vec![
35 // Cte::new("inserted", self.insert)
36 // ],
37 // columns: vec![SelectColumn::raw("*")],
38 // from: Some("inserted".into()),
39 // ..Select::default()
40 // };
41 // let pkey = Model::primary_key().unwrap();
42 // let plc_idx = Model::primary_key_placeholder_idx().unwrap();
43 // let select_existing = Select {
44 // from: Some(Model::table_name().into()),
45 // columns: Model::table_columns().iter().map(|&c| c.into()).collect(),
46 // where_: format!("{pkey} = ${plc_idx}").into(),
47 // ..Select::default()
48 // };
49 // let union = Union {
50 // all: true,
51 // queries: vec![
52 // insert_as_select,
53 // select_existing
54 // ]
55 // };
56 // union.to_sql(Dialect::Postgres)
57 // } else {
58 // self.insert.to_sql(Dialect::Postgres)
59 // };
60 let q = self.insert.to_sql(Dialect::Postgres);
61 (self.closure)(self.acquire, self.model, q)
62 }
63}