Page MenuHomeDevCentral

D2734.id6936.diff
No OneTemporary

D2734.id6936.diff

diff --git a/src/commands/mod.rs b/src/commands/mod.rs
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -2,3 +2,4 @@
pub(crate) mod import;
pub(crate) mod promote;
+pub(crate) mod query;
diff --git a/src/commands/query.rs b/src/commands/query.rs
new file mode 100644
--- /dev/null
+++ b/src/commands/query.rs
@@ -0,0 +1,68 @@
+use std::process::exit;
+
+use sqlx::PgPool;
+
+use crate::db::connect_to_db;
+use crate::QueryArgs;
+use crate::services::query::*;
+
+static EXIT_CODE_NO_RESULT_FOUND: i32 = 4;
+
+pub async fn search(args: QueryArgs, database_url: &str) {
+ let pool = connect_to_db(database_url).await;
+
+ if args.code_insee.is_some() && args.code_voie.is_some() {
+ let code_fantoir = search_fantoir_code(
+ &pool,
+ &args.code_insee.unwrap(),
+ &args.code_voie.unwrap(),
+ ).await;
+
+ if let Some(code) = code_fantoir {
+ search_one_row(&pool, &code).await;
+ return;
+ }
+
+ exit(EXIT_CODE_NO_RESULT_FOUND);
+ }
+
+ if args.libelle.len() > 0 {
+ search_libelle(&pool, args).await;
+ return;
+ }
+
+ unimplemented!()
+}
+
+async fn search_one_row(pool: &PgPool, code_fantoir: &str) {
+ match query_fantoir_code(pool, code_fantoir).await {
+ None => {
+ exit(EXIT_CODE_NO_RESULT_FOUND);
+ }
+ Some(result) => {
+ println!("{}", result);
+ }
+ }
+}
+
+async fn search_libelle(pool: &PgPool, args: QueryArgs) {
+ let expression = args.libelle.join(" ");
+
+ query_libelle(pool, &expression)
+ .await
+ .iter()
+ .filter(|&entry| entry_matches_conditions(entry, &args))
+ .for_each(|entry| {
+ println!("{}", entry);
+ });
+}
+
+fn entry_matches_conditions(entry: &FantoirVoieResult, conditions: &QueryArgs) -> bool {
+ if let Some(code_insee) = &conditions.code_insee {
+ if &entry.code_insee != code_insee {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/main.rs b/src/main.rs
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,12 +2,12 @@
use clap::{Args, Parser};
-use crate::commands::import::import;
use crate::commands::promote::promote;
mod commands;
mod db;
mod fantoir;
+mod services;
#[derive(Debug, Parser)]
#[command(name = "fantoir-datasource")]
@@ -20,6 +20,10 @@
/// Promote an imported FANTOIR table as the current FANTOIR table to use
#[command(arg_required_else_help = true)]
Promote(PromoteArgs),
+
+ /// Query the imported FANTOIR table
+ #[command(arg_required_else_help = true)]
+ Query(QueryArgs)
}
#[derive(Debug, Args)]
@@ -46,6 +50,21 @@
fantoir_table: String,
}
+#[derive(Debug, Args)]
+#[clap(trailing_var_arg=true)]
+pub struct QueryArgs {
+ /// INSEE code to identify a commune
+ #[arg(long)]
+ code_insee: Option<String>,
+
+ /// Identifier of the voie by the commune
+ #[arg(long)]
+ code_voie: Option<String>,
+
+ /// Expression to search
+ libelle: Vec<String>,
+}
+
#[tokio::main]
async fn main() {
let command = FantoirCommand::parse(); // Will exit if argument is missing or --help/--version provided.
@@ -55,10 +74,13 @@
match command {
FantoirCommand::Import(args) => {
- import(&args, &database_url).await;
+ commands::import::import(&args, &database_url).await;
},
FantoirCommand::Promote(args) => {
promote(&args.fantoir_table, &database_url).await;
},
+ FantoirCommand::Query(args) => {
+ commands::query::search(args, &database_url).await
+ },
};
}
diff --git a/src/services/mod.rs b/src/services/mod.rs
new file mode 100644
--- /dev/null
+++ b/src/services/mod.rs
@@ -0,0 +1 @@
+pub mod query;
diff --git a/src/services/query.rs b/src/services/query.rs
new file mode 100644
--- /dev/null
+++ b/src/services/query.rs
@@ -0,0 +1,112 @@
+//! Service to search imported FANTOIR table
+//! This is intended to be exposed to the tool, and used internally to fix FANTOIR codes.
+
+use std::fmt::{Display, Formatter};
+use sqlx::{Error, FromRow, PgPool};
+
+/* -------------------------------------------------------------
+ Search a fantoir code from INSEE code, identifiant communal.
+
+ Useful to fix fantoir code from other sources.
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+pub async fn search_fantoir_code(pool: &PgPool, code_insee: &str, identifiant_communal_voie: &str) -> Option<String> {
+ let result = sqlx::query!(r#"
+SELECT code_fantoir
+FROM fantoir
+WHERE code_insee = $1 AND identifiant_communal_voie = $2
+ "#, code_insee, identifiant_communal_voie)
+ .fetch_one(pool)
+ .await;
+
+ if let Err(Error::RowNotFound) = result {
+ return None;
+ }
+
+ result.unwrap().code_fantoir
+}
+
+/* -------------------------------------------------------------
+ Query short information about voies.
+
+ This tool is mainly intended as an import tool, but as we need
+ this query service to cross datasources, we can leverage this
+ to offer a small search facility.
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#[derive(Debug, Clone, sqlx::FromRow)]
+pub struct FantoirVoieResult {
+ pub code_fantoir: String,
+ pub code_insee: String,
+ pub identifiant_communal_voie: String,
+ pub code_nature_voie: Option<String>,
+ pub libelle_voie: String,
+}
+
+impl FantoirVoieResult {
+ fn get_name (&self) -> String {
+ match &self.code_nature_voie {
+ None => self.libelle_voie.to_string(),
+ Some(kind) => match kind.len() {
+ 0 => self.libelle_voie.to_string(),
+ _ => format!("{} {}", kind, self.libelle_voie)
+ }
+ }
+ }
+}
+
+impl Display for FantoirVoieResult {
+ fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
+ write!(
+ f, "{}\t{} {}\t{}",
+ self.code_fantoir, self.code_insee, self.identifiant_communal_voie, self.get_name()
+ )
+ }
+}
+
+pub async fn query_fantoir_code(pool: &PgPool, code_fantoir: &str) -> Option<FantoirVoieResult> {
+ let result = sqlx::query!(r#"
+SELECT code_insee, identifiant_communal_voie, code_nature_voie, libelle_voie
+FROM fantoir
+WHERE code_fantoir = $1;
+ "#, code_fantoir)
+ .fetch_one(pool)
+ .await;
+
+ if let Err(Error::RowNotFound) = result {
+ return None;
+ }
+
+ let result = result.unwrap();
+
+ Some(
+ FantoirVoieResult {
+ code_fantoir: code_fantoir.to_string(),
+ code_insee: result.code_insee.unwrap(),
+ identifiant_communal_voie: result.identifiant_communal_voie.unwrap(),
+ code_nature_voie: result.code_nature_voie,
+ libelle_voie: result.libelle_voie.unwrap(),
+ }
+ )
+}
+
+pub async fn query_libelle (pool: &PgPool, libelle: &str) -> Vec<FantoirVoieResult> {
+ let result = sqlx::query(r#"
+SELECT code_fantoir, code_insee, identifiant_communal_voie, code_nature_voie, libelle_voie
+FROM fantoir
+WHERE libelle_voie ILIKE CONCAT('%', $1, '%');
+ "#)
+ .bind(libelle)
+ .fetch_all(pool)
+ .await;
+
+ if let Err(Error::RowNotFound) = result {
+ return Vec::new();
+ }
+
+ result
+ .unwrap()
+ .iter()
+ .map(|row| FantoirVoieResult::from_row(row).unwrap())
+ .collect()
+}

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 18, 23:55 (13 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2248404
Default Alt Text
D2734.id6936.diff (7 KB)

Event Timeline