diff --git a/Cargo.toml b/Cargo.toml index 8ea2678..4965fb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/sundy-li/arrow_cli" edition = "2024" license = "Apache-2.0" name = "arrow_cli" -version = "0.6.1" +version = "0.7.0" [dependencies] diff --git a/README.md b/README.md index 35dc76b..a0cd8d3 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Usage: arrow_cli [OPTIONS] Options: -u, --user User name [default: root] - -p, --password User password [default: ] + -p, --password User password [default: ""] --host Flight SQL Server host [default: 127.0.0.1] -P, --port Flight SQL Server port [default: 4100] --tls @@ -32,7 +32,9 @@ Options: --print-schema Print resultset schema --output Result output format [default: table] [possible values: table, json, csv, tsv, psv] -c, --command Execute SQL command and exit + -f, --file Execute SQL commands from a file and exit -h, --help Print help + -V, --version Print version ``` ## Examples @@ -58,6 +60,19 @@ Options: {"number":2} ``` +### Execute SQL from a file + +```bash +❯ arrow_cli -h arch -u sundy -p abc --port 8900 --output table --file query.sql ++-------------+ +| avg(number) | ++-------------+ +| 4.5 | ++-------------+ + +1 rows in set (tickets received in 0.036 sec, rows received in 0.036 sec) +``` + ### StdIn pipe with CSV output ```bash diff --git a/SKILL.md b/SKILL.md index c6853a7..0f7ec5f 100644 --- a/SKILL.md +++ b/SKILL.md @@ -39,6 +39,14 @@ Output: 1 rows in set (tickets received in 0.008 sec, rows received in 0.012 sec) ``` +### Execute SQL from a file and exit + +```bash +arrow_cli --host localhost --port 8900 --user admin --password abc --file query.sql +``` + +The file content is read as a single SQL statement and executed once, then the CLI exits. + ### Pipe SQL through standard input ```bash diff --git a/src/main.rs b/src/main.rs index 50bfa11..9d01092 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,8 +55,16 @@ struct Args { )] output: Output, - #[clap(short = 'c', long, help = "Execute SQL command and exit")] + #[clap( + short = 'c', + long, + help = "Execute SQL command and exit", + conflicts_with = "file" + )] command: Option, + + #[clap(short = 'f', long, help = "Execute SQL commands from a file and exit")] + file: Option, } #[tokio::main] @@ -67,7 +75,7 @@ pub async fn main() -> Result<(), FlightError> { // Authenticate let url = format!("{protocol}://{}:{}", args.host, args.port); let endpoint = endpoint(&args, url)?; - let is_repl = atty::is(Stream::Stdin) && args.command.is_none(); + let is_repl = atty::is(Stream::Stdin) && args.command.is_none() && args.file.is_none(); let mut session = session::Session::try_new(endpoint, is_repl, args).await?; session.handle().await; diff --git a/src/session.rs b/src/session.rs index e0e579e..c9d0a80 100644 --- a/src/session.rs +++ b/src/session.rs @@ -62,6 +62,9 @@ impl Session { } else if self.args.command.is_some() { let command = self.args.command.clone().unwrap(); self.handle_command(&command).await; + } else if self.args.file.is_some() { + let file = self.args.file.clone().unwrap(); + self.handle_file(&file).await; } else { self.handle_stdin().await; } @@ -144,6 +147,17 @@ impl Session { } } + pub async fn handle_file(&mut self, file: &str) { + match std::fs::read_to_string(file) { + Ok(query) => { + self.handle_command(query.trim_end()).await; + } + Err(e) => { + eprintln!("read file {file} err: {e}"); + } + } + } + pub async fn handle_stdin(&mut self) { let mut lines = std::io::stdin().lock().lines(); while let Some(Ok(line)) = lines.next() {