oracle_sql_tools/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use oracle::Connection;
4
5use statements::{PreppedGridData, PreppedRowData};
6use format_data::{FormatData, FormattedData};
7use types::DatatypeIndexes;
8
9pub mod statements;
10pub mod types;
11pub mod utils;
12pub mod format_data;
13
14/// A trait to prepare either a vector or a 2-dimensional vector for a SQL query
15///
16/// The trait either returns [`statements::PreppedRowData`] or [`statements::PreppedGridData`] respectively
17///
18/// Using a vector to select specific columns from a table:
19///
20/// ```no_run
21/// let conn: oracle::Connection = match Connection::connect("<USERNAME>", "<PASSWORD>", "<IP ADDRESS>")?; 
22///
23/// let col_names: Vec<&str> = vec!["Employee ID", "Name", "Job Title", "Department", "Business Unit"];
24///
25/// let table_data: Vec<Vec<Option<String>>> = col_names.prep_data(conn).select("MY_TABLE")?;
26/// ```
27///
28/// Using a 2-dimensional vector to insert data:
29///
30/// ```no_run
31/// let conn: oracle::Connection = match Connection::connect("<USERNAME>", "<PASSWORD>", "<IP ADDRESS>")?; 
32///
33/// let data: Vec<Vec<String>> = vec![
34///     vec!["ColA".to_string(), "ColB".to_string(), "ColC".to_string()],
35///     vec!["A1".to_string(), "B1".to_string(), "C1".to_string()],
36///     vec!["A2".to_string(), "B2".to_string(), "C2".to_string()],
37///     vec!["A3".to_string(), "B3".to_string(), "C3".to_string()],
38/// ];
39/// 
40/// data.prep_data(conn).insert("MY_TABLE")?;
41/// Ok(())
42/// ```
43pub trait PrepData<T: FormatData> {
44    type Prep;
45
46    fn prep_data(self, connection: Connection) -> Self::Prep;
47}
48
49impl<T: FormatData> PrepData<T> for Vec<Vec<T>> {
50    type Prep = PreppedGridData;
51
52    fn prep_data(self, connection: Connection) -> Self::Prep  {
53        // get's the 'dominate' datatype from each column
54        // weighted in order: VARCHAR2, FLOAT, INT, DATE
55        let mut is_varchar: Vec<usize> = Vec::new();
56        let mut is_float: Vec<usize> = Vec::new();
57        let mut is_int: Vec<usize> = Vec::new();
58        let mut is_date: Vec<usize> = Vec::new();
59
60        let mut data = Vec::new();
61        let mut y_index: usize = 0 as usize;
62        for row in self {
63            let mut inner_vec = Vec::new();
64            let mut x_index: usize = 0 as usize;
65            for cell in row {
66                let formatted_cell = cell.fmt_data();
67                if y_index > 0 {
68                    match &formatted_cell {
69                        FormattedData::STRING(_) => is_varchar.push(x_index),
70                        FormattedData::INT(_) => is_int.push(x_index),
71                        FormattedData::FLOAT(_) => is_float.push(x_index),
72                        FormattedData::DATE(_) => is_date.push(x_index),
73                        FormattedData::TIMESTAMP(_) => is_date.push(x_index),
74                        FormattedData::EMPTY => { 
75                            inner_vec.push(formatted_cell); 
76                            x_index += 1 as usize; 
77                            continue;
78                        },
79                    }
80                }
81                inner_vec.push(formatted_cell);
82                x_index += 1 as usize;
83            }
84            data.push(inner_vec);
85            y_index += 1 as usize;
86        }
87
88        let data_indexes = DatatypeIndexes {
89            is_varchar,
90            is_float,
91            is_int,
92            is_date,
93        }.find_uniques();
94
95        Self::Prep {
96            data,
97            conn: connection,
98            data_indexes
99        }
100    }
101}
102
103impl<T: FormatData> PrepData<T> for Vec<T> {
104    type Prep = PreppedRowData;
105
106    fn prep_data(self, connection: Connection) -> Self::Prep {
107        let mut data = Vec::new();
108        for val in self { data.push(val.fmt_data().to_string()) }
109        Self::Prep {
110            data,
111            conn: connection,
112        }
113    }
114}