use super::{
table_refs::{extract_referenced_tables_branch, try_extract_equijoin_branch},
PredicateDecomposition,
};
use crate::schema::CombinedSchema;
fn try_evaluate_constant_predicate(expr: &vibesql_ast::Expression) -> Option<bool> {
use crate::optimizer::expressions::is_constant_false_where;
match is_constant_false_where(expr) {
Some(true) => Some(false), Some(false) => Some(true), None => None, }
}
pub(crate) fn classify_predicate_branch(
expr: &vibesql_ast::Expression,
from_schema: &CombinedSchema,
decomposition: &mut PredicateDecomposition,
) -> Result<(), String> {
let referenced_tables_opt = extract_referenced_tables_branch(expr, from_schema);
match referenced_tables_opt {
None => {
decomposition.complex_predicates.push(expr.clone());
Ok(())
}
Some(referenced_tables) => {
match referenced_tables.len() {
0 => {
match try_evaluate_constant_predicate(expr) {
Some(false) => {
decomposition.always_false = true;
}
Some(true) => {
}
None => {
decomposition.complex_predicates.push(expr.clone());
}
}
Ok(())
}
1 => {
if let vibesql_ast::Expression::InList { values, negated, .. } = expr {
if values.is_empty() && !negated {
decomposition.always_false = true;
return Ok(());
}
}
let table_name = referenced_tables.iter().next().unwrap().clone();
decomposition
.table_local_predicates
.entry(table_name)
.or_default()
.push(expr.clone());
Ok(())
}
2 => {
if let Some((left_table, left_col, right_table, right_col)) =
try_extract_equijoin_branch(expr, from_schema)
{
decomposition.equijoin_conditions.push((
left_table,
left_col,
right_table,
right_col,
expr.clone(),
));
Ok(())
} else {
decomposition.complex_predicates.push(expr.clone());
Ok(())
}
}
_ => {
decomposition.complex_predicates.push(expr.clone());
Ok(())
}
}
}
}
}