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
17 changes: 10 additions & 7 deletions src/planner_v2/binder/expression/bind_cast_expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,22 @@ pub struct BoundCastExpression {
}

impl BoundCastExpression {
pub fn add_cast_to_type(
expr: BoundExpression,
/// If source_expr return_type is same type as target_type, return source_expr directly,
/// otherwise, add a cast expression to the source_expr.
pub fn try_add_cast_to_type(
source_expr: BoundExpression,
target_type: LogicalType,
alias: String,
try_cast: bool,
) -> Result<BoundExpression, BindError> {
// TODO: enhance alias to reduce outside alias assignment
let source_type = expr.return_type();
assert!(source_type != target_type);
let source_type = source_expr.return_type();
if source_type == target_type {
return Ok(source_expr);
}
let cast_function = DefaultCastFunctions::get_cast_function(&source_type, &target_type)?;
let alias = format!("cast({} as {}", source_expr.alias(), target_type);
let base = BoundExpressionBase::new(alias, target_type);
Ok(BoundExpression::BoundCastExpression(
BoundCastExpression::new(base, Box::new(expr), try_cast, cast_function),
BoundCastExpression::new(base, Box::new(source_expr), try_cast, cast_function),
))
}
}
40 changes: 13 additions & 27 deletions src/planner_v2/binder/expression/bind_comparison_expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,38 +23,24 @@ impl ExpressionBinder<'_> {
result_names: &mut Vec<String>,
result_types: &mut Vec<LogicalType>,
) -> Result<BoundExpression, BindError> {
let mut return_names = vec![];
let mut return_types = vec![];
let mut bound_left = self.bind_expression(left, &mut return_names, &mut return_types)?;
let mut bound_right = self.bind_expression(right, &mut return_names, &mut return_types)?;
let mut bound_left = self.bind_expression(left, &mut vec![], &mut vec![])?;
let mut bound_right = self.bind_expression(right, &mut vec![], &mut vec![])?;
let left_type = bound_left.return_type();
let right_type = bound_right.return_type();

// cast the input types to the same type, now obtain the result type of the input types
let input_type = LogicalType::max_logical_type(&left_type, &right_type)?;
if input_type != left_type {
let alias = format!("cast({} as {}", bound_left.alias(), input_type);
bound_left = BoundCastExpression::add_cast_to_type(
bound_left,
input_type.clone(),
alias.clone(),
true,
)?;
return_names[0] = alias;
return_types[0] = input_type.clone();
}
if input_type != right_type {
let alias = format!("cast({} as {}", bound_right.alias(), input_type);
bound_right = BoundCastExpression::add_cast_to_type(
bound_right,
input_type.clone(),
alias.clone(),
true,
)?;
return_names[1] = alias;
return_types[1] = input_type.clone();
}
bound_left =
BoundCastExpression::try_add_cast_to_type(bound_left, input_type.clone(), true)?;
bound_right =
BoundCastExpression::try_add_cast_to_type(bound_right, input_type.clone(), true)?;

result_names.push(format!("{}({},{})", op, return_names[0], return_names[1]));
result_names.push(format!(
"{}({},{})",
op,
bound_left.alias(),
bound_right.alias()
));
result_types.push(LogicalType::Boolean);
let function = DefaultComparisonFunctions::get_comparison_function(op, &input_type)?;
let base = BoundExpressionBase::new("".to_string(), LogicalType::Boolean);
Expand Down
26 changes: 6 additions & 20 deletions src/planner_v2/binder/expression/bind_conjunction_expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,15 @@ impl ExpressionBinder<'_> {
result_types: &mut Vec<LogicalType>,
) -> Result<BoundExpression, BindError> {
let function = DefaultConjunctionFunctions::get_conjunction_function(op)?;

let mut return_names = vec![];
let mut left = self.bind_expression(left, &mut return_names, &mut vec![])?;
left = BoundCastExpression::try_add_cast_to_type(left, LogicalType::Boolean, true)?;
return_names[0] = left.alias();
let mut right = self.bind_expression(right, &mut return_names, &mut vec![])?;
if left.return_type() != LogicalType::Boolean {
let alias = format!("cast({} as {}", left.alias(), LogicalType::Boolean);
left = BoundCastExpression::add_cast_to_type(
left,
LogicalType::Boolean,
alias.clone(),
true,
)?;
return_names[0] = alias;
}
if right.return_type() != LogicalType::Boolean {
let alias = format!("cast({} as {}", right.alias(), LogicalType::Boolean);
right = BoundCastExpression::add_cast_to_type(
right,
LogicalType::Boolean,
alias.clone(),
true,
)?;
return_names[1] = alias;
}
right = BoundCastExpression::try_add_cast_to_type(right, LogicalType::Boolean, true)?;
return_names[1] = right.alias();

result_names.push(format!("{}({},{})", op, return_names[0], return_names[1]));
result_types.push(LogicalType::Boolean);
let base = BoundExpressionBase::new("".to_string(), LogicalType::Boolean);
Expand Down
4 changes: 1 addition & 3 deletions src/planner_v2/binder/query_node/plan_select_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ impl Binder {
{
if source_type != target_type {
// differing types, have to add a cast but may be lossy
let alias = node.base.expressioins[idx].alias();
node.base.expressioins[idx] = BoundCastExpression::add_cast_to_type(
node.base.expressioins[idx] = BoundCastExpression::try_add_cast_to_type(
node.base.expressioins[idx].clone(),
target_type.clone(),
alias,
false,
)?;
node.base.types[idx] = target_type.clone();
Expand Down
4 changes: 1 addition & 3 deletions src/planner_v2/binder/tableref/bind_expression_list_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,9 @@ impl Binder {
for exprs in bound_expr_list.iter_mut() {
for (idx, bound_expr) in exprs.iter_mut().enumerate() {
if bound_expr.return_type() != types[idx] {
let alias = bound_expr.alias().clone();
*bound_expr = BoundCastExpression::add_cast_to_type(
*bound_expr = BoundCastExpression::try_add_cast_to_type(
bound_expr.clone(),
types[idx].clone(),
alias,
false,
)?
}
Expand Down
18 changes: 5 additions & 13 deletions src/planner_v2/function_binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,11 @@ impl FunctionBinder {
let mut new_children = vec![];
for (i, child) in children.into_iter().enumerate() {
let target_type = &bound_function.arguments[i];
let source_type = &child.return_type();
if source_type == target_type {
// no need to cast
new_children.push(child);
} else {
// we need to cast
new_children.push(BoundCastExpression::add_cast_to_type(
child,
target_type.clone(),
"".to_string(),
true,
)?);
}
new_children.push(BoundCastExpression::try_add_cast_to_type(
child,
target_type.clone(),
true,
)?)
}
Ok(new_children)
}
Expand Down