use crate::common::PostgresSchemaType;
use crate::values::PostgresValue;
use core::marker::PhantomData;
use drizzle_core::{SQLTable, ToSQL};
use super::ExecutableState;
pub use drizzle_core::builder::{
UpdateInitial, UpdateReturningSet, UpdateSetClauseSet, UpdateWhereSet,
};
#[derive(Debug, Clone, Copy, Default)]
pub struct UpdateFromSet;
impl ExecutableState for UpdateFromSet {}
pub type UpdateBuilder<'a, Schema, State, Table, Marker = (), Row = ()> =
super::QueryBuilder<'a, Schema, State, Table, Marker, Row>;
type ReturningMarker<Table, Columns> = drizzle_core::Scoped<
<Columns as drizzle_core::IntoSelectTarget>::Marker,
drizzle_core::Cons<Table, drizzle_core::Nil>,
>;
type ReturningRow<Table, Columns> =
<<Columns as drizzle_core::IntoSelectTarget>::Marker as drizzle_core::ResolveRow<Table>>::Row;
type ReturningBuilder<'a, S, T, Columns> = UpdateBuilder<
'a,
S,
UpdateReturningSet,
T,
ReturningMarker<T, Columns>,
ReturningRow<T, Columns>,
>;
impl<'a, Schema, Table> UpdateBuilder<'a, Schema, UpdateInitial, Table>
where
Table: SQLTable<'a, PostgresSchemaType, PostgresValue<'a>>,
{
#[inline]
pub fn set(
self,
values: Table::Update,
) -> UpdateBuilder<'a, Schema, UpdateSetClauseSet, Table> {
let sql = crate::helpers::set::<Table, PostgresSchemaType, PostgresValue<'a>>(&values);
drop(values);
UpdateBuilder {
sql: self.sql.append(sql),
schema: PhantomData,
state: PhantomData,
table: PhantomData,
marker: PhantomData,
row: PhantomData,
grouped: PhantomData,
}
}
}
impl<'a, S, T> UpdateBuilder<'a, S, UpdateSetClauseSet, T> {
#[inline]
pub fn from(
self,
source: impl ToSQL<'a, PostgresValue<'a>>,
) -> UpdateBuilder<'a, S, UpdateFromSet, T> {
let from_sql = crate::helpers::from(source);
UpdateBuilder {
sql: self.sql.append(from_sql),
schema: PhantomData,
state: PhantomData,
table: PhantomData,
marker: PhantomData,
row: PhantomData,
grouped: PhantomData,
}
}
#[inline]
pub fn r#where<E>(self, condition: E) -> UpdateBuilder<'a, S, UpdateWhereSet, T>
where
E: drizzle_core::expr::Expr<'a, PostgresValue<'a>>,
E::SQLType: drizzle_core::types::BooleanLike,
{
let where_sql = crate::helpers::r#where(condition);
UpdateBuilder {
sql: self.sql.append(where_sql),
schema: PhantomData,
state: PhantomData,
table: PhantomData,
marker: PhantomData,
row: PhantomData,
grouped: PhantomData,
}
}
#[inline]
pub fn returning<Columns>(self, columns: Columns) -> ReturningBuilder<'a, S, T, Columns>
where
Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
Columns::Marker: drizzle_core::ResolveRow<T>,
{
let returning_sql = crate::helpers::returning(columns);
UpdateBuilder {
sql: self.sql.append(returning_sql),
schema: PhantomData,
state: PhantomData,
table: PhantomData,
marker: PhantomData,
row: PhantomData,
grouped: PhantomData,
}
}
}
impl<'a, S, T> UpdateBuilder<'a, S, UpdateFromSet, T> {
#[inline]
pub fn r#where<E>(self, condition: E) -> UpdateBuilder<'a, S, UpdateWhereSet, T>
where
E: drizzle_core::expr::Expr<'a, PostgresValue<'a>>,
E::SQLType: drizzle_core::types::BooleanLike,
{
let where_sql = crate::helpers::r#where(condition);
UpdateBuilder {
sql: self.sql.append(where_sql),
schema: PhantomData,
state: PhantomData,
table: PhantomData,
marker: PhantomData,
row: PhantomData,
grouped: PhantomData,
}
}
#[inline]
pub fn returning<Columns>(self, columns: Columns) -> ReturningBuilder<'a, S, T, Columns>
where
Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
Columns::Marker: drizzle_core::ResolveRow<T>,
{
let returning_sql = crate::helpers::returning(columns);
UpdateBuilder {
sql: self.sql.append(returning_sql),
schema: PhantomData,
state: PhantomData,
table: PhantomData,
marker: PhantomData,
row: PhantomData,
grouped: PhantomData,
}
}
}
impl<'a, S, T> UpdateBuilder<'a, S, UpdateWhereSet, T> {
#[inline]
pub fn returning<Columns>(self, columns: Columns) -> ReturningBuilder<'a, S, T, Columns>
where
Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
Columns::Marker: drizzle_core::ResolveRow<T>,
{
let returning_sql = crate::helpers::returning(columns);
UpdateBuilder {
sql: self.sql.append(returning_sql),
schema: PhantomData,
state: PhantomData,
table: PhantomData,
marker: PhantomData,
row: PhantomData,
grouped: PhantomData,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use drizzle_core::{SQL, ToSQL};
#[test]
fn test_update_builder_creation() {
let builder = UpdateBuilder::<(), UpdateInitial, ()> {
sql: SQL::raw("UPDATE test"),
schema: PhantomData,
state: PhantomData,
table: PhantomData,
marker: PhantomData,
row: PhantomData,
grouped: PhantomData,
};
assert_eq!(builder.to_sql().sql(), "UPDATE test");
}
}