diff --git a/CHANGELOG.md b/CHANGELOG.md index ba53656b8637..20983556fb87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -121,6 +121,9 @@ for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/ and a bound to `QueryableByName` with `FromSqlRow`. +* CLI flags of `only-tables` and `except-tables` are now interpreted as regular expressions. + Similary, `only_tabels` and `except_tables` in `diesel.toml` are treated as regular expressions. + ### Fixed * Many types were incorrectly considered non-aggregate when they should not diff --git a/diesel_cli/Cargo.toml b/diesel_cli/Cargo.toml index 34215990a8c7..bbcacafe6f39 100644 --- a/diesel_cli/Cargo.toml +++ b/diesel_cli/Cargo.toml @@ -29,6 +29,8 @@ url = { version = "2.1.0", optional = true } barrel = { version = ">= 0.5.0", optional = true, features = ["diesel"] } libsqlite3-sys = { version = ">=0.8.0, <0.21.0", optional = true, features = ["min_sqlite_version_3_7_16"] } diffy = "0.2.0" +regex = "1.0.6" +serde_regex = "0.3.1" [dependencies.diesel] version = "~2.0.0" diff --git a/diesel_cli/src/cli.rs b/diesel_cli/src/cli.rs index ea11e3826217..6743e54554f0 100644 --- a/diesel_cli/src/cli.rs +++ b/diesel_cli/src/cli.rs @@ -123,32 +123,14 @@ pub fn build_cli() -> App<'static, 'static> { Arg::with_name("only-tables") .short("o") .long("only-tables") - .help("Only include tables from table-name") - .conflicts_with("except-tables") - .conflicts_with("blacklist"), - ) - .arg( - Arg::with_name("whitelist") - .short("w") - .long("whitelist") - .hidden(true) - .conflicts_with("blacklist") + .help("Only include tables from table-name that matches regexp") .conflicts_with("except-tables"), ) .arg( Arg::with_name("except-tables") .short("e") .long("except-tables") - .help("Exclude tables from table-name") - .conflicts_with("only-tables") - .conflicts_with("whitelist"), - ) - .arg( - Arg::with_name("blacklist") - .short("b") - .long("blacklist") - .hidden(true) - .conflicts_with("whitelist") + .help("Exclude tables from table-name that matches regex") .conflicts_with("only-tables"), ) .arg( diff --git a/diesel_cli/src/main.rs b/diesel_cli/src/main.rs index 789244c25601..bffb93bd4e09 100644 --- a/diesel_cli/src/main.rs +++ b/diesel_cli/src/main.rs @@ -28,6 +28,7 @@ mod query_helper; use chrono::*; use clap::{ArgMatches, Shell}; use migrations_internals::{self as migrations, MigrationConnection}; +use regex::Regex; use std::any::Any; use std::error::Error; use std::fmt::Display; @@ -383,7 +384,6 @@ fn convert_absolute_path_to_relative(target_path: &Path, mut current_path: &Path } fn run_infer_schema(matches: &ArgMatches) -> Result<(), Box> { - use crate::infer_schema_internals::TableName; use crate::print_schema::*; let database_url = database::database_url(matches); @@ -396,27 +396,14 @@ fn run_infer_schema(matches: &ArgMatches) -> Result<(), Box> { let filter = matches .values_of("table-name") .unwrap_or_default() - .map(|table_name| { - if let Some(schema) = config.schema_name() { - TableName::new(table_name, schema) - } else { - table_name.parse().unwrap() - } - }) - .collect(); - - if matches.is_present("whitelist") { - eprintln!("The `whitelist` option has been deprecated and renamed to `only-tables`."); - } - - if matches.is_present("blacklist") { - eprintln!("The `blacklist` option has been deprecated and renamed to `except-tables`."); - } - - if matches.is_present("only-tables") || matches.is_present("whitelist") { - config.filter = Filtering::OnlyTables(filter) - } else if matches.is_present("except-tables") || matches.is_present("blacklist") { - config.filter = Filtering::ExceptTables(filter) + .map(|table_name_regex| Regex::new(table_name_regex).map(Into::into)) + .collect::>() + .map_err(|e| format!("invalid argument for table filtering regex: {}", e)); + + if matches.is_present("only-tables") { + config.filter = Filtering::OnlyTables(filter?) + } else if matches.is_present("except-tables") { + config.filter = Filtering::ExceptTables(filter?) } if matches.is_present("with-docs") { diff --git a/diesel_cli/src/print_schema.rs b/diesel_cli/src/print_schema.rs index b8cdf8c89035..1a9604df21f9 100644 --- a/diesel_cli/src/print_schema.rs +++ b/diesel_cli/src/print_schema.rs @@ -3,15 +3,18 @@ use crate::config; use crate::infer_schema_internals::*; use serde::de::{self, MapAccess, Visitor}; use serde::{Deserialize, Deserializer}; +use serde_regex::Serde as RegexWrapper; use std::error::Error; use std::fmt::{self, Display, Formatter, Write}; use std::io::Write as IoWrite; const SCHEMA_HEADER: &str = "// @generated automatically by Diesel CLI.\n"; +type Regex = RegexWrapper<::regex::Regex>; + pub enum Filtering { - OnlyTables(Vec), - ExceptTables(Vec), + OnlyTables(Vec), + ExceptTables(Vec), None, } @@ -26,8 +29,8 @@ impl Filtering { use self::Filtering::*; match *self { - OnlyTables(ref names) => !names.contains(name), - ExceptTables(ref names) => names.contains(name), + OnlyTables(ref regexes) => !regexes.iter().any(|regex| regex.is_match(&name.sql_name)), + ExceptTables(ref regexes) => regexes.iter().any(|regex| regex.is_match(&name.sql_name)), None => false, } } @@ -318,21 +321,21 @@ impl<'de> Deserialize<'de> for Filtering { where V: MapAccess<'de>, { - let mut only_tables = None; - let mut except_tables = None; - while let Some((key, value)) = map.next_entry()? { + let mut only_tables = None::>; + let mut except_tables = None::>; + while let Some(key) = map.next_key()? { match key { "only_tables" => { if only_tables.is_some() { return Err(de::Error::duplicate_field("only_tables")); } - only_tables = Some(value); + only_tables = Some(map.next_value()?); } "except_tables" => { if except_tables.is_some() { return Err(de::Error::duplicate_field("except_tables")); } - except_tables = Some(value); + except_tables = Some(map.next_value()?); } _ => { return Err(de::Error::unknown_field( @@ -343,10 +346,10 @@ impl<'de> Deserialize<'de> for Filtering { } } match (only_tables, except_tables) { - (Some(_), Some(_)) => Err(de::Error::duplicate_field("except_tables")), - (Some(w), None) => Ok(Filtering::OnlyTables(w)), - (None, Some(b)) => Ok(Filtering::ExceptTables(b)), + (Some(t), None) => Ok(Filtering::OnlyTables(t)), + (None, Some(t)) => Ok(Filtering::ExceptTables(t)), (None, None) => Ok(Filtering::None), + _ => Err(de::Error::duplicate_field("only_tables except_tables")), } } } diff --git a/diesel_cli/tests/print_schema.rs b/diesel_cli/tests/print_schema.rs index f2a28834bcf0..f4cd6d55f486 100644 --- a/diesel_cli/tests/print_schema.rs +++ b/diesel_cli/tests/print_schema.rs @@ -18,7 +18,15 @@ fn run_infer_schema() { fn run_infer_schema_include() { test_print_schema( "print_schema_only_tables", - vec!["--with-docs", "-w", "users1"], + vec!["--with-docs", "-o", "users1"], + ); +} + +#[test] +fn run_infer_schema_include_regex() { + test_print_schema( + "print_schema_only_table_regexes", + vec!["--with-docs", "-o", "users1"], ); } @@ -26,7 +34,15 @@ fn run_infer_schema_include() { fn run_infer_schema_exclude() { test_print_schema( "print_schema_except_tables", - vec!["--with-docs", "-b", "users1"], + vec!["--with-docs", "-e", "users1"], + ); +} + +#[test] +fn run_infer_schema_exclude_regex() { + test_print_schema( + "print_schema_except_table_regexes", + vec!["--with-docs", "-e", "users1"], ); } diff --git a/diesel_cli/tests/print_schema/print_schema_except_table_regexes/diesel.toml b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/diesel.toml new file mode 100644 index 000000000000..f1ac714489d2 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/diesel.toml @@ -0,0 +1,4 @@ +[print_schema] +file = "src/schema.rs" +with_docs = true +filter = { except_tables = [".*1"] } diff --git a/diesel_cli/tests/print_schema/print_schema_except_table_regexes/mysql/expected.rs b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/mysql/expected.rs new file mode 100644 index 000000000000..4b152b02fa4f --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/mysql/expected.rs @@ -0,0 +1,15 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + /// Representation of the `users2` table. + /// + /// (Automatically generated by Diesel.) + users2 (id) { + /// The `id` column of the `users2` table. + /// + /// Its SQL type is `Integer`. + /// + /// (Automatically generated by Diesel.) + id -> Integer, + } +} diff --git a/diesel_cli/tests/print_schema/print_schema_except_table_regexes/mysql/schema.sql b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/mysql/schema.sql new file mode 100644 index 000000000000..556e9f7b54e8 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/mysql/schema.sql @@ -0,0 +1,2 @@ +CREATE TABLE users1 (id INTEGER PRIMARY KEY); +CREATE TABLE users2 (id INTEGER PRIMARY KEY); diff --git a/diesel_cli/tests/print_schema/print_schema_except_table_regexes/postgres/expected.rs b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/postgres/expected.rs new file mode 100644 index 000000000000..1a6c144d9a53 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/postgres/expected.rs @@ -0,0 +1,15 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + /// Representation of the `users2` table. + /// + /// (Automatically generated by Diesel.) + users2 (id) { + /// The `id` column of the `users2` table. + /// + /// Its SQL type is `Int4`. + /// + /// (Automatically generated by Diesel.) + id -> Int4, + } +} diff --git a/diesel_cli/tests/print_schema/print_schema_except_table_regexes/postgres/schema.sql b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/postgres/schema.sql new file mode 100644 index 000000000000..37d66071ac40 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/postgres/schema.sql @@ -0,0 +1,2 @@ +CREATE TABLE users1 (id SERIAL PRIMARY KEY); +CREATE TABLE users2 (id SERIAL PRIMARY KEY); diff --git a/diesel_cli/tests/print_schema/print_schema_except_table_regexes/sqlite/expected.rs b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/sqlite/expected.rs new file mode 100644 index 000000000000..ddc6550c77a7 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/sqlite/expected.rs @@ -0,0 +1,15 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + /// Representation of the `users2` table. + /// + /// (Automatically generated by Diesel.) + users2 (id) { + /// The `id` column of the `users2` table. + /// + /// Its SQL type is `Nullable`. + /// + /// (Automatically generated by Diesel.) + id -> Nullable, + } +} diff --git a/diesel_cli/tests/print_schema/print_schema_except_table_regexes/sqlite/schema.sql b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/sqlite/schema.sql new file mode 100644 index 000000000000..556e9f7b54e8 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_except_table_regexes/sqlite/schema.sql @@ -0,0 +1,2 @@ +CREATE TABLE users1 (id INTEGER PRIMARY KEY); +CREATE TABLE users2 (id INTEGER PRIMARY KEY); diff --git a/diesel_cli/tests/print_schema/print_schema_only_table_regexes/diesel.toml b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/diesel.toml new file mode 100644 index 000000000000..5f058f8cd628 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/diesel.toml @@ -0,0 +1,4 @@ +[print_schema] +file = "src/schema.rs" +with_docs = true +filter = { only_tables = [".*1"] } diff --git a/diesel_cli/tests/print_schema/print_schema_only_table_regexes/mysql/expected.rs b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/mysql/expected.rs new file mode 100644 index 000000000000..6d2c006f9504 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/mysql/expected.rs @@ -0,0 +1,15 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + /// Representation of the `users1` table. + /// + /// (Automatically generated by Diesel.) + users1 (id) { + /// The `id` column of the `users1` table. + /// + /// Its SQL type is `Integer`. + /// + /// (Automatically generated by Diesel.) + id -> Integer, + } +} diff --git a/diesel_cli/tests/print_schema/print_schema_only_table_regexes/mysql/schema.sql b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/mysql/schema.sql new file mode 100644 index 000000000000..556e9f7b54e8 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/mysql/schema.sql @@ -0,0 +1,2 @@ +CREATE TABLE users1 (id INTEGER PRIMARY KEY); +CREATE TABLE users2 (id INTEGER PRIMARY KEY); diff --git a/diesel_cli/tests/print_schema/print_schema_only_table_regexes/postgres/expected.rs b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/postgres/expected.rs new file mode 100644 index 000000000000..802f38c7c4db --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/postgres/expected.rs @@ -0,0 +1,15 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + /// Representation of the `users1` table. + /// + /// (Automatically generated by Diesel.) + users1 (id) { + /// The `id` column of the `users1` table. + /// + /// Its SQL type is `Int4`. + /// + /// (Automatically generated by Diesel.) + id -> Int4, + } +} diff --git a/diesel_cli/tests/print_schema/print_schema_only_table_regexes/postgres/schema.sql b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/postgres/schema.sql new file mode 100644 index 000000000000..37d66071ac40 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/postgres/schema.sql @@ -0,0 +1,2 @@ +CREATE TABLE users1 (id SERIAL PRIMARY KEY); +CREATE TABLE users2 (id SERIAL PRIMARY KEY); diff --git a/diesel_cli/tests/print_schema/print_schema_only_table_regexes/sqlite/expected.rs b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/sqlite/expected.rs new file mode 100644 index 000000000000..27b9cb8818c4 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/sqlite/expected.rs @@ -0,0 +1,15 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + /// Representation of the `users1` table. + /// + /// (Automatically generated by Diesel.) + users1 (id) { + /// The `id` column of the `users1` table. + /// + /// Its SQL type is `Nullable`. + /// + /// (Automatically generated by Diesel.) + id -> Nullable, + } +} diff --git a/diesel_cli/tests/print_schema/print_schema_only_table_regexes/sqlite/schema.sql b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/sqlite/schema.sql new file mode 100644 index 000000000000..556e9f7b54e8 --- /dev/null +++ b/diesel_cli/tests/print_schema/print_schema_only_table_regexes/sqlite/schema.sql @@ -0,0 +1,2 @@ +CREATE TABLE users1 (id INTEGER PRIMARY KEY); +CREATE TABLE users2 (id INTEGER PRIMARY KEY);