use crate::{errors::ExecutorError, schema::CombinedSchema};
#[derive(Debug)]
pub enum EquijoinEvalStrategy {
Simple {
left_col_idx: usize,
right_col_idx: usize,
remaining_condition: Option<Box<vibesql_ast::Expression>>,
},
Complex,
}
pub fn eval_join_condition_to_bool(value: vibesql_types::SqlValue) -> Result<bool, ExecutorError> {
match value {
vibesql_types::SqlValue::Boolean(b) => Ok(b),
vibesql_types::SqlValue::Null => Ok(false),
vibesql_types::SqlValue::Integer(i) => Ok(i != 0),
other => Err(ExecutorError::InvalidWhereClause(format!(
"JOIN condition must evaluate to boolean, got: {:?}",
other
))),
}
}
pub fn analyze_join_condition(
condition: &vibesql_ast::Expression,
schema: &CombinedSchema,
left_col_count: usize,
) -> EquijoinEvalStrategy {
use super::super::join_analyzer;
if let Some(equi_info) = join_analyzer::analyze_equi_join(condition, schema, left_col_count) {
return EquijoinEvalStrategy::Simple {
left_col_idx: equi_info.left_col_idx,
right_col_idx: equi_info.right_col_idx,
remaining_condition: None,
};
}
if let vibesql_ast::Expression::BinaryOp { op: vibesql_ast::BinaryOperator::And, left, right } =
condition
{
if let Some(equi_info) = join_analyzer::analyze_equi_join(left, schema, left_col_count) {
return EquijoinEvalStrategy::Simple {
left_col_idx: equi_info.left_col_idx,
right_col_idx: equi_info.right_col_idx,
remaining_condition: Some(Box::new(right.as_ref().clone())),
};
}
if let Some(equi_info) = join_analyzer::analyze_equi_join(right, schema, left_col_count) {
return EquijoinEvalStrategy::Simple {
left_col_idx: equi_info.left_col_idx,
right_col_idx: equi_info.right_col_idx,
remaining_condition: Some(Box::new(left.as_ref().clone())),
};
}
}
EquijoinEvalStrategy::Complex
}