Skip to content

Commit

Permalink
fix insert on conflict do nothing
Browse files Browse the repository at this point in the history
  • Loading branch information
kurtbuilds committed Nov 20, 2024
1 parent f04a90a commit c62fb7b
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
34 changes: 31 additions & 3 deletions core/src/insert.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::Result;
use futures::future::BoxFuture;
pub use sqlmo::query::OnConflict;
#[allow(unused_imports)]
use sqlmo::{Dialect, Insert, ToSql};
use sqlmo::{Dialect, Insert, ToSql, Union, Select, Cte, SelectColumn};

/// Represents an insert query.
/// We had to turn this into a model because we need to pass in the on_conflict configuration.
Expand All @@ -28,7 +27,36 @@ impl<'a, Acquire, Model: crate::model::Model<DB>, DB: sqlx::Database> std::futur
type IntoFuture = BoxFuture<'a, Self::Output>;

fn into_future(self) -> Self::IntoFuture {
let q = self.insert.to_sql(Dialect::Postgres);
// hack to get around the fact that postgres drops the return
// value in ON CONFLICT DO NOTHING case
let q = if matches!(self.insert.on_conflict, OnConflict::Ignore) {
let insert_as_select = Select {
ctes: vec![
Cte::new("inserted", self.insert)
],
columns: vec![SelectColumn::raw("*")],
from: Some("inserted".into()),
..Select::default()
};
let pkey = Model::primary_key().unwrap();
let plc_idx = Model::primary_key_placeholder_idx().unwrap();
let select_existing = Select {
from: Some(Model::table_name().into()),
columns: Model::table_columns().iter().map(|&c| c.into()).collect(),
where_: format!("{pkey} = ${plc_idx}").into(),
..Select::default()
};
let union = Union {
all: true,
queries: vec![
insert_as_select,
select_existing
]
};
union.to_sql(Dialect::Postgres)
} else {
self.insert.to_sql(Dialect::Postgres)
};
(self.closure)(self.acquire, self.model, q)
}
}
4 changes: 4 additions & 0 deletions core/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,8 @@ pub trait TableMeta {
fn table_name() -> &'static str;
fn table_columns() -> &'static [&'static str];
fn primary_key() -> Option<&'static str>;
fn primary_key_placeholder_idx() -> Option<usize> {
let col = Self::primary_key()?;
Self::table_columns().iter().position(|&c| c == col).map(|i| i + 1)
}
}

0 comments on commit c62fb7b

Please sign in to comment.