|
| 1 | +use std::collections::HashMap; |
| 2 | +use tokio_postgres::{types::Type, Error, NoTls}; |
| 3 | + |
| 4 | +static MOST_RECOVERED: &str = r#"SELECT * FROM cases |
| 5 | +WHERE daily_recovered = (SELECT max(daily_recovered) FROM cases);"#; |
| 6 | +static GROUP_BY_MONTH: &str = " |
| 7 | +SELECT date_trunc('month', d)::date as month, |
| 8 | + sum(daily_confirmed) as new_cases, |
| 9 | + sum(daily_recovered) as recovered |
| 10 | +FROM cases |
| 11 | +GROUP BY month |
| 12 | +ORDER BY month"; |
| 13 | + |
| 14 | +/// silly way to convert row into Vec of Strings from postgres types |
| 15 | +/// see https://docs.rs/postgres/latest/postgres/types/trait.FromSql.html |
| 16 | +async fn row_to_str_vec(row: &tokio_postgres::Row) -> Vec<String> { |
| 17 | + (0..row.len()) |
| 18 | + .into_iter() |
| 19 | + .map(|ci| match *row.columns().get(ci).unwrap().type_() { |
| 20 | + Type::DATE => row.get::<usize, chrono::NaiveDate>(ci).to_string(), |
| 21 | + Type::INT4 => row.get::<usize, i32>(ci).to_string(), |
| 22 | + Type::INT8 => row.get::<usize, i64>(ci).to_string(), |
| 23 | + _ => "blah".to_string(), |
| 24 | + }) |
| 25 | + .collect() |
| 26 | +} |
| 27 | + |
| 28 | +async fn row_to_str_hashmap(row: &tokio_postgres::Row) -> HashMap<String, String> { |
| 29 | + let values = row_to_str_vec(row).await; |
| 30 | + values |
| 31 | + .into_iter() |
| 32 | + .zip(row.columns().iter()) |
| 33 | + .map(|(v, k)| (k.name().to_string(), v)) |
| 34 | + .collect() |
| 35 | +} |
| 36 | + |
| 37 | +#[tokio::main] |
| 38 | +async fn main() -> Result<(), Error> { |
| 39 | + let (mut client, connection) = |
| 40 | + tokio_postgres::connect("host=localhost user=htd", NoTls).await?; |
| 41 | + |
| 42 | + // connection object performs communication with DB, spawned to run on its own |
| 43 | + tokio::spawn(async move { |
| 44 | + if let Err(e) = connection.await { |
| 45 | + eprintln!("connection error: {}", e); |
| 46 | + } |
| 47 | + }); |
| 48 | + |
| 49 | + let rows = client.query(MOST_RECOVERED, &[]).await?; |
| 50 | + |
| 51 | + let value: chrono::NaiveDate = rows[0].get(0); |
| 52 | + println!("{:?}", value); |
| 53 | + println!("{:?}", row_to_str_vec(&rows[0]).await); |
| 54 | + println!("{:?}", row_to_str_hashmap(&rows[0]).await); |
| 55 | + |
| 56 | + let transaction = client.transaction().await?; |
| 57 | + transaction.query("DELETE FROM month_cases", &[]).await?; |
| 58 | + let ins_mv = transaction |
| 59 | + .prepare( |
| 60 | + "INSERT INTO month_cases |
| 61 | + (mon, new_cases, recovered) |
| 62 | + VALUES ($1, $2, $3)", |
| 63 | + ) |
| 64 | + .await?; |
| 65 | + |
| 66 | + for row in transaction.query(GROUP_BY_MONTH, &[]).await? { |
| 67 | + println!("{:?}", row_to_str_vec(&row).await); |
| 68 | + let date: chrono::NaiveDate = row.get(0); |
| 69 | + let new_cases: i64 = row.get(1); |
| 70 | + let recovered: i64 = row.get(2); |
| 71 | + transaction |
| 72 | + .execute( |
| 73 | + &ins_mv, |
| 74 | + &[&date.to_string(), &(new_cases as i32), &(recovered as i32)], |
| 75 | + ) |
| 76 | + .await?; |
| 77 | + } |
| 78 | + transaction.commit().await?; |
| 79 | + Ok(()) |
| 80 | +} |
0 commit comments