use std::marker::PhantomData;
use crate::dialect::{Dialect, SupportsReturning};
use crate::expr::Value;
use crate::render::{QuerySink, SelectItem, Sink, render_select_list};
use crate::scope::{Cons, Nil, NotNull, Table, TableSlot};
use crate::select::Selection;
pub trait Statement: private::Sealed {
type Dialect: Dialect;
type Table: Table;
#[doc(hidden)]
fn render(&self) -> QuerySink<Self::Dialect>;
fn to_sql(&self, _dialect: Self::Dialect) -> (String, Vec<Value>) {
self.render().finish()
}
fn returning<Sel, Idx>(self, sel: Sel) -> Returning<Self, Sel>
where
Self: Sized,
Self::Dialect: SupportsReturning,
Sel: Selection<WrittenTable<Self::Table>, Idx>,
{
Returning {
returning: sel.items(),
statement: self,
_marker: PhantomData,
}
}
}
pub(crate) mod private {
pub trait Sealed {}
}
pub type WrittenTable<T> = Cons<TableSlot<T, NotNull>, Nil>;
pub struct Returning<S, Sel> {
pub(crate) statement: S,
pub(crate) returning: Vec<SelectItem>,
pub(crate) _marker: PhantomData<fn() -> Sel>,
}
impl<S: Statement, Sel> Returning<S, Sel> {
pub fn to_sql(&self, _dialect: S::Dialect) -> (String, Vec<Value>) {
let mut sink = self.statement.render();
sink.text(" RETURNING ");
render_select_list::<S::Dialect>(&self.returning, &mut sink);
sink.finish()
}
}