sql_tools 0.11.10

A rust crate meant to make SQL queries simple and communication between various SQL versions easy.
Documentation
use crate::{
    Error, SQLImplementation,
    data_types::{SQLDataTypes, ToSQLData},
    statements::select::{
        SelectProps,
        sql_implementations::{
            multithread::multithread_execution, mutate_query::limit_offset,
            shared_select_operations, sqlite::execution::sqlite_handle_execution,
        },
    },
};

pub mod execution;

pub(crate) fn build_select_sqlite(
    select_props: SelectProps,
) -> Result<Vec<Vec<Box<SQLDataTypes>>>, Error> {
    let conn_info = match &select_props.connect {
        SQLImplementation::Oracle(_) => return Err(Error::SQLVariationError),
        SQLImplementation::SQLite(connect) => connect,
    };

    let conn = conn_info.initialize_connection()?;

    let table = &select_props.table;
    let cols = &select_props
        .columns
        .iter()
        .map(|col| -> Result<String, Error> {
            let col = match col {
                crate::statements::select::Column::Name(name) => {
                    format!("{}.{}", name.table, name.name)
                }
                crate::statements::select::Column::Function(function) => format!("{}", function),
                crate::statements::select::Column::Varchar(varchar) => format!("'{}'", varchar),
                crate::statements::select::Column::ALL(all) => {
                    let columns = conn_info.table_info(&table)?;
                    columns
                        .iter()
                        .map(|col| format!("{}.{}", all, col))
                        .collect::<Vec<String>>()
                        .join(", ")
                }
            };
            Ok(col)
        })
        .collect::<Result<Vec<String>, Error>>()?;

    let columns = &cols.join(", ");
    let head = &columns.split(",").collect::<Vec<&str>>();
    let header = head
        .iter()
        .map(|col| {
            let col = col.split(".").collect::<Vec<&str>>();
            let col = col[col.len() - 1];
            let col = col.split(" ").collect::<Vec<&str>>();
            let col = col[col.len() - 1];
            let col = col.split(" as ").collect::<Vec<&str>>();
            let col = col[col.len() - 1];
            Box::new(col.to_sql_fmt())
        })
        .collect::<Vec<Box<SQLDataTypes>>>();
    let columns = &cols.join(", ");

    let mut query = format!("SELECT {} FROM {}", &columns, &table,);
    let mut count_sql = format!("SELECT COUNT(*) FROM {}", &table);

    query = shared_select_operations(&select_props, query)?;
    count_sql = shared_select_operations(&select_props, count_sql)?;

    query = limit_offset(&select_props, query);
    count_sql = limit_offset(&select_props, count_sql);

    let mut count: Option<usize> = None;
    let mut stmt = conn.prepare(&count_sql)?;
    let count_query = stmt.query_map([], |row| Ok(row.get(0)?))?;
    for res in count_query {
        let row = res?;
        count = if let Some(val) = row {
            Some(val)
        } else {
            Some(0usize)
        }
    }

    multithread_execution(SQLImplementation::SQLite(conn_info.to_owned()) ,sqlite_handle_execution, select_props, &header, query, count)
}

pub(crate) fn build_select_sqlite_single_thread(
    select_props: SelectProps,
) -> Result<Vec<Vec<Box<SQLDataTypes>>>, Error> {
    let conn_info = match &select_props.connect {
        SQLImplementation::Oracle(_) => return Err(Error::SQLVariationError),
        SQLImplementation::SQLite(connect) => connect,
    };

    let table = &select_props.table;
    let cols = &select_props
        .columns
        .iter()
        .map(|col| -> Result<String, Error> {
            let col = match col {
                crate::statements::select::Column::Name(name) => {
                    format!("{}.{}", name.table, name.name)
                }
                crate::statements::select::Column::Function(function) => format!("{}", function),
                crate::statements::select::Column::Varchar(varchar) => format!("'{}'", varchar),
                crate::statements::select::Column::ALL(all) => {
                    let columns = conn_info.table_info(&table)?;
                    columns
                        .iter()
                        .map(|col| format!("{}.{}", all, col))
                        .collect::<Vec<String>>()
                        .join(", ")
                }
            };
            Ok(col)
        })
        .collect::<Result<Vec<String>, Error>>()?;

    let columns = &cols.join(", ");

    let conn = conn_info.initialize_connection()?;

    let mut query = format!("SELECT {} FROM {}", &columns, &table,);

    query = shared_select_operations(&select_props, query)?;

    query = limit_offset(&select_props, query);

    let mut stmt = conn.prepare(&query)?;
    let mut rows = stmt.query([])?;
    let mut res = Vec::new();
    let header = columns.split(",").collect::<Vec<&str>>();
    while let Some(row) = rows.next()? {
        let p = header
            .iter()
            .enumerate()
            .map(|(idx, _)| Box::new(row.get::<usize, SQLDataTypes>(idx).unwrap()))
            .collect::<Vec<Box<SQLDataTypes>>>();
        res.push(p)
    }

    if select_props.return_header {
        let header = header
            .iter()
            .map(|col| Box::new(col.to_sql_fmt()))
            .collect::<Vec<Box<SQLDataTypes>>>();
        let header = header
            .iter()
            .map(|head| {
                let head = head.to_string();
                let head = head.split(" as ").collect::<Vec<&str>>();
                let head = head[head.len() - 1];
                let head = head.split(" ").collect::<Vec<&str>>();
                let head = head[head.len() - 1];
                let head = head.split(".").collect::<Vec<&str>>();
                let head = head[head.len() - 1];
                Box::new(head.to_sql_fmt())
            })
            .collect::<Vec<Box<SQLDataTypes>>>();
        let header = vec![header.to_owned()];
        res.splice(..0, header.iter().cloned());
    }

    Ok(res)
}