use std::mem;
use from::{Table, RcTable};
use field::{Field, RcField};
use select_query::{SelectQuery, LimitMany, Select, NoResult};
use expression::{
Expression, ToExpression, UntypedExpression,
ExprValue, ToExprValue};
#[allow(dead_code)]
#[deriving(Clone)]
pub enum Insert<T, V, M> {
DefaultValues,
Values(Vec<V>),
UntypedValues(Vec<Vec<ExprValue<()>>>),
FromSelect(SelectQuery<T, LimitMany, M>)
}
#[allow(dead_code)]
#[deriving(Clone)]
pub struct InsertQuery<T, V, M, RT, RL> {
into: RcTable,
cols: Option<Vec<RcField>>,
values: Insert<T, V, M>,
returning: Option<Select>
}
macro_rules! insert(
($name:ident, $(($t:ident, $arg:ident)),+) => (
fn $name<$($t:Clone,)+>(&self, $($arg: &NamedField<$t>,)+) -> InsertQuery<($($t,)+), ($(ExprValue<$t>,)+), M, (), ()> {
let mut cols = vec![];
$(cols.push((*$arg).upcast_field());)+
let mut query = InsertQuery::new(self);
query.cols = Some(cols);
query
}
)
)
macro_rules! insertable(
() => (
pub trait Insertable<M: Clone>: Table {
fn insert_all(&self) -> InsertQuery<(), (), M, (), ()> {
InsertQuery::new(self)
}
fn insert_fields(&self, fields: &[&Field]) -> InsertQuery<(), (), M, (), ()> {
let mut cols = vec![];
for field in fields.iter() {
cols.push(field.upcast_field())
}
InsertQuery::new_with_cols(self, cols)
}
}
)
)
insertable!()
#[allow(dead_code)]
impl<T: Clone, V: Clone, M: Clone, RT: Clone, RL: Clone> InsertQuery<T, V, M, RT, RL> {
pub fn new(into: &Table) -> InsertQuery<T, V, M, RT, RL> {
InsertQuery {
into: into.upcast_table(),
cols: None,
values: Insert::DefaultValues,
returning: None
}
}
pub fn new_with_cols(into: &Table, cols: Vec<RcField>) -> InsertQuery<T, V, M, RT, RL> {
InsertQuery {
into: into.upcast_table(),
cols: Some(cols),
values: Insert::DefaultValues,
returning: None
}
}
pub fn get_into(&self) -> &RcTable { &self.into }
pub fn get_cols(&self) -> &Option<Vec<RcField>> { &self.cols }
pub fn get_values(&self) -> &Insert<T, V, M> { &self.values }
pub fn get_returning(&self) -> &Option<Select> { &self.returning }
pub fn push(&mut self, value: V) {
let mut reassign = false;
match &self.values {
&Insert::DefaultValues | &Insert::FromSelect(_) => {
reassign = true;
},
_ => ()
}
if reassign {
self.values = Insert::Values(vec![value])
} else {
match &mut self.values {
&Insert::Values(ref mut values) => {
values.push(value)
},
_ => ()
}
}
}
pub fn push_untyped(&mut self, values: &[&ToExpression<()>]) {
let mut reassign = false;
match &self.values {
&Insert::DefaultValues | &Insert::FromSelect(_) => {
reassign = true;
},
_ => ()
}
let values_vec = values.iter().map(|v| v.as_expr().to_expr_val()).collect();
if reassign {
self.values = Insert::UntypedValues(vec![values_vec])
} else {
match &mut self.values {
&Insert::UntypedValues(ref mut values) => {
values.push(values_vec)
},
_ => ()
}
}
}
pub fn from_select(&self, select: SelectQuery<T, LimitMany, M>) -> InsertQuery<T, V, M, RT, RL> {
with_clone!(self, query, query.values = Insert::FromSelect(select))
}
}
impl<T: Clone, V: Clone, M: Clone, RT, RL> InsertQuery<T, V, M, RT, RL> {
pub fn returning_1<T1: Clone>(mut self, field: &Expression<T1>) -> InsertQuery<T, V, M, (T1), LimitMany> {
self.returning = Some(Select::Only(vec![field.upcast_expression()]));
unsafe{ mem::transmute(self) }
}
pub fn returning_2<T1: Clone, T2: Clone>(mut self, field1: &Expression<T1>, field2: &Expression<T2>) -> InsertQuery<T, V, M, (T1, T2), LimitMany> {
self.returning = Some(Select::Only(vec![field1.upcast_expression(), field2.upcast_expression()]));
unsafe{ mem::transmute(self) }
}
pub fn returning(mut self, fields: &[&UntypedExpression]) -> InsertQuery<T, V, M, (), LimitMany> {
self.returning = Some(Select::Only(fields.iter().map(|f| f.upcast_expression()).collect()));
unsafe{ mem::transmute(self) }
}
pub fn returning_all(mut self) -> InsertQuery<T, V, M, (), LimitMany> {
self.returning = Some(Select::All);
unsafe{ mem::transmute(self) }
}
pub fn no_returning(mut self) -> InsertQuery<T, V, M, (), NoResult> {
self.returning = None;
unsafe{ mem::transmute(self) }
}
}