Skip to content

Change default EXPLAIN format in datafusion-cli to tree format #15427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 31, 2025
32 changes: 27 additions & 5 deletions datafusion-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ use datafusion_cli::{
};

use clap::Parser;
use datafusion::common::config_err;
use datafusion::config::ConfigOptions;
use mimalloc::MiMalloc;

#[global_allocator]
Expand Down Expand Up @@ -150,11 +152,7 @@ async fn main_inner() -> Result<()> {
env::set_current_dir(p).unwrap();
};

let mut session_config = SessionConfig::from_env()?.with_information_schema(true);

if let Some(batch_size) = args.batch_size {
session_config = session_config.with_batch_size(batch_size);
};
let session_config = get_session_config(&args)?;

let mut rt_builder = RuntimeEnvBuilder::new();
// set memory pool size
Expand Down Expand Up @@ -226,6 +224,30 @@ async fn main_inner() -> Result<()> {
Ok(())
}

/// Get the session configuration based on the provided arguments
/// and environment settings.
fn get_session_config(args: &Args) -> Result<SessionConfig> {
// Read options from environment variables and merge with command line options
let mut config_options = ConfigOptions::from_env()?;

if let Some(batch_size) = args.batch_size {
if batch_size == 0 {
return config_err!("batch_size must be greater than 0");
}
config_options.execution.batch_size = batch_size;
};

// use easier to understand "tree" mode by default
// if the user hasn't specified an explain format in the environment
if env::var_os("DATAFUSION_EXPLAIN_FORMAT").is_none() {
config_options.explain.format = String::from("tree");
}

let session_config =
SessionConfig::from(config_options).with_information_schema(true);
Ok(session_config)
}

fn parse_valid_file(dir: &str) -> Result<String, String> {
if Path::new(dir).is_file() {
Ok(dir.to_string())
Expand Down
25 changes: 25 additions & 0 deletions datafusion-cli/tests/cli_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ fn init() {
"batch_size",
["--command", "show datafusion.execution.batch_size", "-q", "-b", "1"],
)]
#[case::default_explain_plan(
"default_explain_plan",
// default explain format should be tree
["--command", "EXPLAIN SELECT 123"],
)]
#[case::can_see_indent_format(
"can_see_indent_format",
// can choose the old explain format too
["--command", "EXPLAIN FORMAT indent SELECT 123"],
)]
#[test]
fn cli_quick_test<'a>(
#[case] snapshot_name: &'a str,
Expand All @@ -74,6 +84,21 @@ fn cli_quick_test<'a>(
assert_cmd_snapshot!(cmd);
}

#[test]
fn cli_explain_environment_overrides() {
let mut settings = make_settings();
settings.set_snapshot_suffix("explain_plan_environment_overrides");
let _bound = settings.bind_to_scope();

let mut cmd = cli();

// should use the environment variable to override the default explain plan
cmd.env("DATAFUSION_EXPLAIN_FORMAT", "pgjson")
.args(["--command", "EXPLAIN SELECT 123"]);

assert_cmd_snapshot!(cmd);
}

#[rstest]
#[case("csv")]
#[case("tsv")]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
source: datafusion-cli/tests/cli_integration.rs
info:
program: datafusion-cli
args:
- "--command"
- EXPLAIN SELECT 123
env:
DATAFUSION_EXPLAIN_FORMAT: pgjson
snapshot_kind: text
---
success: true
exit_code: 0
----- stdout -----
[CLI_VERSION]
+--------------+-----------------------------------------+
| plan_type | plan |
+--------------+-----------------------------------------+
| logical_plan | [ |
| | { |
| | "Plan": { |
| | "Expressions": [ |
| | "Int64(123)" |
| | ], |
| | "Node Type": "Projection", |
| | "Output": [ |
| | "Int64(123)" |
| | ], |
| | "Plans": [ |
| | { |
| | "Node Type": "EmptyRelation", |
| | "Output": [], |
| | "Plans": [] |
| | } |
| | ] |
| | } |
| | } |
| | ] |
+--------------+-----------------------------------------+
1 row(s) fetched.
[ELAPSED]


----- stderr -----
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
source: datafusion-cli/tests/cli_integration.rs
info:
program: datafusion-cli
args:
- "--command"
- EXPLAIN FORMAT indent SELECT 123
snapshot_kind: text
---
success: true
exit_code: 0
----- stdout -----
[CLI_VERSION]
+---------------+------------------------------------------+
| plan_type | plan |
+---------------+------------------------------------------+
| logical_plan | Projection: Int64(123) |
| | EmptyRelation |
| physical_plan | ProjectionExec: expr=[123 as Int64(123)] |
| | PlaceholderRowExec |
| | |
+---------------+------------------------------------------+
2 row(s) fetched.
[ELAPSED]


----- stderr -----
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
source: datafusion-cli/tests/cli_integration.rs
info:
program: datafusion-cli
args:
- "--command"
- EXPLAIN SELECT 123
snapshot_kind: text
---
success: true
exit_code: 0
----- stdout -----
[CLI_VERSION]
+---------------+-------------------------------+
| plan_type | plan |
+---------------+-------------------------------+
| physical_plan | ┌───────────────────────────┐ |
| | │ ProjectionExec │ |
| | │ -------------------- │ |
| | │ Int64(123): 123 │ |
| | └─────────────┬─────────────┘ |
| | ┌─────────────┴─────────────┐ |
| | │ PlaceholderRowExec │ |
| | └───────────────────────────┘ |
| | |
+---------------+-------------------------------+
1 row(s) fetched.
[ELAPSED]


----- stderr -----