Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
---
name: Rust

on:
push:
branches: [ "main" ]
branches: [main]
pull_request:
branches: [ "main" ]
branches: [main]

env:
CARGO_TERM_COLOR: always
Expand Down
12 changes: 6 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ repos:
hooks:
- id: check-github-workflows
- id: check-renovate
- repo: https://github.com/backplane/pre-commit-rust-hooks
rev: v1.1.0
hooks:
- id: fmt
- id: check
- id: clippy
- repo: https://github.com/backplane/pre-commit-rust-hooks
rev: v1.1.0
hooks:
- id: fmt
- id: check
- id: clippy
24 changes: 17 additions & 7 deletions src/args.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
use clap::{ArgAction, Parser};
use indoc::indoc;

#[derive(clap::Parser, Debug)]
pub(crate) fn parse_args() -> Args {
Args::parse()
}

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub(crate) struct Args {
#[arg(help="Increase verbosity")]
#[arg(short='q', long="quiet")]
#[arg(action=clap::ArgAction::Count)]
#[arg(help = "Decrease verbosity")]
#[arg(short = 'q', long = "quiet")]
#[arg(action=ArgAction::Count)]
pub(crate) quiet: u8,

#[arg(help="Increase verbosity")]
#[arg(short='v', long="verbose")]
#[arg(action=clap::ArgAction::Count)]
#[arg(help = "Increase verbosity")]
#[arg(short = 'v', long = "verbose")]
#[arg(action=ArgAction::Count)]
pub(crate) verbose: u8,

#[arg(short = 't', long = "table")]
#[arg(help = "Table or views to query. Can be used multiple times.")]
#[arg(action=ArgAction::Set)]
pub(crate) table: Option<Vec<String>>,

#[arg(help = "Pattern to match every cell with")]
pub(crate) pattern: String,

Expand Down
6 changes: 4 additions & 2 deletions src/cell_to_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,14 @@ pub(crate) fn sqlite_cell_to_string(value_ref: SqliteValueRef) -> Result<Option<
}
// Date
if <chrono::NaiveDate as Type<Sqlite>>::compatible(&type_info) {
let value = <chrono::NaiveDate as Decode<Sqlite>>::decode(value_ref).map_err(errr_format)?;
let value =
<chrono::NaiveDate as Decode<Sqlite>>::decode(value_ref).map_err(errr_format)?;
return Ok(Some(value.format("%Y-%m-%d").to_string()));
}
// Time
if <chrono::NaiveTime as Type<Sqlite>>::compatible(&type_info) {
let value = <chrono::NaiveTime as Decode<Sqlite>>::decode(value_ref).map_err(errr_format)?;
let value =
<chrono::NaiveTime as Decode<Sqlite>>::decode(value_ref).map_err(errr_format)?;
return Ok(Some(value.format("%H:%M:%S").to_string()));
}

Expand Down
62 changes: 50 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ mod args;
mod cell_to_string;
mod select;

use clap::Parser as _;
use sqlparser::dialect::SQLiteDialect;

use sqlx::sqlite::SqliteConnectOptions;
Expand All @@ -11,7 +10,7 @@ use sqlx::{Column, Executor, Pool, Row, Sqlite, SqlitePool};

#[tokio::main()]
async fn main() {
let args = args::Args::parse();
let args = args::parse_args();
// Set default log level to 2.
let quiet_level: i16 = 2 + args.verbose as i16 - args.quiet as i16;

Expand All @@ -32,10 +31,25 @@ async fn main() {
}
};

process_sqlite_database(args.database_uri, &pattern).await;
let select_variant = match args.table {
None => SelectVariant::WholeDB,
Some(table_names) => SelectVariant::SpecificTables(table_names),
};

match process_sqlite_database(args.database_uri, &pattern, select_variant).await {
Ok(_) => {}
Err(err) => {
log::error!("Unable read tables from database: {}", err);
std::process::exit(74);
}
}
}

async fn process_sqlite_database(database_uri: String, pattern: &regex::Regex) {
async fn process_sqlite_database(
database_uri: String,
pattern: &regex::Regex,
select_variant: SelectVariant,
) -> Result<(), Error> {
let dialect = SQLiteDialect {};

let options: SqliteConnectOptions = match database_uri.parse::<SqliteConnectOptions>() {
Expand All @@ -54,18 +68,36 @@ async fn process_sqlite_database(database_uri: String, pattern: &regex::Regex) {
}
};

let table_names = match sqlite_select_tables(&db).await {
Ok(db) => db,
Err(err) => {
log::error!("Unable read tables from database: {}", err);
std::process::exit(74);
match select_variant {
SelectVariant::WholeDB => match sqlite_select_tables(&db).await {
Ok(table_names) => {
let mut table_names = table_names;
sqlite_select_from_tables(&db, &mut table_names, pattern, &dialect).await
}
Err(err) => Err(err),
},
SelectVariant::SpecificTables(table_names) => {
let mut table_names = table_names.into_iter();
sqlite_select_from_tables(&db, &mut table_names, pattern, &dialect).await
}
};
}
}

async fn sqlite_select_from_tables<Iter>(
db: &Pool<Sqlite>,
table_names: &mut Iter,
pattern: &regex::Regex,
dialect: &SQLiteDialect,
) -> Result<(), Error>
where
Iter: Iterator<Item = String>,
{
for table_name in table_names {
let select_query = select::generate_select(table_name.as_str(), &dialect);
sqlite_check_rows(&table_name, &db, select_query.as_str(), pattern).await;
let select_query = select::generate_select(table_name.as_str(), dialect);
sqlite_check_rows(&table_name, db, select_query.as_str(), pattern).await;
}

Ok(())
}

async fn sqlite_select_tables(db: &Pool<Sqlite>) -> Result<impl Iterator<Item = String>, Error> {
Expand Down Expand Up @@ -158,3 +190,9 @@ fn sqlite_process_row(
}
}
}

#[non_exhaustive]
enum SelectVariant {
WholeDB,
SpecificTables(Vec<String>),
}