#![allow(unused)] #![allow(warnings)] use crate::DB_URL; use sqlx::{mysql::*, Connection, Error, Executor, FromRow, Row}; use std::any::Any; use tokio::time::{sleep, Duration}; // check specific table in database. If the table exists it returns true, or false. pub async fn exists_table(table_name: &String) -> bool { let mut query_base = String::from("SELECT 1 FROM information_schema.tables WHERE table_schema = 'tradingbot' AND table_name = '"); query_base.push_str(table_name.as_str()); query_base.push('\''); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let exists_table = sqlx::query(&query_base).fetch_all(&mut conn).await.unwrap(); conn.close().await; !exists_table.is_empty() } // check specific record in table. If the record exists it returns true, or false. pub async fn exists_record(table_name: &String, condition: &Option) -> bool { #[derive(Debug, FromRow)] struct Success { success: i32, } let mut query_base = String::from("SELECT EXISTS (SELECT * FROM "); query_base.push_str(table_name.as_str()); match condition { Some(T) => { query_base.push_str(" WHERE "); query_base.push_str(T.as_str()); } None => {} } query_base.push_str(" LIMIT 1) as success;"); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let mut exists_record = sqlx::query_as::<_, Success>(&query_base) .fetch_one(&mut conn) .await; while exists_record.is_err() { sleep(Duration::from_millis(200)).await; exists_record = sqlx::query_as::<_, Success>(&query_base) .fetch_one(&mut conn) .await; } let result = exists_record.unwrap(); conn.close().await; if result.success == 0 { false } else { true } } // make a new table. If the job succeeds it returns true, or false. // columns_vec: Vec<(column name, type, option)> pub async fn new_table( table_name: &String, columns_vec: &Vec<(&str, &str, Option<&str>)>, table_condition: &Option<&str>, ) -> Result<(), Box> { // query building. let mut query = String::from("CREATE TABLE IF NOT EXISTS "); query.push_str(table_name); query.push('('); for element in columns_vec.iter() { query.push_str(element.0); query.push(' '); query.push_str(element.1); query.push(' '); match element.2 { None => {} _ => { if (element.2.unwrap().contains("UNSIGNED")) { query.push_str("UNSIGNED "); } if (element.2.unwrap().contains("UN")) { query.push_str("UNSIGNED "); } if (element.2.unwrap().contains("PK")) { query.push_str("PRIMARY KEY "); } if (element.2.unwrap().contains("NOTNULL")) { query.push_str("NOT NULL"); } if (element.2.unwrap().contains("AI")) { query.push_str("AUTO_INCREMENT "); } } } query.push(','); } query.pop(); query.push_str(")"); match table_condition { Some(T) => { query.push(' '); query.push_str(T); } None => {} } query.push(';'); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let mut query_result = sqlx::query(&query).execute(&mut conn).await; while let Err(e) = query_result { sleep(Duration::from_millis(200)).await; query_result = sqlx::query(&query).execute(&mut conn).await; } conn.close().await?; Ok(()) } // drop a table. If the job succeeds it returns true, or false. pub async fn drop_table(table_name: &String) -> Result { let mut query = String::from("DROP TABLE `tradingbot`.`"); query.push_str(table_name); query.push_str("`;"); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let query_result = sqlx::query(&query).execute(&mut conn).await; conn.close().await?; query_result } // copy data from source table to destination table // both table structures must be same pub async fn copy_table_data( source_table: &String, destination_table: &String, ) -> Result<(), Box> { // query building. let mut query = String::from("INSERT INTO "); query.push_str(destination_table.as_str()); query.push_str(" (SELECT * FROM "); query.push_str(source_table.as_str()); query.push_str(");"); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let mut query_result = sqlx::query(&query).execute(&mut conn).await; while let Err(e) = query_result { query_result = sqlx::query(&query).execute(&mut conn).await; sleep(Duration::from_millis(200)).await; } conn.close().await?; Ok(()) } // insert a record into specific table // e.g. column: ["name", "class", "age"], // values: [["Kim", "blue", "7"] pub async fn insert_one_record( table_name: &String, columns: &Vec<&str>, values: &Vec, ) -> Result { // query building. let mut query = String::from("INSERT INTO "); query.push_str(table_name); query.push('('); for element in (*columns).clone() { query.push_str(element); query.push_str(","); } query.pop(); query.push_str(") "); query.push_str("VALUES("); for element in (*values).clone() { query.push('\"'); if element == "true" { query.push('1'); } else if element == "false" { query.push('0'); } else { query.push_str(element.as_str()); } query.push('\"'); query.push_str(","); } query.pop(); query.push_str(");"); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let query_result = sqlx::query(&query).execute(&mut conn).await; conn.close().await?; query_result } pub async fn copy_record( src_table: &String, dest_table: &String, columns: &str, condition: &Option, ) -> Result { // query building. let mut query = String::from("INSERT INTO "); query.push_str(dest_table.as_str()); query.push_str(" ("); query.push_str(columns); query.push_str(") SELECT "); query.push_str(columns); query.push_str(" FROM "); query.push_str(src_table.as_str()); match condition { None => {} Some(condition) => { query.push(' '); query.push_str(condition.as_str()); query.push(';'); } } let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let query_result = sqlx::query(&query).execute(&mut conn).await; conn.close().await?; query_result } // insert several records into specific table at once // the length of columns and each inner vector in values should be same. // e.g. column: ["name", "class", "age"], // values: [["Kim", "blue", "7"], ["Lee", "red", "9"], ...] pub async fn insert_records( table_name: &String, columns: &Vec<&str>, values: &Vec>, ) -> Result<(), Box> { // query building. let mut query = String::from("INSERT INTO "); query.push_str(table_name); query.push('('); for element in (*columns).clone() { query.push_str(element); query.push_str(","); } query.pop(); query.push_str(") "); query.push_str("VALUES "); for element in (*values).clone() { query.push('('); for element in element.into_iter() { query.push('\''); if element == "true" { query.push('1'); } else if element == "false" { query.push('0'); } else { query.push_str(element.as_str()); } query.push_str("\',"); } query.pop(); query.push_str("),"); } query.pop(); query.push_str(";"); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let mut query_result = sqlx::query(&query).execute(&mut conn).await; while let Err(e) = query_result { query_result = sqlx::query(&query).execute(&mut conn).await; sleep(Duration::from_millis(200)).await; } conn.close().await?; Ok(()) } // update a record in table // record: [column name, value], condition: (column name, value) pub async fn update_record( table_name: &String, record: &Vec<(&str, &str)>, condition: &Vec<(&str, &str)>, ) -> Result { // query building. let mut query = String::from("UPDATE "); query.push_str(table_name); query.push_str(" SET "); for element in record.iter() { query.push_str(element.0); query.push('='); if element.1 == "true" { query.push('1'); } else if element.1 == "false" { query.push('0'); } else { query.push('\"'); query.push_str(element.1); query.push('\"'); } query.push_str(","); } query.pop(); query.push_str(" WHERE "); for element in condition { query.push_str(element.0); query.push_str("=\""); query.push_str(element.1); query.push_str("\" AND "); } query.pop(); query.pop(); query.pop(); query.pop(); query.push(';'); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let query_result = sqlx::query(&query).execute(&mut conn).await; conn.close().await?; query_result } // update a record in table // record: [column name, value], condition: (column name, value) pub async fn update_record2( table_name: &String, record: &Vec<(String, String)>, condition: &Vec<(String, String)>, ) -> Result { // query building. let mut query = String::from("UPDATE "); query.push_str(table_name); query.push_str(" SET "); for element in record.iter() { query.push_str(element.0.as_str()); query.push('='); if element.1.as_str() == "true" { query.push('1'); } else if element.1.as_str() == "false" { query.push('0'); } else { query.push('\"'); query.push_str(element.1.as_str()); query.push('\"'); } query.push_str(","); } query.pop(); query.push_str(" WHERE "); for element in condition { query.push_str(element.0.as_str()); query.push_str("=\""); query.push_str(element.1.as_str()); query.push_str("\" AND "); } query.pop(); query.pop(); query.pop(); query.pop(); query.push(';'); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let query_result = sqlx::query(&query).execute(&mut conn).await; conn.close().await?; query_result } // update a record in table // record: (column name, value), condition: (column name, value) pub async fn update_record3( table_name: &String, record: &Vec<(String, String)>, condition: &Vec<(String, String)>, ) -> Result { // query building. let mut query = String::from("UPDATE "); query.push_str(table_name); query.push_str(" SET "); for element in record.iter() { query.push_str(element.0.as_str()); query.push('='); if element.1.as_str() == "true" { query.push('1'); } else if element.1.as_str() == "false" { query.push('0'); } else { query.push_str(element.1.as_str()); } query.push_str(","); } query.pop(); query.push_str(" WHERE "); for element in condition { query.push_str(element.0.as_str()); query.push_str("=\""); query.push_str(element.1.as_str()); query.push_str("\" AND "); } query.pop(); query.pop(); query.pop(); query.pop(); query.push(';'); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let query_result = sqlx::query(&query).execute(&mut conn).await; conn.close().await?; query_result } // update many records in a row // record: [[id1, val1_1, val2_1], [id2, val1_2, val2_1], ...] (the first element in each record must be id) // columns: ["col_name1", "col_name2"] (columns except id) pub async fn update_records( table_name: &String, records: &Vec>, columns: &Vec<&str>, ) -> Result { // query building. let mut query = String::from("UPDATE "); query.push_str(table_name); query.push_str(" s JOIN("); let mut first_flag: bool = true; let col_len = columns.len(); let mut record_count: usize = 0; let mut col_count: usize = 0; let mut new_scores_vec: Vec = Vec::new(); let mut new_score_name = String::from("new_score"); for _ in 0..col_len { new_scores_vec.push(new_score_name.clone()); new_scores_vec[record_count].push_str(record_count.to_string().as_str()); record_count += 1; } record_count = 0; for record in records { query.push_str("SELECT "); if first_flag == true { for element in record { if record_count == 0 { query.push_str(&element); query.push_str(" as id, "); record_count += 1; } else { query.push_str(&element); query.push_str(" as "); query.push_str(new_scores_vec[col_count].clone().as_str()); query.push_str(", "); record_count += 1; col_count += 1; } } query.pop(); query.pop(); query.push(' '); first_flag = false; } else { for _ in 0..7 { query.pop(); } query.push_str("UNION ALL SELECT "); for element in record { if element.as_str() == "true" { query.push('1'); } else if element.as_str() == "false" { query.push('0'); } else { query.push_str(element.as_str()); } query.push_str(","); } query.pop(); query.push(' '); } } query.push_str(") vals ON s.id = vals.id SET "); record_count = 0; for element in new_scores_vec { query.push_str(columns[record_count]); query.push_str(" = "); query.push_str(&element); query.push_str(", "); record_count += 1; } query.pop(); query.pop(); query.push(';'); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let query_result = sqlx::query(&query).execute(&mut conn).await; conn.close().await?; query_result } // delete a record in table // condition: (column name, value) pub async fn delete_record( table_name: &String, condition: &String, ) -> Result { // query building. let mut query = String::from("DELETE FROM "); query.push_str(table_name); query.push(' '); query.push_str(condition.as_str()); query.push(';'); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let query_result = sqlx::query(&query).execute(&mut conn).await; conn.close().await?; query_result } // count total row in table pub async fn count_rows(table_name: &String) -> Result { #[derive(FromRow)] struct Count { cnt: i32, } // query building. let mut query = String::from("SELECT COUNT(*) as cnt FROM "); query.push_str(table_name.as_str()); query.push(';'); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let query_result = sqlx::query_as::<_, Count>(&query) .fetch_one(&mut conn) .await; let result = match query_result { Ok(T) => Ok(T.cnt), Err(E) => return Err(E), }; conn.close().await?; result } // delete all rows in table pub async fn delete_all_rows( table_name: &String, ) -> Result<(), Box> { let mut query = String::from("TRUNCATE TABLE "); query.push_str(table_name); query.push_str(";"); let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let mut query_result = sqlx::query(&query).execute(&mut conn).await; while let Err(e) = query_result { query_result = sqlx::query(&query).execute(&mut conn).await; sleep(Duration::from_millis(200)).await; } conn.close().await?; Ok(()) } // select record from table pub async fn select_record( table_name: &String, column: &String, condition: &Option, data_struct: &T, ) -> Result, Box> where T: for<'r> FromRow<'r, MySqlRow> + Send + Unpin, { let mut query = String::from("SELECT "); query.push_str(column.to_lowercase().as_str()); query.push_str(" FROM "); query.push_str(table_name.to_lowercase().as_str()); match condition { None => {} Some(condition) => { query.push(' '); query.push_str(condition.as_str()); query.push(';'); } } let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); // let mut query_result: Vec = sqlx::query_as::<_, T>(&query).fetch_all(&mut conn).await?; let mut query_result = sqlx::query_as::<_, T>(&query).fetch_all(&mut conn).await; let mut query_result_vec: Vec = Vec::new(); loop { match query_result { Ok(T) => { if !T.is_empty() { query_result_vec = T; break; } else { sleep(Duration::from_millis(200)).await; query_result = sqlx::query_as::<_, T>(&query).fetch_all(&mut conn).await; } } Err(e) => { sleep(Duration::from_millis(200)).await; query_result = sqlx::query_as::<_, T>(&query).fetch_all(&mut conn).await; } } } conn.close().await?; Ok(query_result_vec) } // select record from table. No loop pub async fn try_select_record( table_name: &String, column: &String, condition: &Option, data_struct: &T, ) -> Result, Box> where T: for<'r> FromRow<'r, MySqlRow> + Send + Unpin, { let mut query = String::from("SELECT "); query.push_str(column.to_lowercase().as_str()); query.push_str(" FROM "); query.push_str(table_name.to_lowercase().as_str()); match condition { None => {} Some(condition) => { query.push(' '); query.push_str(condition.as_str()); query.push(';'); } } let mut conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; //retry connection until it will be done. while conn_result.is_err() { sleep(Duration::from_millis(200)).await; conn_result = sqlx::mysql::MySqlConnection::connect(DB_URL).await; } let mut conn = conn_result.unwrap(); let mut query_result: Vec = sqlx::query_as::<_, T>(&query).fetch_all(&mut conn).await?; conn.close().await?; Ok(query_result) }