1use std::marker::PhantomData;
5
6use crate::dialect::{Dialect, SupportsReturning};
7use crate::expr::Value;
8use crate::render::{QuerySink, SelectItem, Sink, render_select_list};
9use crate::scope::{Cons, Nil, NotNull, Table, TableSlot};
10use crate::select::Selection;
11
12pub trait Statement: private::Sealed {
16 type Dialect: Dialect;
17 type Table: Table;
18
19 #[doc(hidden)]
20 fn render(&self) -> QuerySink<Self::Dialect>;
21
22 fn to_sql(&self, _dialect: Self::Dialect) -> (String, Vec<Value>) {
24 self.render().finish()
25 }
26
27 fn returning<Sel, Idx>(self, sel: Sel) -> Returning<Self, Sel>
32 where
33 Self: Sized,
34 Self::Dialect: SupportsReturning,
35 Sel: Selection<WrittenTable<Self::Table>, Idx>,
36 {
37 Returning {
38 returning: sel.items(),
39 statement: self,
40 _marker: PhantomData,
41 }
42 }
43}
44
45pub(crate) mod private {
46 pub trait Sealed {}
47}
48
49pub type WrittenTable<T> = Cons<TableSlot<T, NotNull>, Nil>;
52
53pub struct Returning<S, Sel> {
58 pub(crate) statement: S,
59 pub(crate) returning: Vec<SelectItem>,
60 pub(crate) _marker: PhantomData<fn() -> Sel>,
61}
62
63impl<S: Statement, Sel> Returning<S, Sel> {
64 pub fn to_sql(&self, _dialect: S::Dialect) -> (String, Vec<Value>) {
65 let mut sink = self.statement.render();
66 sink.text(" RETURNING ");
67 render_select_list::<S::Dialect>(&self.returning, &mut sink);
68 sink.finish()
69 }
70}