Skip to content

Commit

Permalink
Merge pull request #2515 from TaKO8Ki/filter-regex
Browse files Browse the repository at this point in the history
Implement regex filtering
  • Loading branch information
weiznich committed Sep 29, 2020
2 parents 56232d9 + 6f3fe60 commit d7ce43d
Show file tree
Hide file tree
Showing 20 changed files with 159 additions and 56 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/
and a bound to `QueryableByName<DB>` with `FromSqlRow<Untyped, DB>`.


* 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
Expand Down
2 changes: 2 additions & 0 deletions diesel_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
22 changes: 2 additions & 20 deletions diesel_cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
31 changes: 9 additions & 22 deletions diesel_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<dyn Error>> {
use crate::infer_schema_internals::TableName;
use crate::print_schema::*;

let database_url = database::database_url(matches);
Expand All @@ -396,27 +396,14 @@ fn run_infer_schema(matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
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::<Result<_, _>>()
.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") {
Expand Down
27 changes: 15 additions & 12 deletions diesel_cli/src/print_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<TableName>),
ExceptTables(Vec<TableName>),
OnlyTables(Vec<Regex>),
ExceptTables(Vec<Regex>),
None,
}

Expand All @@ -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,
}
}
Expand Down Expand Up @@ -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::<Vec<Regex>>;
let mut except_tables = None::<Vec<Regex>>;
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(
Expand All @@ -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")),
}
}
}
Expand Down
20 changes: 18 additions & 2 deletions diesel_cli/tests/print_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,31 @@ 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"],
);
}

#[test]
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"],
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[print_schema]
file = "src/schema.rs"
with_docs = true
filter = { except_tables = [".*1"] }
Original file line number Diff line number Diff line change
@@ -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,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE TABLE users1 (id INTEGER PRIMARY KEY);
CREATE TABLE users2 (id INTEGER PRIMARY KEY);
Original file line number Diff line number Diff line change
@@ -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,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE TABLE users1 (id SERIAL PRIMARY KEY);
CREATE TABLE users2 (id SERIAL PRIMARY KEY);
Original file line number Diff line number Diff line change
@@ -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<Integer>`.
///
/// (Automatically generated by Diesel.)
id -> Nullable<Integer>,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE TABLE users1 (id INTEGER PRIMARY KEY);
CREATE TABLE users2 (id INTEGER PRIMARY KEY);
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[print_schema]
file = "src/schema.rs"
with_docs = true
filter = { only_tables = [".*1"] }
Original file line number Diff line number Diff line change
@@ -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,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE TABLE users1 (id INTEGER PRIMARY KEY);
CREATE TABLE users2 (id INTEGER PRIMARY KEY);
Original file line number Diff line number Diff line change
@@ -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,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE TABLE users1 (id SERIAL PRIMARY KEY);
CREATE TABLE users2 (id SERIAL PRIMARY KEY);
Original file line number Diff line number Diff line change
@@ -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<Integer>`.
///
/// (Automatically generated by Diesel.)
id -> Nullable<Integer>,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE TABLE users1 (id INTEGER PRIMARY KEY);
CREATE TABLE users2 (id INTEGER PRIMARY KEY);

0 comments on commit d7ce43d

Please sign in to comment.