Skip to content

Commit 7d3cae0

Browse files
authored
feat: add -c option to pass the SQL query directly as an argument on datafusion-cli (#6765)
* feat: add `-c option` to pass the SQL query directly as an argument on datafusion-cli * feat: add integration tests of datafusion-cli * chore: exclude test data files of datafusion-cli from RAT check
1 parent f24a724 commit 7d3cae0

File tree

7 files changed

+254
-17
lines changed

7 files changed

+254
-17
lines changed

datafusion-cli/Cargo.lock

Lines changed: 152 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

datafusion-cli/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,9 @@ parking_lot = { version = "0.12" }
4343
rustyline = "11.0"
4444
tokio = { version = "1.24", features = ["macros", "rt", "rt-multi-thread", "sync", "parking_lot"] }
4545
url = "2.2"
46+
47+
[dev-dependencies]
48+
assert_cmd = "2.0"
49+
ctor = "0.2.0"
50+
predicates = "3.0"
51+
rstest = "0.17"

datafusion-cli/src/exec.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,20 @@ use std::time::Instant;
4141
use std::{fs::File, sync::Arc};
4242
use url::Url;
4343

44+
/// run and execute SQL statements and commands, against a context with the given print options
45+
pub async fn exec_from_commands(
46+
ctx: &mut SessionContext,
47+
print_options: &PrintOptions,
48+
commands: Vec<String>,
49+
) {
50+
for sql in commands {
51+
match exec_and_print(ctx, print_options, sql).await {
52+
Ok(_) => {}
53+
Err(err) => println!("{err}"),
54+
}
55+
}
56+
}
57+
4458
/// run and execute SQL statements and commands from a file, against a context with the given print options
4559
pub async fn exec_from_lines(
4660
ctx: &mut SessionContext,
@@ -58,11 +72,8 @@ pub async fn exec_from_lines(
5872
let line = line.trim_end();
5973
query.push_str(line);
6074
if line.ends_with(';') {
61-
match unescape_input(line) {
62-
Ok(sql) => match exec_and_print(ctx, print_options, sql).await {
63-
Ok(_) => {}
64-
Err(err) => eprintln!("{err}"),
65-
},
75+
match exec_and_print(ctx, print_options, query).await {
76+
Ok(_) => {}
6677
Err(err) => eprintln!("{err}"),
6778
}
6879
query = "".to_owned();
@@ -149,11 +160,8 @@ pub async fn exec_from_repl(
149160
}
150161
Ok(line) => {
151162
rl.add_history_entry(line.trim_end())?;
152-
match unescape_input(&line) {
153-
Ok(sql) => match exec_and_print(ctx, &print_options, sql).await {
154-
Ok(_) => {}
155-
Err(err) => eprintln!("{err}"),
156-
},
163+
match exec_and_print(ctx, &print_options, line).await {
164+
Ok(_) => {}
157165
Err(err) => eprintln!("{err}"),
158166
}
159167
}
@@ -182,6 +190,7 @@ async fn exec_and_print(
182190
) -> Result<()> {
183191
let now = Instant::now();
184192

193+
let sql = unescape_input(&sql)?;
185194
let plan = ctx.state().create_logical_plan(&sql).await?;
186195
let df = match &plan {
187196
LogicalPlan::Ddl(DdlStatement::CreateExternalTable(cmd)) => {

datafusion-cli/src/main.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,21 @@ struct Args {
4444
data_path: Option<String>,
4545

4646
#[clap(
47-
short = 'c',
47+
short = 'b',
4848
long,
4949
help = "The batch size of each query, or use DataFusion default",
5050
validator(is_valid_batch_size)
5151
)]
5252
batch_size: Option<usize>,
5353

54+
#[clap(
55+
short = 'c',
56+
long,
57+
multiple_values = true,
58+
help = "Execute the given command string(s), then exit"
59+
)]
60+
command: Vec<String>,
61+
5462
#[clap(
5563
short,
5664
long,
@@ -116,6 +124,7 @@ pub async fn main() -> Result<()> {
116124
quiet: args.quiet,
117125
};
118126

127+
let commands = args.command;
119128
let files = args.file;
120129
let rc = match args.rc {
121130
Some(file) => file,
@@ -132,18 +141,25 @@ pub async fn main() -> Result<()> {
132141
}
133142
};
134143

135-
if !files.is_empty() {
136-
exec::exec_from_files(files, &mut ctx, &print_options).await;
137-
Ok(())
138-
} else {
144+
if commands.is_empty() && files.is_empty() {
139145
if !rc.is_empty() {
140146
exec::exec_from_files(rc, &mut ctx, &print_options).await
141147
}
142148
// TODO maybe we can have thiserror for cli but for now let's keep it simple
143-
exec::exec_from_repl(&mut ctx, &mut print_options)
149+
return exec::exec_from_repl(&mut ctx, &mut print_options)
144150
.await
145-
.map_err(|e| DataFusionError::External(Box::new(e)))
151+
.map_err(|e| DataFusionError::External(Box::new(e)));
146152
}
153+
154+
if !files.is_empty() {
155+
exec::exec_from_files(files, &mut ctx, &print_options).await;
156+
}
157+
158+
if !commands.is_empty() {
159+
exec::exec_from_commands(&mut ctx, &print_options, commands).await;
160+
}
161+
162+
Ok(())
147163
}
148164

149165
fn create_runtime_env() -> Result<RuntimeEnv> {

0 commit comments

Comments
 (0)