#[cfg(feature="with-json")]
use serde_json::Value as JsonValue;
use crate::{backend::QueryBuilder, types::*, expr::*, value::*, prepare::*};
#[derive(Debug, Clone)]
pub struct UpdateStatement {
pub(crate) table: Option<Box<TableRef>>,
pub(crate) values: Vec<(String, Box<SimpleExpr>)>,
pub(crate) wherei: Option<Box<SimpleExpr>>,
pub(crate) orders: Vec<OrderExpr>,
pub(crate) limit: Option<Value>,
}
impl Default for UpdateStatement {
fn default() -> Self {
Self::new()
}
}
impl UpdateStatement {
pub fn new() -> Self {
Self {
table: None,
values: Vec::new(),
wherei: None,
orders: Vec::new(),
limit: None,
}
}
#[allow(clippy::wrong_self_convention)]
pub fn table<T>(&mut self, tbl_ref: T) -> &mut Self
where T: IntoTableRef {
self.table = Some(Box::new(tbl_ref.into_table_ref()));
self
}
#[deprecated(
since = "0.5.0",
note = "Please use the UpdateStatement::table function instead"
)]
#[allow(clippy::wrong_self_convention)]
pub fn into_table<T>(&mut self, table: T) -> &mut Self
where T: IntoTableRef {
self.table(table)
}
pub fn value_expr<T>(&mut self, col: T, exp: SimpleExpr) -> &mut Self
where T: IntoIden {
self.push_boxed_value(col.into_iden().to_string(), exp);
self
}
#[cfg(feature="with-json")]
#[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
pub fn json(&mut self, values: JsonValue) -> &mut Self {
match values {
JsonValue::Object(_) => (),
_ => unimplemented!(),
}
for (k, v) in values.as_object().unwrap() {
let v = json_value_to_sea_value(v);
self.push_boxed_value(k.into(), SimpleExpr::Value(v));
}
self
}
pub fn values<T>(&mut self, values: Vec<(T, Value)>) -> &mut Self
where T: IntoIden {
for (k, v) in values.into_iter() {
self.push_boxed_value(k.into_iden().to_string(), SimpleExpr::Value(v));
}
self
}
pub fn value<T>(&mut self, col: T, value: Value) -> &mut Self
where T: IntoIden {
self.push_boxed_value(col.into_iden().to_string(), SimpleExpr::Value(value));
self
}
fn push_boxed_value(&mut self, k: String, v: SimpleExpr) -> &mut Self {
self.values.push((k, Box::new(v)));
self
}
pub fn and_where(&mut self, other: SimpleExpr) -> &mut Self {
self.and_or_where(BinOper::And, other)
}
pub fn or_where(&mut self, other: SimpleExpr) -> &mut Self {
self.and_or_where(BinOper::Or, other)
}
fn and_or_where(&mut self, bopr: BinOper, right: SimpleExpr) -> &mut Self {
self.wherei = Self::merge_expr(
self.wherei.take(),
match bopr {
BinOper::And => BinOper::And,
BinOper::Or => BinOper::Or,
_ => panic!("not allow"),
},
right
);
self
}
fn merge_expr(left: Option<Box<SimpleExpr>>, bopr: BinOper, right: SimpleExpr) -> Option<Box<SimpleExpr>> {
Some(Box::new(match left {
Some(left) => SimpleExpr::Binary(
left,
bopr,
Box::new(right)
),
None => right,
}))
}
pub fn order_by<T>(&mut self, col: T, order: Order) -> &mut Self
where T: IntoColumnRef {
self.orders.push(OrderExpr {
expr: SimpleExpr::Column(col.into_column_ref()),
order,
});
self
}
#[deprecated(
since = "0.9.0",
note = "Please use the [`UpdateStatement::order_by`] with a tuple as [`ColumnRef`]"
)]
pub fn order_by_tbl<T, C>
(&mut self, table: T, col: C, order: Order) -> &mut Self
where T: IntoIden, C: IntoIden {
self.order_by((table.into_iden(), col.into_iden()), order)
}
pub fn order_by_expr(&mut self, expr: SimpleExpr, order: Order) -> &mut Self {
self.orders.push(OrderExpr {
expr,
order,
});
self
}
pub fn order_by_customs<T>(&mut self, cols: Vec<(T, Order)>) -> &mut Self
where T: ToString {
let mut orders = cols.into_iter().map(
|(c, order)| OrderExpr {
expr: SimpleExpr::Custom(c.to_string()),
order,
}).collect();
self.orders.append(&mut orders);
self
}
pub fn order_by_columns<T>(&mut self, cols: Vec<(T, Order)>) -> &mut Self
where T: IntoColumnRef {
let mut orders = cols.into_iter().map(
|(c, order)| OrderExpr {
expr: SimpleExpr::Column(c.into_column_ref()),
order,
}).collect();
self.orders.append(&mut orders);
self
}
#[deprecated(
since = "0.9.0",
note = "Please use the [`UpdateStatement::order_by_columns`] with a tuple as [`ColumnRef`]"
)]
pub fn order_by_table_columns<T, C>
(&mut self, cols: Vec<(T, C, Order)>) -> &mut Self
where T: IntoIden, C: IntoIden {
self.order_by_columns(cols.into_iter().map(|(t, c, o)| ((t.into_iden(), c.into_iden()), o)).collect())
}
pub fn limit(&mut self, limit: u64) -> &mut Self {
self.limit = Some(Value::BigUnsigned(limit));
self
}
pub fn build_collect<T: QueryBuilder>(&self, query_builder: T, collector: &mut dyn FnMut(Value)) -> String {
let mut sql = SqlWriter::new();
query_builder.prepare_update_statement(self, &mut sql, collector);
sql.result()
}
pub fn build_collect_any(&self, query_builder: &dyn QueryBuilder, collector: &mut dyn FnMut(Value)) -> String {
let mut sql = SqlWriter::new();
query_builder.prepare_update_statement(self, &mut sql, collector);
sql.result()
}
pub fn build<T: QueryBuilder>(&self, query_builder: T) -> (String, Values) {
let mut values = Vec::new();
let mut collector = |v| values.push(v);
let sql = self.build_collect(query_builder, &mut collector);
(sql, Values(values))
}
pub fn build_any(&self, query_builder: &dyn QueryBuilder) -> (String, Values) {
let mut values = Vec::new();
let mut collector = |v| values.push(v);
let sql = self.build_collect_any(query_builder, &mut collector);
(sql, Values(values))
}
pub fn to_string<T: QueryBuilder>(&self, query_builder: T) -> String {
let (sql, values) = self.build_any(&query_builder);
inject_parameters(&sql, values.0, &query_builder)
}
}