Skip to content

fix(cli): fail on formatting errors during text output#46

Open
wackywendell wants to merge 4 commits intomainfrom
wendell/cli-fail-on-failure
Open

fix(cli): fail on formatting errors during text output#46
wackywendell wants to merge 4 commits intomainfrom
wendell/cli-fail-on-failure

Conversation

@wackywendell
Copy link
Collaborator

@wackywendell wackywendell commented Jan 6, 2026

Return a terminal error when text formatting reports errors in convert/validate while keeping best-effort output.

Also a bit of code cleanup.

Before

❯ cargo run --features=cli convert -i ~/data/where-42.substrait.json -t text
   Compiling substrait-explain v0.2.0 (/Users/wendell.smith/go/src/github.com/DataDog/substrait-explain)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.56s
     Running `target/debug/substrait-explain convert -i /Users/wendell.smith/data/where-42.substrait.json -t text`
=== Plan
Root["?column?"]
  Project[42]
    Filter[!{RexType} => ]
      Read[!{ReadRel} => ]
[ Process Exit Code: 0 ]

Note that !{RexType} and !{ReadRel} are not recognized, but no warnings are printed; also exit code 0 is for 'success'.

After

❯ cargo run --features=cli convert -i ~/data/where-42.substrait.json -t text
   Compiling substrait-explain v0.2.0 (/Users/wendell.smith/go/src/github.com/DataDog/substrait-explain)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.97s
     Running `target/debug/substrait-explain convert -i /Users/wendell.smith/data/where-42.substrait.json -t text`
=== Plan
Root["?column?"]
  Project[42]
    Filter[!{RexType} => ]
      Read[!{ReadRel} => ]
Formatting issues:
  Error formatting output: Unimplemented Error writing RexType: Subquery textification not implemented
  Error formatting output: Unimplemented Error writing ReadRel: Unexpected read type Some(VirtualTable(VirtualTable { values: [], expressions: [Struct { fields: [Expression { rex_type: Some(Literal(Literal { nullable: false, type_variation_reference: 0, literal_type: Some(I32(0)) })) }] }] }))
[ Process Exit Code: 1 ]

Note the errors and the non-zero exit code.

@wackywendell wackywendell force-pushed the wendell/cli-fail-on-failure branch from b02b450 to 74698d6 Compare January 6, 2026 22:49
@wackywendell wackywendell force-pushed the wendell/cli-fail-on-failure branch 2 times, most recently from 2fae074 to c045ecf Compare January 23, 2026 23:42
@DataDog DataDog deleted a comment from chatgpt-codex-connector bot Jan 23, 2026
@wackywendell wackywendell marked this pull request as ready for review January 24, 2026 00:01
@wackywendell wackywendell requested a review from a team as a code owner January 24, 2026 00:01
use crate::parser::ExpressionParser;

fn parse_exact(rule: Rule, input: &str) -> pest::iterators::Pair<Rule> {
fn parse_exact(rule: Rule, input: &'_ str) -> pest::iterators::Pair<'_, Rule> {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed for newer Rust clippy version

),
}
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These have been disabled for a long time, no need to keep them

@wackywendell wackywendell force-pushed the wendell/cli-fail-on-failure branch from d19db33 to f2c18b5 Compare January 30, 2026 18:21
}
#[cfg(not(feature = "serde"))]
{
return Err("YAML support requires the 'serde' feature. Install with: cargo install substrait-explain --features cli,serde".into());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the return and ; creates an expression, but is anything done with this expression now? Is there still error propagation?

Copy link
Collaborator Author

@wackywendell wackywendell Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - an expression without a ; at the end of a function (or any {…} block) is the same as a return. This is considered more idiomatic in Rust; see this clippy lint.

Note also that this function returns a Result<…>; if you add a ; to this line without the Result, it would fail to compile because there would be nothing returned from this branch.

let RexType::ScalarFunction(func) = condition.rex_type.as_mut().unwrap() else {
panic!("Expected ScalarFunction");
};
func.function_reference = 999; // Invalid - doesn't exist in extensions
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a formatting issue or is this validation of the reference?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's both - it's invalid as a plan, therefore can't be formatted. At formatting time, we use the function reference to look up the function name in the extensions, and then print the function name in the expression; if the function reference is valid, then the function name can't be printed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments