1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use std::collections::HashMap;
use std::sync::RwLock;

use crate::build::{mysql_build_insert_script, pg_build_insert_script};
use crate::{
    DatabaseType, QueryWrapper, RdbcDmlValue, RdbcSQL, RdbcTable, RdbcTableColumn, RdbcTableInner,
    RdbcValue,
};

pub struct InsertWrapper {
    driver_: RwLock<Option<DatabaseType>>,
    table_: Vec<RdbcTableInner>,
    join_: Option<Vec<RdbcTableInner>>,
    column_: Vec<RdbcTableColumn>,
    values_: Vec<RdbcDmlValue>,
    column_values: Vec<(RdbcTableColumn, RdbcDmlValue)>,
    query_: Option<QueryWrapper>,
}

impl InsertWrapper {
    pub fn new() -> InsertWrapper {
        InsertWrapper {
            driver_: RwLock::new(None),
            table_: Vec::new(),
            join_: None,
            column_: Vec::new(),
            values_: Vec::new(),
            column_values: Vec::new(),
            query_: None,
        }
    }
    pub fn set_driver(&self, driver: DatabaseType) -> &Self {
        *self.driver_.write().unwrap() = Some(driver);
        self
    }

    pub fn get_table(&self) -> &Vec<RdbcTableInner> {
        &self.table_
    }
    pub fn get_column(&self) -> &Vec<RdbcTableColumn> {
        &self.column_
    }
    pub fn get_values(&self) -> &Vec<RdbcDmlValue> {
        &self.values_
    }
    pub fn get_column_values(&self) -> &Vec<(RdbcTableColumn, RdbcDmlValue)> {
        &self.column_values
    }
    pub fn get_query(&self) -> Option<&QueryWrapper> {
        self.query_.as_ref()
    }
}

impl InsertWrapper {
    pub fn insert_query(&mut self, query: QueryWrapper) -> &mut Self {
        self.query_ = Some(query);
        self
    }

    pub fn insert_column<TC>(&mut self, column: TC) -> &mut Self
    where
        RdbcTableColumn: From<TC>,
    {
        self.column_.push(RdbcTableColumn::from(column));
        self
    }
    pub fn insert_value<RV>(&mut self, value: RV) -> &mut Self
    where
        RdbcDmlValue: From<RV>,
    {
        self.values_.push(RdbcDmlValue::from(value));
        self
    }

    pub fn insert_column_value<TC, RV>(&mut self, column: TC, value: RV) -> &mut Self
    where
        RdbcTableColumn: From<TC>,
        RdbcDmlValue: From<RV>,
    {
        self.column_values
            .push((RdbcTableColumn::from(column), RdbcDmlValue::from(value)));
        self
    }
}
impl RdbcTable for InsertWrapper {
    fn get_table_mut(&mut self) -> &mut Vec<RdbcTableInner> {
        self.table_.as_mut()
    }
    fn get_join_mut(&mut self) -> &mut Vec<RdbcTableInner> {
        if self.join_.is_none() {
            self.join_ = Some(vec![]);
        }
        self.join_.as_mut().unwrap()
    }
}

impl RdbcSQL for InsertWrapper {
    fn build_script(&self, database_type: DatabaseType) -> (String, HashMap<String, RdbcValue>) {
        match database_type {
            DatabaseType::Postgres => pg_build_insert_script(self),
            DatabaseType::MySQL => mysql_build_insert_script(self),
        }
    }
}