use std::rc::Rc;
#[cfg(feature="with-json")]
use serde_json::Value as JsonValue;
use crate::{backend::QueryBuilder, types::*, value::*, prepare::*};
#[derive(Debug, Clone)]
pub struct InsertStatement {
pub(crate) table: Option<Box<TableRef>>,
pub(crate) columns: Vec<Rc<dyn Iden>>,
pub(crate) values: Vec<Vec<Value>>,
}
impl Default for InsertStatement {
fn default() -> Self {
Self::new()
}
}
impl InsertStatement {
pub fn new() -> Self {
Self {
table: None,
columns: Vec::new(),
values: Vec::new(),
}
}
#[allow(clippy::wrong_self_convention)]
pub fn into_table<T>(&mut self, tbl_ref: T) -> &mut Self
where T: IntoTableRef {
self.table = Some(Box::new(tbl_ref.into_table_ref()));
self
}
pub fn columns<C>(&mut self, columns: Vec<C>) -> &mut Self
where C: IntoIden {
self.columns = columns.into_iter().map(|c| c.into_iden()).collect();
self
}
pub fn values(&mut self, values: Vec<Value>) -> Result<&mut Self, String> {
if self.columns.len() != values.len() {
return Err(format!("columns and values length mismatch: {} != {}", self.columns.len(), values.len()));
}
self.values.push(values);
Ok(self)
}
pub fn values_panic(&mut self, values: Vec<Value>) -> &mut Self {
self.values(values).unwrap()
}
#[cfg(feature="with-json")]
#[cfg_attr(docsrs, doc(cfg(feature = "with-json")))]
pub fn json(&mut self, object: JsonValue) -> &mut Self {
match object {
JsonValue::Object(_) => (),
_ => panic!("object must be JsonValue::Object"),
}
let mut values = Vec::new();
if self.columns.is_empty() {
let map = object.as_object().unwrap();
let mut keys: Vec<String> = map.keys().cloned().collect();
keys.sort();
for k in keys.iter() {
self.columns.push(Rc::new(Alias::new(k)));
}
}
for col in self.columns.iter() {
values.push(
match object.get(col.to_string()) {
Some(value) => json_value_to_sea_value(value),
None => Value::Null,
}
);
}
self.values.push(values);
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_insert_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_insert_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)
}
}