use keelson_core::clause::{
ConflictClause, HasReturning, HasTableRef, HasValues, HasWith, Returning, TableRef, Values,
With,
};
use keelson_core::expr::{Expr, IntoExpr, IntoExprList};
use keelson_core::{Dialect, Error, Expression, Mod, Query, QueryExtensions, QueryType, SqlWriter};
use crate::Sqlite;
use crate::extras::{HasOr, HasUpserts, Or, write_spaced};
#[derive(Debug, Clone, Default)]
pub struct InsertQuery {
pub with: With,
pub or: Option<Or>,
pub table: TableRef,
pub values: Values,
pub upserts: Vec<ConflictClause>,
pub returning: Returning,
}
impl InsertQuery {
pub fn new() -> InsertQuery {
InsertQuery::default()
}
pub fn apply(&mut self, mods: impl Mod<InsertQuery>) {
mods.apply(self);
}
}
impl Expression for InsertQuery {
fn write_sql(&self, w: &mut SqlWriter<'_>) {
w.write_if(!self.with.is_empty(), "", &self.with, " ");
if self.table.is_empty() {
w.record_error(Error::Incomplete("the target table of an INSERT"));
return;
}
w.push_str("INSERT");
if let Some(or) = self.or {
w.push_str(" OR ");
w.push_str(or.as_str());
}
w.push_str(" INTO ");
w.write_expr(&self.table);
if self.values.is_empty() {
if self.upserts.iter().any(|c| !c.is_empty()) {
w.record_error(Error::other(
"a DEFAULT VALUES insert cannot carry an ON CONFLICT clause",
));
return;
}
w.push_str(" DEFAULT VALUES");
} else {
w.push_str(" ");
w.write_expr(&self.values);
}
if self.upserts.iter().any(|c| !c.is_empty()) {
w.push_str(" ");
write_spaced(w, self.upserts.iter().filter(|c| !c.is_empty()));
}
w.write_if(!self.returning.is_empty(), " ", &self.returning, "");
}
}
impl Query for InsertQuery {
fn query_type(&self) -> QueryType {
QueryType::Insert
}
fn dialect(&self) -> &dyn Dialect {
&Sqlite
}
}
impl<H, L, M> QueryExtensions<H, L, M> for InsertQuery {}
impl IntoExpr for InsertQuery {
fn into_expr(self) -> Expr {
crate::query(self)
}
}
impl IntoExprList for InsertQuery {
fn into_expr_list(self) -> Vec<Expr> {
vec![self.into_expr()]
}
}
impl HasWith for InsertQuery {
fn with_mut(&mut self) -> &mut With {
&mut self.with
}
}
impl HasTableRef for InsertQuery {
fn table_ref_mut(&mut self) -> &mut TableRef {
&mut self.table
}
}
impl HasValues for InsertQuery {
fn values_mut(&mut self) -> &mut Values {
&mut self.values
}
}
impl HasOr for InsertQuery {
fn or_mut(&mut self) -> &mut Option<Or> {
&mut self.or
}
}
impl HasUpserts for InsertQuery {
fn upserts_mut(&mut self) -> &mut Vec<ConflictClause> {
&mut self.upserts
}
}
impl HasReturning for InsertQuery {
fn returning_mut(&mut self) -> &mut Returning {
&mut self.returning
}
}