use crate::clause;
use crate::item::Ident;
use crate::item::Row;
use crate::item::TableRef;
macro_rules! stmt_common {
($stmt:ident) => {
impl<'a> std::convert::From<$stmt<'a>> for $crate::stmt::Stmt<'a> {
#[inline]
fn from(val: $stmt<'a>) -> Self {
$crate::stmt::Stmt::$stmt(val)
}
}
impl<'a> $stmt<'a> {
pub fn with<N, S>(mut self, name: N, stmt: S) -> $stmt<'a>
where
N: Into<$crate::item::Ident<'a>>,
S: Into<$crate::stmt::Stmt<'a>>,
{
self.with = match self.with.take() {
Some(mut with) => {
with.1.push($crate::item::Cte {
name: name.into(),
columns: Vec::new(),
stmt: stmt.into(),
});
Some(with)
}
None => Some(
[$crate::item::Cte {
name: name.into(),
columns: Vec::new(),
stmt: stmt.into(),
}]
.into(),
),
};
self
}
pub fn with_labeled<N, C, I, S>(mut self, name: N, fields: I, stmt: S) -> $stmt<'a>
where
N: Into<$crate::item::Ident<'a>>,
C: Into<$crate::item::Ident<'a>>,
I: IntoIterator<Item = C>,
S: Into<$crate::stmt::Stmt<'a>>,
{
self.with = match self.with.take() {
Some(mut with) => {
with.1.push($crate::item::Cte {
name: name.into(),
columns: fields.into_iter().map(Into::into).collect(),
stmt: stmt.into(),
});
Some(with)
}
None => Some(
[$crate::item::Cte {
name: name.into(),
columns: fields.into_iter().map(Into::into).collect(),
stmt: stmt.into(),
}]
.into(),
),
};
self
}
pub fn recursive(mut self) -> $stmt<'a> {
if let Some(mut with) = self.with {
with.0 = true;
self.with = Some(with);
}
self
}
pub fn no_recursive(mut self) -> $stmt<'a> {
if let Some(mut with) = self.with {
with.0 = false;
self.with = Some(with);
}
self
}
}
};
}
pub mod binary;
pub mod data;
pub mod delete;
pub mod insert;
pub mod result;
pub mod select;
pub mod update;
pub mod values;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Stmt<'a> {
Insert(insert::Insert<'a>),
Select(select::Select<'a>),
Update(update::Update<'a>),
Delete(delete::Delete<'a>),
Values(values::Values<'a>),
Binary(binary::Binary<'a>),
Result(result::Result<'a>),
}
crate::macros::gen_display!(Stmt<'_>);
#[inline]
pub fn select<'a, F>(fields: F) -> select::Select<'a>
where
F: Into<clause::Select<'a>>,
{
select::Select {
fields: fields.into(),
..Default::default()
}
}
#[inline]
pub fn values<'a, I, R>(values: I) -> values::Values<'a>
where
R: Into<Row<'a>>,
I: IntoIterator<Item = R>,
{
values::Values {
rows: clause::Values(values.into_iter().map(Into::into).collect()),
..Default::default()
}
}
#[inline]
pub fn insert<'a, T, I, C>(table: T, columns: I) -> insert::Insert<'a>
where
T: Into<TableRef<'a>>,
C: Into<Ident<'a>>,
I: IntoIterator<Item = C>,
{
insert::Insert {
table: clause::Insert(table.into(), columns.into_iter().map(Into::into).collect()),
..Default::default()
}
}
#[inline]
pub fn delete<'a, T>(table: T) -> delete::Delete<'a>
where
T: Into<clause::Delete<'a>>,
{
delete::Delete {
table: table.into(),
..Default::default()
}
}
#[inline]
pub fn update<'a, T>(table: T) -> update::Update<'a>
where
T: Into<clause::Update<'a>>,
{
update::Update {
table: table.into(),
..Default::default()
}
}
macro_rules! generate_binary_funcs {
($(#[$comment:meta])* $fn:ident $op:expr) => {
$(#[$comment])*
#[inline]
pub fn $fn<'a, L, R>(left: L, right: R) -> $crate::stmt::binary::Binary<'a>
where
L: Into<$crate::stmt::result::Result<'a>>,
R: Into<$crate::stmt::result::Result<'a>>,
{
$crate::stmt::binary::Binary {
with: None,
op: $op,
left: ::std::boxed::Box::new(left.into()),
right: ::std::boxed::Box::new(right.into()),
}
}
};
}
generate_binary_funcs!(
union "UNION");
generate_binary_funcs!(
union_all "UNION ALL");
generate_binary_funcs!(
except "EXCEPT");
generate_binary_funcs!(
except_all "EXCEPT ALL");
generate_binary_funcs!(
intersect "INTERSECT");
generate_binary_funcs!(
intersect_all "INTERSECT ALL");
#[cfg(test)]
mod tests {
#[test]
fn cte() {
let tbl1 = &"tbl1".to_string();
let tbl2 = &"tbl2".to_string();
let query = crate::stmt::select(["name"])
.from(["tbl1", "tbl2"])
.with_labeled("tbl1", ["name"], crate::stmt::values([(tbl1,)]))
.with(
"tbl2",
crate::stmt::select([crate::ops::as_field(tbl2, "name")]),
);
assert_eq!(
query.to_string(),
"WITH tbl1(name) AS (VALUES ('tbl1')), tbl2 AS (SELECT 'tbl2' AS name) SELECT name FROM tbl1, tbl2"
);
}
}