Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F11723025
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
rDS Nasqueron Datasources
Attached
Detach File
Event Timeline
Log In to Comment