From c1957dfbf6a6a8759f87f958db0a3003e69e6b67 Mon Sep 17 00:00:00 2001 From: pavlospt Date: Fri, 15 Mar 2024 14:29:52 +0200 Subject: [PATCH 1/2] Introduce Inquire crate in rust-pgdatadiff-client --- rust-pgdatadiff-client/Cargo.toml | 1 + rust-pgdatadiff-client/src/main.rs | 125 +++++++++++++++++++++-------- 2 files changed, 92 insertions(+), 34 deletions(-) diff --git a/rust-pgdatadiff-client/Cargo.toml b/rust-pgdatadiff-client/Cargo.toml index 2a8658a..b182b6b 100644 --- a/rust-pgdatadiff-client/Cargo.toml +++ b/rust-pgdatadiff-client/Cargo.toml @@ -16,3 +16,4 @@ clap = { version = "4.5.2", features = ["derive"] } tokio = "1.36.0" env_logger = "0.11.3" rust-pgdatadiff = { version = "0.1.2", path = ".." } +inquire = "0.7.1" diff --git a/rust-pgdatadiff-client/src/main.rs b/rust-pgdatadiff-client/src/main.rs index fa90bad..3d120be 100644 --- a/rust-pgdatadiff-client/src/main.rs +++ b/rust-pgdatadiff-client/src/main.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::{Parser, Subcommand}; +use inquire::{Confirm, Text}; use rust_pgdatadiff::diff::diff_ops::Differ; use rust_pgdatadiff::diff::diff_payload::DiffPayload; @@ -51,38 +52,94 @@ enum Commands { async fn main() -> Result<()> { env_logger::init(); - let cli = Cli::parse(); - match &cli.command { - Commands::Version => { - println!("Version: {}", env!("CARGO_PKG_VERSION")); - Ok(()) - } - Commands::Diff { - first_db, - second_db, - only_tables, - only_sequences, - only_count, - chunk_size, - max_connections, - include_tables, - exclude_tables, - schema_name, - } => { - let payload = DiffPayload::new( - first_db.clone(), - second_db.clone(), - *only_tables, - *only_sequences, - *only_count, - *chunk_size, - *max_connections, - include_tables.to_vec(), - exclude_tables.to_vec(), - schema_name.clone(), - ); - let _ = Differ::diff_dbs(payload).await; - Ok(()) - } - } + // let cli = Cli::parse(); + // match &cli.command { + // Commands::Version => { + // println!("Version: {}", env!("CARGO_PKG_VERSION")); + // Ok(()) + // } + // Commands::Diff { + // first_db, + // second_db, + // only_tables, + // only_sequences, + // only_count, + // chunk_size, + // max_connections, + // include_tables, + // exclude_tables, + // schema_name, + // } => { + // let payload = DiffPayload::new( + // first_db.clone(), + // second_db.clone(), + // *only_tables, + // *only_sequences, + // *only_count, + // *chunk_size, + // *max_connections, + // include_tables.to_vec(), + // exclude_tables.to_vec(), + // schema_name.clone(), + // ); + // let _ = Differ::diff_dbs(payload).await; + // Ok(()) + // } + // } + + let first_db = Text::new("First DB") + .with_default("postgres://postgres:postgres@localhost:5438/example") + .with_help_message("Enter the first database connection string") + .prompt()?; + let second_db = Text::new("Second DB") + .with_default("postgres://postgres:postgres@localhost:5439/example") + .with_help_message("Enter the first database connection string") + .prompt()?; + let only_tables = Confirm::new("Do you want to only compare tables?") + .with_default(false) + .with_help_message("By confirming this option, you will only compare tables") + .prompt()?; + let only_sequences = Confirm::new("Do you want to only compare sequences?") + .with_default(false) + .with_help_message("By confirming this option, you will only compare sequences") + .prompt()?; + let only_count = Confirm::new("Do you want to only count rows of tables?") + .with_default(false) + .with_help_message("By confirming this option, you will only row counts of tables") + .prompt()?; + let chunk_size = Text::new("Number of rows to compare (in batch)") + .with_default("10000") + .with_help_message("Enter the chunk size when comparing data") + .prompt()?; + let max_connections = Text::new("Number of DB connections to utilize") + .with_default("100") + .with_help_message("Enter the max connections for Postgres pool") + .prompt()?; + let include_tables = Text::new("Tables to include in the comparison") + .with_default("") + .with_help_message("Enter the tables to include in the comparison (comma separated)") + .prompt()?; + let exclude_tables = Text::new("Tables to exclude from the comparison") + .with_default("") + .with_help_message("Enter the tables to exclude from the comparison (comma separated)") + .prompt()?; + let schema_name = Text::new("DB schema name to compare") + .with_default("public") + .with_help_message("Enter the DB schema name to perform the comparison on") + .prompt()?; + + let payload = DiffPayload::new( + first_db, + second_db, + only_tables, + only_sequences, + only_count, + chunk_size.parse::().unwrap(), + max_connections.parse::().unwrap(), + include_tables.trim().split_whitespace().into_iter().collect(), + exclude_tables.trim().split_whitespace().into_iter().collect(), + schema_name, + ); + let _ = Differ::diff_dbs(payload).await; + Ok(()) } From 80f8d62ed070d5f6968f049753679cbd97ad08b6 Mon Sep 17 00:00:00 2001 From: pavlospt Date: Fri, 15 Mar 2024 14:47:38 +0200 Subject: [PATCH 2/2] Introduce features in rust-pgdatadiff-client --- README.md | 24 ++++++- rust-pgdatadiff-client/Cargo.toml | 11 ++- rust-pgdatadiff-client/src/main.rs | 105 ++++++++++++++++++----------- 3 files changed, 93 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 1be8974..9279785 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,20 @@ _The benchmarks below are based on DBs with 5 tables and 1M rows each. The resul In case you want to use this as a client you can install it through `cargo`: +Client supports two features that allow you to choose between `Clap` or `Inquire` for running it. + +[![asciicast](https://asciinema.org/a/647065.svg)](https://asciinema.org/a/647065) + +## Clap + +```shell +cargo install rust-pgdatadiff-client --features with-clap +``` + +## Inquire + ```shell -cargo install rust-pgdatadiff-client +cargo install rust-pgdatadiff-client //or with `--features with-inquire` ``` # Installation (Library) @@ -43,12 +55,13 @@ or ```toml [dependencies] -rust-pgdatadiff = "0.1.0" +rust-pgdatadiff = "0.1" ``` # Usage (Client) -``` +## Clap +```shell Usage: rust-pgdatadiff-client diff [OPTIONS] Arguments: @@ -68,6 +81,11 @@ Options: -V, --version Print version ``` +## Inquire +```shell +rust-pgdatadiff-client +``` + # Usage (Library) ```rust diff --git a/rust-pgdatadiff-client/Cargo.toml b/rust-pgdatadiff-client/Cargo.toml index b182b6b..dcc7873 100644 --- a/rust-pgdatadiff-client/Cargo.toml +++ b/rust-pgdatadiff-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rust-pgdatadiff-client" -version = "0.1.2" +version = "0.1.7" edition = "2021" license = "MIT" description = "Rust client for comparing two PostgreSQL databases" @@ -12,8 +12,13 @@ documentation = "https://docs.rs/rust-pgdatadiff-client" [dependencies] anyhow = "1.0.81" -clap = { version = "4.5.2", features = ["derive"] } +clap = { version = "4.5.2", features = ["derive"], optional = true } tokio = "1.36.0" env_logger = "0.11.3" rust-pgdatadiff = { version = "0.1.2", path = ".." } -inquire = "0.7.1" +inquire = { version = "0.7.1", optional = true } + +[features] +default = ["with-inquire"] +with-inquire = ["dep:inquire"] +with-clap = ["dep:clap"] diff --git a/rust-pgdatadiff-client/src/main.rs b/rust-pgdatadiff-client/src/main.rs index 3d120be..a1086b7 100644 --- a/rust-pgdatadiff-client/src/main.rs +++ b/rust-pgdatadiff-client/src/main.rs @@ -1,9 +1,14 @@ use anyhow::Result; -use clap::{Parser, Subcommand}; + +#[cfg(not(feature = "with-clap"))] use inquire::{Confirm, Text}; + +#[cfg(feature = "with-clap")] +use clap::{Parser, Subcommand}; use rust_pgdatadiff::diff::diff_ops::Differ; use rust_pgdatadiff::diff::diff_payload::DiffPayload; +#[cfg(feature = "with-clap")] #[derive(Parser)] #[command(author, version, about, long_about = None)] #[command(propagate_version = true)] @@ -12,6 +17,7 @@ struct Cli { command: Commands, } +#[cfg(feature = "with-clap")] #[derive(Subcommand)] enum Commands { #[command(about = "Print the version")] @@ -48,45 +54,46 @@ enum Commands { }, } -#[tokio::main] -async fn main() -> Result<()> { - env_logger::init(); - - // let cli = Cli::parse(); - // match &cli.command { - // Commands::Version => { - // println!("Version: {}", env!("CARGO_PKG_VERSION")); - // Ok(()) - // } - // Commands::Diff { - // first_db, - // second_db, - // only_tables, - // only_sequences, - // only_count, - // chunk_size, - // max_connections, - // include_tables, - // exclude_tables, - // schema_name, - // } => { - // let payload = DiffPayload::new( - // first_db.clone(), - // second_db.clone(), - // *only_tables, - // *only_sequences, - // *only_count, - // *chunk_size, - // *max_connections, - // include_tables.to_vec(), - // exclude_tables.to_vec(), - // schema_name.clone(), - // ); - // let _ = Differ::diff_dbs(payload).await; - // Ok(()) - // } - // } +#[cfg(feature = "with-clap")] +async fn main_clap() -> Result<()> { + let cli = Cli::parse(); + match &cli.command { + Commands::Version => { + println!("Version: {}", env!("CARGO_PKG_VERSION")); + Ok(()) + } + Commands::Diff { + first_db, + second_db, + only_tables, + only_sequences, + only_count, + chunk_size, + max_connections, + include_tables, + exclude_tables, + schema_name, + } => { + let payload = DiffPayload::new( + first_db.clone(), + second_db.clone(), + *only_tables, + *only_sequences, + *only_count, + *chunk_size, + *max_connections, + include_tables.to_vec(), + exclude_tables.to_vec(), + schema_name.clone(), + ); + let _ = Differ::diff_dbs(payload).await; + Ok(()) + } + } +} +#[cfg(not(feature = "with-clap"))] +async fn main_inquire() -> Result<()> { let first_db = Text::new("First DB") .with_default("postgres://postgres:postgres@localhost:5438/example") .with_help_message("Enter the first database connection string") @@ -136,10 +143,26 @@ async fn main() -> Result<()> { only_count, chunk_size.parse::().unwrap(), max_connections.parse::().unwrap(), - include_tables.trim().split_whitespace().into_iter().collect(), - exclude_tables.trim().split_whitespace().into_iter().collect(), + include_tables.split_whitespace().collect(), + exclude_tables.split_whitespace().collect(), schema_name, ); let _ = Differ::diff_dbs(payload).await; Ok(()) } + +#[tokio::main] +async fn main() -> Result<()> { + env_logger::init(); + + #[cfg(feature = "with-clap")] + { + _ = main_clap().await; + } + #[cfg(not(feature = "with-clap"))] + { + _ = main_inquire().await; + } + + Ok(()) +}