use super::Simplify;
use toasty_core::stmt;
impl Simplify<'_> {
pub(super) fn simplify_expr_list(&mut self, expr: &mut stmt::ExprList) -> Option<stmt::Expr> {
if let Some(expr) = self.simplify_expr_list_all_values(expr) {
return Some(expr);
}
if let Some(expr) = self.simplify_expr_list_insert_stmt(expr) {
return Some(expr);
}
None
}
fn simplify_expr_list_all_values(&mut self, expr: &mut stmt::ExprList) -> Option<stmt::Expr> {
let all_values = expr.items.iter().all(|expr| expr.is_value());
if all_values {
let mut values = vec![];
for expr in expr.items.drain(..) {
let stmt::Expr::Value(value) = expr else {
panic!()
};
values.push(value);
}
Some(stmt::Value::list_from_vec(values).into())
} else {
None
}
}
fn simplify_expr_list_insert_stmt(&mut self, expr: &mut stmt::ExprList) -> Option<stmt::Expr> {
for item in &expr.items {
let stmt::Expr::Stmt(expr_stmt) = item else {
return None;
};
let insert = expr_stmt.stmt.as_insert()?;
if !insert.source.single {
return None;
}
match &insert.returning {
Some(stmt::Returning::Model { .. }) => {}
_ => return None,
}
if !insert.target.is_model() {
return None;
}
}
let first_insert = match &expr.items[0] {
stmt::Expr::Stmt(s) => s.stmt.as_insert().unwrap(),
_ => unreachable!(),
};
let first_target_model = match &first_insert.target {
stmt::InsertTarget::Model(model_id) => model_id,
_ => unreachable!(),
};
let first_returning = first_insert.returning.as_ref().unwrap();
for item in &expr.items[1..] {
let insert = match item {
stmt::Expr::Stmt(s) => s.stmt.as_insert().unwrap(),
_ => unreachable!(),
};
let target_model = match &insert.target {
stmt::InsertTarget::Model(model_id) => model_id,
_ => unreachable!(),
};
if target_model != first_target_model {
return None;
}
if insert.returning.as_ref().unwrap() != first_returning {
return None;
}
}
let mut items = expr.items.drain(..).collect::<Vec<_>>();
let mut merged_insert = match items.remove(0) {
stmt::Expr::Stmt(s) => s.stmt.into_insert_unwrap(),
_ => unreachable!(),
};
for item in items {
let insert = match item {
stmt::Expr::Stmt(s) => s.stmt.into_insert_unwrap(),
_ => unreachable!(),
};
merged_insert.merge(insert);
}
merged_insert.source.single = false;
Some(stmt::Expr::stmt(stmt::Statement::Insert(merged_insert)))
}
}