-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Optimizer should have option to skip failing rules #2909
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
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
3708996
Projection::new
andygrove 2246957
try_new and validation
andygrove 6720cd1
better variable name
andygrove e41ab4b
split into try_new and try_new_with_schema
andygrove 5e813b2
fmt
andygrove faa5aa8
skip optimizer rules that fail
andygrove 6500eac
unit tests
andygrove dc4b30b
upmerge
andygrove 8f0c3e4
fix merge conflict
andygrove 8f73f9d
Merge remote-tracking branch 'apache/master' into optimizer-error-han…
andygrove 2cb9101
user configurable
andygrove 4dd1111
Update datafusion/optimizer/src/optimizer.rs
andygrove 7fd096a
Update datafusion/optimizer/src/optimizer.rs
andygrove 1cc7739
Update datafusion/optimizer/src/optimizer.rs
andygrove 58b29e0
fix errors from applying suggestions
andygrove File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,7 +20,7 @@ | |
| use chrono::{DateTime, Utc}; | ||
| use datafusion_common::Result; | ||
| use datafusion_expr::logical_plan::LogicalPlan; | ||
| use log::{debug, trace}; | ||
| use log::{debug, trace, warn}; | ||
| use std::sync::Arc; | ||
|
|
||
| /// `OptimizerRule` transforms one ['LogicalPlan'] into another which | ||
|
|
@@ -45,6 +45,8 @@ pub struct OptimizerConfig { | |
| /// to use a literal value instead | ||
| pub query_execution_start_time: DateTime<Utc>, | ||
| next_id: usize, | ||
| /// Option to skip rules that produce errors | ||
| skip_failing_rules: bool, | ||
| } | ||
|
|
||
| impl OptimizerConfig { | ||
|
|
@@ -53,9 +55,16 @@ impl OptimizerConfig { | |
| Self { | ||
| query_execution_start_time: chrono::Utc::now(), | ||
| next_id: 0, // useful for generating things like unique subquery aliases | ||
| skip_failing_rules: true, | ||
| } | ||
| } | ||
|
|
||
| /// Specify whether the optimizer should skip rules that produce errors, or fail the query | ||
| pub fn with_skip_failing_rules(mut self, b: bool) -> Self { | ||
| self.skip_failing_rules = b; | ||
| self | ||
| } | ||
|
|
||
| pub fn next_id(&mut self) -> usize { | ||
| self.next_id += 1; | ||
| self.next_id | ||
|
|
@@ -97,13 +106,88 @@ impl Optimizer { | |
| debug!("Input logical plan:\n{}\n", plan.display_indent()); | ||
| trace!("Full input logical plan:\n{:?}", plan); | ||
| for rule in &self.rules { | ||
| new_plan = rule.optimize(&new_plan, optimizer_config)?; | ||
| observer(&new_plan, rule.as_ref()); | ||
| debug!("After apply {} rule:\n", rule.name()); | ||
| debug!("Optimized logical plan:\n{}\n", new_plan.display_indent()); | ||
| let result = rule.optimize(&new_plan, optimizer_config); | ||
| match result { | ||
| Ok(plan) => { | ||
| new_plan = plan; | ||
| observer(&new_plan, rule.as_ref()); | ||
| debug!("After apply {} rule:\n", rule.name()); | ||
| debug!("Optimized logical plan:\n{}\n", new_plan.display_indent()); | ||
| } | ||
| Err(ref e) => { | ||
| if optimizer_config.skip_failing_rules { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the main change here - we now have the option to ignore optimization rules that fail
andygrove marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Note to future readers: if you see this warning it signals a | ||
| // bug in the DataFusion optimizer. Please consider filing a ticket | ||
| // https://github.com/apache/arrow-datafusion | ||
| warn!( | ||
| "Skipping optimizer rule {} due to unexpected error: {}", | ||
| rule.name(), | ||
| e | ||
| ); | ||
| } else { | ||
| return result; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| debug!("Optimized logical plan:\n{}\n", new_plan.display_indent()); | ||
| trace!("Full Optimized logical plan:\n {:?}", new_plan); | ||
| Ok(new_plan) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use crate::optimizer::Optimizer; | ||
| use crate::{OptimizerConfig, OptimizerRule}; | ||
| use datafusion_common::{DFSchema, DataFusionError}; | ||
| use datafusion_expr::logical_plan::EmptyRelation; | ||
| use datafusion_expr::LogicalPlan; | ||
| use std::sync::Arc; | ||
|
|
||
| #[test] | ||
| fn skip_failing_rule() -> Result<(), DataFusionError> { | ||
| let opt = Optimizer::new(vec![Arc::new(BadRule {})]); | ||
| let mut config = OptimizerConfig::new().with_skip_failing_rules(true); | ||
| let plan = LogicalPlan::EmptyRelation(EmptyRelation { | ||
| produce_one_row: false, | ||
| schema: Arc::new(DFSchema::empty()), | ||
| }); | ||
| opt.optimize(&plan, &mut config, &observe)?; | ||
| Ok(()) | ||
| } | ||
|
|
||
| #[test] | ||
| fn no_skip_failing_rule() -> Result<(), DataFusionError> { | ||
| let opt = Optimizer::new(vec![Arc::new(BadRule {})]); | ||
| let mut config = OptimizerConfig::new().with_skip_failing_rules(false); | ||
| let plan = LogicalPlan::EmptyRelation(EmptyRelation { | ||
| produce_one_row: false, | ||
| schema: Arc::new(DFSchema::empty()), | ||
| }); | ||
| let result = opt.optimize(&plan, &mut config, &observe); | ||
| assert_eq!( | ||
| "Error during planning: rule failed", | ||
| format!("{}", result.err().unwrap()) | ||
| ); | ||
| Ok(()) | ||
| } | ||
|
|
||
| fn observe(_plan: &LogicalPlan, _rule: &dyn OptimizerRule) {} | ||
|
|
||
| struct BadRule {} | ||
|
|
||
| impl OptimizerRule for BadRule { | ||
| fn optimize( | ||
| &self, | ||
| _plan: &LogicalPlan, | ||
| _optimizer_config: &mut OptimizerConfig, | ||
| ) -> datafusion_common::Result<LogicalPlan> { | ||
| Err(DataFusionError::Plan("rule failed".to_string())) | ||
| } | ||
|
|
||
| fn name(&self) -> &str { | ||
| "bad rule" | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯 for it being a config setting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I love this too! There are a few places I would want our product to fail in case of an error here but others I would not. so the configuration is great