Skip to content

Commit

Permalink
refactor: move type_coercion to analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
jackwener committed Apr 5, 2023
1 parent e86c83e commit d04a2d5
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 136 deletions.
4 changes: 1 addition & 3 deletions datafusion/core/src/physical_plan/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2164,9 +2164,7 @@ mod tests {

assert_contains!(
&e,
r#"type_coercion
caused by
Internal error: Optimizer rule 'type_coercion' failed due to unexpected error: Error during planning: Can not find compatible types to compare Boolean with [Struct([Field { name: "foo", data_type: Boolean, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), Utf8]. This was likely caused by a bug in DataFusion's code and we would welcome that you file an bug report in our issue tracker"#
r#"Error during planning: Can not find compatible types to compare Boolean with [Struct([Field { name: "foo", data_type: Boolean, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), Utf8]"#
);

Ok(())
Expand Down
27 changes: 15 additions & 12 deletions datafusion/core/tests/sql/timestamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,14 +925,12 @@ async fn test_ts_dt_binary_ops() -> Result<()> {
let batch = &plan[0];
let mut res: Option<String> = None;
for row in 0..batch.num_rows() {
if &array_value_to_string(batch.column(0), row)?
== "logical_plan after type_coercion"
{
if &array_value_to_string(batch.column(0), row)? == "initial_logical_plan" {
res = Some(array_value_to_string(batch.column(1), row)?);
break;
}
}
assert_eq!(res, Some("Projection: CAST(Utf8(\"2000-01-01\") AS Timestamp(Nanosecond, None)) >= CAST(CAST(Utf8(\"2000-01-01\") AS Date32) AS Timestamp(Nanosecond, None))\n EmptyRelation".to_string()));
assert_eq!(res, Some("Projection: CAST(Utf8(\"2000-01-01\") AS Timestamp(Nanosecond, None)) >= CAST(Utf8(\"2000-01-01\") AS Date32)\n EmptyRelation".to_string()));

//test cast path timestamp date using function
let sql = "select now() >= '2000-01-01'::date";
Expand All @@ -942,14 +940,18 @@ async fn test_ts_dt_binary_ops() -> Result<()> {
let batch = &plan[0];
let mut res: Option<String> = None;
for row in 0..batch.num_rows() {
if &array_value_to_string(batch.column(0), row)?
== "logical_plan after type_coercion"
{
if &array_value_to_string(batch.column(0), row)? == "initial_logical_plan" {
res = Some(array_value_to_string(batch.column(1), row)?);
break;
}
}
assert_eq!(res, Some("Projection: CAST(now() AS Timestamp(Nanosecond, None)) >= CAST(CAST(Utf8(\"2000-01-01\") AS Date32) AS Timestamp(Nanosecond, None))\n EmptyRelation".to_string()));
assert_eq!(
res,
Some(
"Projection: now() >= CAST(Utf8(\"2000-01-01\") AS Date32)\n EmptyRelation"
.to_string()
)
);

let sql = "select now() = current_date()";
let df = ctx.sql(sql).await.unwrap();
Expand All @@ -958,14 +960,15 @@ async fn test_ts_dt_binary_ops() -> Result<()> {
let batch = &plan[0];
let mut res: Option<String> = None;
for row in 0..batch.num_rows() {
if &array_value_to_string(batch.column(0), row)?
== "logical_plan after type_coercion"
{
if &array_value_to_string(batch.column(0), row)? == "initial_logical_plan" {
res = Some(array_value_to_string(batch.column(1), row)?);
break;
}
}
assert_eq!(res, Some("Projection: CAST(now() AS Timestamp(Nanosecond, None)) = CAST(currentdate() AS Timestamp(Nanosecond, None))\n EmptyRelation".to_string()));
assert_eq!(
res,
Some("Projection: now() = currentdate()\n EmptyRelation".to_string())
);

Ok(())
}
Expand Down
10 changes: 6 additions & 4 deletions datafusion/core/tests/sql/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,16 @@ async fn window_frame_creation_type_checking() -> Result<()> {
// Error is returned from the physical plan.
check_query(
true,
"Internal error: Operator - is not implemented for types UInt32(1) and Utf8(\"1 DAY\")."
).await?;
r#"Execution error: Cannot cast Utf8("1 DAY") to UInt32"#,
)
.await?;

// Error is returned from the logical plan.
check_query(
false,
"Internal error: Optimizer rule 'type_coercion' failed due to unexpected error: Execution error: Cannot cast Utf8(\"1 DAY\") to UInt32."
).await
r#"Execution error: Cannot cast Utf8("1 DAY") to UInt32"#,
)
.await
}

fn split_record_batch(batch: RecordBatch, n_split: usize) -> Vec<RecordBatch> {
Expand Down
5 changes: 4 additions & 1 deletion datafusion/optimizer/src/analyzer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

mod count_wildcard_rule;
mod inline_table_scan;
pub(crate) mod type_coercion;

use crate::analyzer::count_wildcard_rule::CountWildcardRule;
use crate::analyzer::inline_table_scan::InlineTableScan;

use crate::analyzer::type_coercion::TypeCoercion;
use datafusion_common::config::ConfigOptions;
use datafusion_common::tree_node::{TreeNode, VisitRecursion};
use datafusion_common::{DataFusionError, Result};
Expand Down Expand Up @@ -64,8 +66,9 @@ impl Analyzer {
/// Create a new analyzer using the recommended list of rules
pub fn new() -> Self {
let rules: Vec<Arc<dyn AnalyzerRule + Send + Sync>> = vec![
Arc::new(CountWildcardRule::new()),
Arc::new(InlineTableScan::new()),
Arc::new(TypeCoercion::new()),
Arc::new(CountWildcardRule::new()),
];
Self::with_rules(rules)
}
Expand Down
Loading

0 comments on commit d04a2d5

Please sign in to comment.