oracle_sql_tools 0.2.0

An extension to the Rust-Oracle crate to make simple queries easy to implement.
Documentation
use std::collections::HashMap;
use oracle::Connection;

use crate::{format_data::FormattedData, types::{errors::OracleSqlToolsError, DatatypeIndexes}, utils::remove_invalid_chars};
use super::mutate_row::MutateRow;

pub(crate) trait CreateFromInsert {
    fn create_table(&self, table_name: &str, col_indexes: &DatatypeIndexes, conn: &Connection) 
    -> Result<(), OracleSqlToolsError>;
}

macro_rules! compare_data_length {
    ($varchar_col_size:ident, $val:ident, $x:ident) => {
        match $varchar_col_size.get(&$x) {
            Some(prev_val) => {
                if $val.to_string().len() > *prev_val { $varchar_col_size.insert($x, $val.to_string().len()) }
                else { continue }
            },
            None => $varchar_col_size.insert($x, $val.to_string().len()),
        }
    };
}

impl CreateFromInsert for Vec<Vec<FormattedData>> {
    fn create_table(&self, table_name: &str, data_type_indexes: &DatatypeIndexes, conn: &Connection) 
    -> Result<(), OracleSqlToolsError> {
        if self.len() <= 1 { return Err(OracleSqlToolsError::NoData); }

        let mut varchar_col_size: HashMap<usize, usize> = HashMap::new();
        for x in 0..self[0].len() {
            if !data_type_indexes.is_varchar.contains(&x) { continue; };
            for y in 1..self.len() {
                match &self[y][x] {
                    FormattedData::STRING(val) => compare_data_length!(varchar_col_size, val, x),
                    FormattedData::INT(val) => compare_data_length!(varchar_col_size, val, x),
                    FormattedData::FLOAT(val) => compare_data_length!(varchar_col_size, val, x),
                    FormattedData::DATE(val) => compare_data_length!(varchar_col_size, val, x),
                    FormattedData::TIMESTAMP(val) => compare_data_length!(varchar_col_size, val, x),
                    FormattedData::EMPTY => { let val = 0 as usize; compare_data_length!(varchar_col_size, val, x) },
                };
            }
        }

        let mut sql_data_types = Vec::new();
        for x in 0..self[0].len() {
            if data_type_indexes.is_varchar.contains(&x) {
                match varchar_col_size.get(&x) {
                    Some(val) => sql_data_types.push(format!("VARCHAR2({})", val)),
                    None => continue,
                }
            } else if data_type_indexes.is_int.contains(&x) { sql_data_types.push(format!("NUMBER")) }
            else if data_type_indexes.is_float.contains(&x) { sql_data_types.push(format!("FLOAT")) }
            else if data_type_indexes.is_date.contains(&x) { sql_data_types.push(format!("DATE")) }
            else { sql_data_types.push(format!("VARCHAR2(50)")) }
        }

        let mut col_names = Vec::new();
        for (i, col_header) in self[0].to_string().iter().enumerate() {
            col_names.push(format!("{} {}", remove_invalid_chars(col_header), sql_data_types[i]))
        }
        let create_table_stmt = format!("CREATE TABLE {} ({})", table_name, col_names.join(", "));
        conn.execute(&create_table_stmt, &[])?;
        conn.commit()?;
        Ok(())
    }
}