use std::collections::HashSet;
pub(super) fn extract_table_names_from_from_clause(from: &vibesql_ast::FromClause) -> Vec<String> {
let mut tables = Vec::new();
collect_table_names(from, &mut tables);
tables
}
fn collect_table_names(from: &vibesql_ast::FromClause, tables: &mut Vec<String>) {
match from {
vibesql_ast::FromClause::Table { name, alias, .. } => {
tables.push(alias.clone().unwrap_or_else(|| name.clone()));
}
vibesql_ast::FromClause::Join { left, right, .. } => {
collect_table_names(left, tables);
collect_table_names(right, tables);
}
vibesql_ast::FromClause::Subquery { alias, .. } => {
tables.push(alias.clone());
}
vibesql_ast::FromClause::Values { alias, .. } => {
tables.push(alias.clone());
}
}
}
pub(super) fn predicate_references_only_tables(
expr: &vibesql_ast::Expression,
table_set: &HashSet<String>,
) -> bool {
match expr {
vibesql_ast::Expression::ColumnRef(col_id)
if col_id.schema_canonical().is_none() && col_id.table_canonical().is_some() =>
{
let t = col_id.table_canonical().unwrap();
let t_lower = t.to_lowercase();
table_set.contains(t) || table_set.contains(&t_lower)
}
vibesql_ast::Expression::ColumnRef(col_id)
if col_id.schema_canonical().is_none() && col_id.table_canonical().is_none() =>
{
true
}
vibesql_ast::Expression::ColumnRef(_) => {
false
}
vibesql_ast::Expression::IsNull { expr: inner, .. } => {
predicate_references_only_tables(inner, table_set)
}
vibesql_ast::Expression::UnaryOp { expr: inner, .. } => {
predicate_references_only_tables(inner, table_set)
}
vibesql_ast::Expression::BinaryOp { left, right, .. } => {
let left_only = predicate_references_only_tables(left, table_set);
let right_only = predicate_references_only_tables(right, table_set);
left_only && right_only
}
vibesql_ast::Expression::Literal(_) => {
true
}
_ => false,
}
}