use crate::{query::QueryBuilder, table::Table};
use mysql::{prelude::Queryable, PooledConn};
use rusqlite::Error as RusqliteError;
use log::{debug, info};
use std::fmt::Error;
pub fn insert<T: Table>(
conn: &mut PooledConn,
table_rows: Vec<T>,
) -> Result<String, RusqliteError> {
let mut statements: Vec<String> = Vec::new();
for (index, table_row) in table_rows.iter().enumerate() {
match generate_statement(table_row, index == 0) {
Ok(statement) => statements.push(statement),
Err(_) => return Err(RusqliteError::InvalidQuery),
}
}
let joined_statements = statements.join(", ");
match conn.query_drop(&joined_statements) {
Ok(_) => info!("Inserted into table, done."),
Err(err) => eprintln!("Error: {}", err),
}
info!("Inserted into table, done.");
Ok(joined_statements)
}
pub fn into<'a, T: Table + Default>(
conn: &'a mut PooledConn,
columns: Vec<String>,
subquery: Box<dyn QueryBuilder<'a> + 'a>,
) -> Result<String, RusqliteError> {
let statement = generate_insert_into_statement::<T>(columns, subquery);
let sql = statement?;
let _ = conn.query_drop(&sql);
info!("Inserted into table, done.");
Ok(sql)
}
fn generate_insert_into_statement<'a, T: Table + Default>(
columns: Vec<String>,
subquery: Box<dyn QueryBuilder<'a> + 'a>,
) -> Result<String, RusqliteError> {
let columns_str = columns.join(", ");
let subquery_str = subquery.to_sql();
let table_row = T::default();
let table_name = table_row.get_name().replace("\"", "").replace("\\", "");
let sql = format!(
"INSERT INTO {} ({}) {}",
table_name, columns_str, subquery_str
);
Ok(sql)
}
fn generate_statement<T: Table>(table_row: &T, first_statement: bool) -> Result<String, Error> {
let mut columns_str = String::new();
let mut values_str = String::new();
let column_fields = table_row.get_column_fields();
let column_values = table_row.get_column_values();
for (column_name, value) in column_fields.iter().zip(column_values.iter()) {
if table_row.is_auto_increment_primary_key(value) {
debug!("Skipping AutoIncrementPrimaryKey field in SQL statement generation.");
continue;
}
let escaped_value = value.replace("'", "''");
columns_str.push_str(&format!("{}, ", column_name));
values_str.push_str(&format!("'{}', ", escaped_value)); }
let table_name = table_row.get_name().replace("\"", "").replace("\\", "");
if !columns_str.is_empty() {
columns_str.pop();
columns_str.pop();
}
if !values_str.is_empty() {
values_str.pop();
values_str.pop();
}
let sql = if first_statement {
format!(
"INSERT INTO {} ({}) VALUES ({})",
table_name, columns_str, values_str
)
} else {
format!("({})", values_str)
};
debug!("{}", sql);
Ok(sql)
}