77 lines
2.6 KiB
Rust
77 lines
2.6 KiB
Rust
use std::fs::File;
|
|
use std::io::{BufReader, BufRead};
|
|
|
|
use rusqlite::{Connection, Result, Statement, params};
|
|
|
|
/// Create a new SQLite DB and sets the appropriate pragmas.
|
|
///
|
|
/// This is a one time batch import. We don't care about atomicity
|
|
/// here. If the batch fails, then we'll start it over from scratch.
|
|
/// Disabling the rollback journal speeds up quite a lot the inserts.
|
|
///
|
|
///
|
|
fn conn_db (path: &str) -> Result<Connection> {
|
|
let db = Connection::open(path)?;
|
|
db.pragma_update(None,"journal_mode","OFF")?;
|
|
db.pragma_update(None,"synchronous","OFF")?;
|
|
db.execute(
|
|
"CREATE TABLE fantoir (
|
|
id INTEGER PRIMARY KEY,
|
|
rivoli TEXT NOT NULL,
|
|
insee TEXT NOT NULL,
|
|
libelle TEXT NOT NULL
|
|
)", []
|
|
)?;
|
|
Ok(db)
|
|
}
|
|
|
|
/// Parsing a FANTOIR file. This is where all the business logic lives.
|
|
///
|
|
/// # Parsing logic
|
|
///
|
|
/// For each line, we try to figure out what kind of record type we're
|
|
/// looking at. We're using some of the FANTOIR specificities to do so.
|
|
///
|
|
/// 1. If the 3rd char is empty, we can assume it's a "Département"
|
|
/// record.
|
|
/// 2. If the 3rd & 6th char are empty, it's a "Commune".
|
|
/// 3. All the other record will be street records. In that case, we
|
|
/// can extract the insee code, the rivoli code (with the key) and
|
|
/// the street name (aka libelle).
|
|
#[inline]
|
|
fn parse_fantoir_lines(reader: BufReader<File>, mut stmt: Statement) -> () {
|
|
for line in reader.lines() {
|
|
let l = line.unwrap();
|
|
if l.chars().nth(3) == Some(' ') {
|
|
// Enregistrement Département
|
|
} else if l.chars().nth(6) == Some(' ') {
|
|
// Enregistrement Commune
|
|
} else {
|
|
let mut full_insee = String::from(l.get(0..2).unwrap());
|
|
full_insee.push_str(l.get(3..6).unwrap());
|
|
let rivoli_with_key = l.get(6..11).unwrap();
|
|
let libelle = l.get(15..41).unwrap().trim();
|
|
stmt.execute(params! [rivoli_with_key, full_insee, libelle]).unwrap();
|
|
}
|
|
};
|
|
}
|
|
|
|
fn main() -> std::io::Result<()> {
|
|
let db = match conn_db("./fantoir.sqlite") {
|
|
Err(err) => panic!("Cannot close DB: {}", err),
|
|
Ok(conn) => conn
|
|
};
|
|
let stmt = db.prepare(
|
|
"INSERT INTO fantoir (rivoli, insee, libelle) VALUES (?1, ?2, ?3)"
|
|
).unwrap();
|
|
let fantoir_path = std::env::args().nth(1).unwrap();
|
|
let file = match File::open(&fantoir_path) {
|
|
Err(err) => panic!("Cannot read file {}: {}", fantoir_path, err),
|
|
Ok(file) => file,
|
|
};
|
|
let reader = BufReader::new(file);
|
|
parse_fantoir_lines(reader, stmt);
|
|
db.close();
|
|
Ok(())
|
|
}
|