Page MenuHomeDevCentral

No OneTemporary

diff --git a/Cargo.toml b/Cargo.toml
index 08cee41..5ce074b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,23 +1,27 @@
[package]
name = "fantoir-datasource"
version = "0.1.0"
edition = "2021"
description = "Generates a Postgres table from FANTOIR raw file"
authors = [
"Sébastien Santoro <dereckson@espace-win.org>"
]
license = "BSD-2-Clause"
[dependencies]
+[dependencies.async-scoped]
+version = "~0.7.1"
+features = ["use-tokio"]
+
[dependencies.clap]
version = "~4.0.32"
features = ["derive"]
[dependencies.sqlx]
version = "~0.6.2"
features = ["runtime-tokio-native-tls", "postgres", "chrono"]
[dependencies.tokio]
version = "~1.23.0"
features = ["full"]
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
index d438718..dcfee45 100644
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -1,3 +1,4 @@
//! Commands for the fantoir-datasource tool.
pub(crate) mod import;
+pub(crate) mod promote;
diff --git a/src/commands/promote/mod.rs b/src/commands/promote/mod.rs
new file mode 100644
index 0000000..bbd1921
--- /dev/null
+++ b/src/commands/promote/mod.rs
@@ -0,0 +1,27 @@
+//! Command to promote a table as the one to use.
+
+use sqlx::PgPool;
+use crate::db::{connect_to_db, run_multiple_queries_groups};
+
+/// Promotes a FANTOIR table as the relevant version to use
+pub async fn promote (fantoir_table: &str, database_url: &str) {
+ let pool = connect_to_db(database_url).await;
+ let queries_groups = get_queries_groups(&pool, fantoir_table);
+
+ run_multiple_queries_groups(&pool, &queries_groups);
+}
+
+/// Determines the groups of queries needed for promotion
+fn get_queries_groups (pool: &PgPool, fantoir_table: &str) -> Vec<String> {
+ let mut queries_groups = vec![
+ include_str!("../../schema/promote/config.sql"),
+ include_str!("../../schema/promote/fantoir_view.sql"),
+ ];
+
+ queries_groups
+ .into_iter()
+ .map(|queries| queries
+ .replace("/*table*/fantoir", fantoir_table)
+ )
+ .collect()
+}
diff --git a/src/db.rs b/src/db.rs
index 617f4e1..efd87b6 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -1,71 +1,83 @@
//! # Utilities for database.
//!
//! This module provides helpers to interact with a PostgreSQL database.
//! Functions expect to work with an executor from sqlx crate.
+use async_scoped::TokioScope;
use sqlx::PgPool;
use sqlx::postgres::PgPoolOptions;
static QUERIES_SEPARATOR: &str = "\n\n\n";
pub async fn connect_to_db (database_url: &str) -> PgPool {
PgPoolOptions::new()
.max_connections(3)
.connect(database_url)
.await
.expect("Can't connect to database.")
}
pub async fn is_table_exists (pool: &PgPool, table: &str) -> bool {
let query = r#"
SELECT EXISTS (
SELECT FROM
pg_tables
WHERE
schemaname = 'public' AND
tablename = $1
);
"#;
let result: (bool,) = sqlx::query_as(query)
.bind(table)
.fetch_one(pool)
.await
.expect("Can't check if table exists.");
result.0
}
pub async fn is_table_empty (pool: &PgPool, table: &str) -> bool {
let query = r#"
SELECT EXISTS (
SELECT 1 FROM %%table%%
);
"#.replace("%%table%%", table);
let result: (bool,) = sqlx::query_as(&query)
.fetch_one(pool)
.await
.expect("Can't check if table is empty.");
!result.0
}
pub async fn truncate_table (pool: &PgPool, table: &str) {
let query = format!("TRUNCATE TABLE {} RESTART IDENTITY;", table);
sqlx::query(&query)
.bind(table)
.execute(pool)
.await
.expect("Can't truncate table.");
}
pub async fn run_multiple_queries(pool: &PgPool, queries: &str) {
for query in queries.split(QUERIES_SEPARATOR) {
sqlx::query(&query)
.execute(pool)
.await
.expect("Can't run SQL query.");
}
}
+
+pub fn run_multiple_queries_groups (pool: &PgPool, queries_groups: &Vec<String>) {
+ let n = queries_groups.len();
+ TokioScope::scope_and_block(|scope| {
+ for i in 0..n {
+ scope.spawn(
+ run_multiple_queries(pool, &queries_groups[i])
+ )
+ }
+ });
+}
diff --git a/src/main.rs b/src/main.rs
index ee15c08..71e2400 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,50 +1,64 @@
use std::env;
use clap::{Args, Parser};
use crate::commands::import::import;
+use crate::commands::promote::promote;
mod commands;
mod db;
mod fantoir;
#[derive(Debug, Parser)]
#[command(name = "fantoir-datasource")]
#[clap(author="Nasqueron project", version, about="Import FANTOIR database into PostgreSQL", long_about=None)]
enum FantoirCommand {
/// Import from FANTOIR file generated by the DGFIP
#[command(arg_required_else_help = true)]
Import(ImportArgs),
+
+ /// Promote an imported FANTOIR table as the current FANTOIR table to use
+ #[command(arg_required_else_help = true)]
+ Promote(PromoteArgs),
}
#[derive(Debug, Args)]
pub struct ImportArgs {
/// Create table if it doesn't exist
#[arg(short = 'c')]
create_table: bool,
/// Truncate table if it already exists, allowing the overwrite mode.
/// If not specified, the script will fail if table exists.
#[arg(short = 't')]
overwrite_table: bool,
/// The FANTOIR file to import
fantoir_file: String,
/// The name of the table to populate
fantoir_table: String,
}
+#[derive(Debug, Args)]
+pub struct PromoteArgs {
+ /// The name of the table to promote
+ fantoir_table: String,
+}
+
#[tokio::main]
async fn main() {
let command = FantoirCommand::parse(); // Will exit if argument is missing or --help/--version provided.
let database_url = env::var("DATABASE_URL")
.expect("The environment variable DATABASE_URL need to be set to your PostgreSQL database.");
match command {
FantoirCommand::Import(args) => {
import(&args, &database_url).await;
},
+ FantoirCommand::Promote(args) => {
+ promote(&args.fantoir_table, &database_url).await;
+ },
};
}
diff --git a/src/schema/promote/config.sql b/src/schema/promote/config.sql
new file mode 100644
index 0000000..1a11914
--- /dev/null
+++ b/src/schema/promote/config.sql
@@ -0,0 +1,22 @@
+-- If you provide several instructions, separate those with TWO blank lines.
+--
+-- This schema is compiled as part of the program, as such you need to rebuild
+-- (`cargo build`) the project after any schema modification.
+
+CREATE TABLE IF NOT EXISTS fantoir_config
+(
+ key VARCHAR(63) NOT NULL
+ CONSTRAINT fantoir_config_pk
+ PRIMARY KEY,
+ CONSTRAINT fantoir_config_key_format
+ CHECK ( key ~ '^[a-zA-Z][a-zA-Z0-9_]*$' ),
+ value VARCHAR(255)
+);
+
+
+INSERT INTO fantoir_config
+ (key, value)
+VALUES
+ ('fantoir_table', '/*table*/fantoir')
+ON CONFLICT (key) DO UPDATE
+ SET value = excluded.value;
diff --git a/src/schema/promote/fantoir_view.sql b/src/schema/promote/fantoir_view.sql
new file mode 100644
index 0000000..4e7db52
--- /dev/null
+++ b/src/schema/promote/fantoir_view.sql
@@ -0,0 +1,7 @@
+-- If you provide several instructions, separate those with TWO blank lines.
+--
+-- This schema is compiled as part of the program, as such you need to rebuild
+-- (`cargo build`) the project after any schema modification.
+
+CREATE OR REPLACE VIEW fantoir AS
+ SELECT * FROM /*table*/fantoir;

File Metadata

Mime Type
text/x-diff
Expires
Thu, Sep 18, 07:32 (15 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2990182
Default Alt Text
(7 KB)

Event Timeline