Skip to content

Commit 1901d6f

Browse files
authored
feat: allow datafusion-cli to accept multiple statements (#7138)
* feat: allow cli to accept multiple statements * add empty line between results * use current context dialect * move empty line to print_timing_info
1 parent c3dbe43 commit 1901d6f

File tree

4 files changed

+28
-15
lines changed

4 files changed

+28
-15
lines changed

datafusion-cli/src/exec.rs

+23-11
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::{
2626
},
2727
print_options::PrintOptions,
2828
};
29+
use datafusion::sql::{parser::DFParser, sqlparser::dialect::dialect_from_str};
2930
use datafusion::{
3031
datasource::listing::ListingTableUrl,
3132
error::{DataFusionError, Result},
@@ -192,18 +193,29 @@ async fn exec_and_print(
192193
let now = Instant::now();
193194

194195
let sql = unescape_input(&sql)?;
195-
let plan = ctx.state().create_logical_plan(&sql).await?;
196-
let df = match &plan {
197-
LogicalPlan::Ddl(DdlStatement::CreateExternalTable(cmd)) => {
198-
create_external_table(ctx, cmd).await?;
199-
ctx.execute_logical_plan(plan).await?
200-
}
201-
_ => ctx.execute_logical_plan(plan).await?,
202-
};
203-
204-
let results = df.collect().await?;
205-
print_options.print_batches(&results, now)?;
196+
let task_ctx = ctx.task_ctx();
197+
let dialect = &task_ctx.session_config().options().sql_parser.dialect;
198+
let dialect = dialect_from_str(dialect).ok_or_else(|| {
199+
DataFusionError::Plan(format!(
200+
"Unsupported SQL dialect: {dialect}. Available dialects: \
201+
Generic, MySQL, PostgreSQL, Hive, SQLite, Snowflake, Redshift, \
202+
MsSQL, ClickHouse, BigQuery, Ansi."
203+
))
204+
})?;
205+
let statements = DFParser::parse_sql_with_dialect(&sql, dialect.as_ref())?;
206+
for statement in statements {
207+
let plan = ctx.state().statement_to_plan(statement).await?;
208+
let df = match &plan {
209+
LogicalPlan::Ddl(DdlStatement::CreateExternalTable(cmd)) => {
210+
create_external_table(ctx, cmd).await?;
211+
ctx.execute_logical_plan(plan).await?
212+
}
213+
_ => ctx.execute_logical_plan(plan).await?,
214+
};
206215

216+
let results = df.collect().await?;
217+
print_options.print_batches(&results, now)?;
218+
}
207219
Ok(())
208220
}
209221

datafusion-cli/src/helper.rs

-3
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,6 @@ impl CliHelper {
5454
Ok(statements) if statements.is_empty() => Ok(ValidationResult::Invalid(
5555
Some(" 🤔 You entered an empty statement".to_string()),
5656
)),
57-
Ok(statements) if statements.len() > 1 => Ok(ValidationResult::Invalid(
58-
Some(" 🤔 You entered more than one statement".to_string()),
59-
)),
6057
Ok(_statements) => Ok(ValidationResult::Valid(None)),
6158
Err(err) => Ok(ValidationResult::Invalid(Some(format!(
6259
" 🤔 Invalid statement: {err}",

datafusion-cli/src/print_options.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub struct PrintOptions {
2828

2929
fn print_timing_info(row_count: usize, now: Instant) {
3030
println!(
31-
"{} {} in set. Query took {:.3} seconds.",
31+
"{} {} in set. Query took {:.3} seconds.\n",
3232
row_count,
3333
if row_count == 1 { "row" } else { "rows" },
3434
now.elapsed().as_secs_f64()

datafusion-cli/tests/cli_integration.rs

+4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ fn init() {
3333
["--command", "select 1", "--format", "json", "-q"],
3434
"[{\"Int64(1)\":1}]\n"
3535
)]
36+
#[case::exec_multiple_statements(
37+
["--command", "select 1; select 2;", "--format", "json", "-q"],
38+
"[{\"Int64(1)\":1}]\n[{\"Int64(2)\":2}]\n"
39+
)]
3640
#[case::exec_from_files(
3741
["--file", "tests/data/sql.txt", "--format", "json", "-q"],
3842
"[{\"Int64(1)\":1}]\n"

0 commit comments

Comments
 (0)