Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions datafusion/src/logical_plan/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1972,10 +1972,27 @@ fn create_name(e: &Expr, input_schema: &DFSchema) -> Result<String> {
Ok(format!("{} IN ({:?})", expr, list))
}
}
other => Err(DataFusionError::NotImplemented(format!(
"Create name does not support logical expression {:?}",
other
))),
Expr::Between {
expr,
negated,
low,
high,
} => {
let expr = create_name(expr, input_schema)?;
let low = create_name(low, input_schema)?;
let high = create_name(high, input_schema)?;
if *negated {
Ok(format!("{} NOT BETWEEN {} AND {}", expr, low, high))
} else {
Ok(format!("{} BETWEEN {} AND {}", expr, low, high))
}
}
Expr::Sort { .. } => Err(DataFusionError::Internal(
"Create name does not support sort expression".to_string(),
)),
Expr::Wildcard => Err(DataFusionError::Internal(
"Create name does not support wildcard".to_string(),
)),
}
}

Expand Down
25 changes: 21 additions & 4 deletions datafusion/src/physical_plan/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,27 @@ fn create_physical_name(e: &Expr, is_first_expr: bool) -> Result<String> {
Ok(format!("{} IN ({:?})", expr, list))
}
}
other => Err(DataFusionError::NotImplemented(format!(
"Cannot derive physical field name for logical expression {:?}",
other
))),
Expr::Between {
expr,
negated,
low,
high,
} => {
let expr = create_physical_name(expr, false)?;
let low = create_physical_name(low, false)?;
let high = create_physical_name(high, false)?;
if *negated {
Ok(format!("{} NOT BETWEEN {} AND {}", expr, low, high))
} else {
Ok(format!("{} BETWEEN {} AND {}", expr, low, high))
}
}
Expr::Sort { .. } => Err(DataFusionError::Internal(
"Create physical name does not support sort expression".to_string(),
)),
Expr::Wildcard => Err(DataFusionError::Internal(
"Create physical name does not support wildcard".to_string(),
)),
}
}

Expand Down
48 changes: 48 additions & 0 deletions datafusion/tests/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5397,6 +5397,54 @@ async fn case_with_bool_type_result() -> Result<()> {
Ok(())
}

#[tokio::test]
async fn use_between_expression_in_select_query() -> Result<()> {
let mut ctx = ExecutionContext::new();

let sql = "SELECT 1 NOT BETWEEN 3 AND 5";
let actual = execute_to_batches(&mut ctx, sql).await;
let expected = vec![
"+---------------+",
"| Boolean(true) |",
"+---------------+",
"| true |",
"+---------------+",
];
assert_batches_eq!(expected, &actual);

let input = Int64Array::from(vec![1, 2, 3, 4]);
let batch = RecordBatch::try_from_iter(vec![("c1", Arc::new(input) as _)]).unwrap();
let table = MemTable::try_new(batch.schema(), vec![vec![batch]])?;
ctx.register_table("test", Arc::new(table))?;

let sql = "SELECT abs(c1) BETWEEN 0 AND LoG(c1 * 100 ) FROM test";
let actual = execute_to_batches(&mut ctx, sql).await;
// Expect field name to be correctly converted for expr, low and high.
let expected = vec![
"+--------------------------------------------------------------------+",
"| abs(test.c1) BETWEEN Int64(0) AND log(test.c1 Multiply Int64(100)) |",
"+--------------------------------------------------------------------+",
"| true |",
"| true |",
"| false |",
"| false |",
"+--------------------------------------------------------------------+",
];
assert_batches_eq!(expected, &actual);

let sql = "EXPLAIN SELECT c1 BETWEEN 2 AND 3 FROM test";
let actual = execute_to_batches(&mut ctx, sql).await;
let formatted = arrow::util::pretty::pretty_format_batches(&actual).unwrap();

// Only test that the projection exprs arecorrect, rather than entire output
let needle = "ProjectionExec: expr=[c1@0 >= 2 AND c1@0 <= 3 as test.c1 BETWEEN Int64(2) AND Int64(3)]";
assert_contains!(&formatted, needle);
let needle = "Projection: #test.c1 BETWEEN Int64(2) AND Int64(3)";
assert_contains!(&formatted, needle);

Ok(())
}

#[tokio::test]
async fn query_get_indexed_field() -> Result<()> {
let mut ctx = ExecutionContext::new();
Expand Down