pub use crate::loader::parseutil::*;
use csv;
use serde::Deserialize;
use sqlx::Transaction;
use std::collections::HashMap;
use std::convert::TryFrom;
#[derive(Debug, Deserialize, PartialEq, Clone)]
pub struct LocRecord {
pub uid: u32,
pub iso2: String,
pub iso3: String,
pub code3: Option<u32>,
pub fips: Option<u32>,
pub admin2: String,
pub province_state: String,
pub country_region: String,
pub lat: Option<f64>,
pub lon: Option<f64>,
pub combined_key: String,
pub population: Option<u64>,
}
pub fn parse_to_final<A: Iterator<Item = csv::StringRecord>>(
striter: A,
) -> impl Iterator<Item = LocRecord> {
striter.filter_map(|x| rec_to_struct(&x).expect("rec_to_struct"))
}
pub async fn load<'a, A: std::io::Read>(
rdr: &'a mut csv::Reader<A>,
mut transaction: Transaction<sqlx::pool::PoolConnection<sqlx::SqliteConnection>>,
) -> HashMap<u32, u64> {
assert_eq!(
vec![
"UID",
"iso2",
"iso3",
"code3",
"FIPS",
"Admin2",
"Province_State",
"Country_Region",
"Lat",
"Long_",
"Combined_Key",
"Population"
],
rdr.headers().unwrap().iter().collect::<Vec<&str>>()
);
let recs = parse_records(rdr.byte_records());
let finaliter = parse_to_final(recs);
let mut hm = HashMap::new();
for rec in finaliter {
match (rec.fips, rec.population) {
(Some(fipsi), Some(popi)) => {
hm.insert(fipsi, popi);
}
_ => (),
}
let query =
sqlx::query("INSERT INTO loc_lookup VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
query
.bind(i64::from(rec.uid))
.bind(rec.iso2)
.bind(rec.iso3)
.bind(rec.code3.map(i64::from))
.bind(rec.fips.map(i64::from))
.bind(if rec.admin2.len() == 0 {
None
} else {
Some(rec.admin2)
})
.bind(if rec.province_state.len() == 0 {
None
} else {
Some(rec.province_state)
})
.bind(rec.country_region)
.bind(rec.lat)
.bind(rec.lon)
.bind(rec.combined_key)
.bind(
rec.population
.map(|x| i64::try_from(x).expect("population range")),
)
.execute(&mut transaction)
.await
.unwrap();
}
transaction.commit().await.unwrap();
hm
}