use vibesql_ast::{FromClause, SelectItem, SelectStmt};
use super::expression::{contains_aggregate, contains_arithmetic, contains_window_function};
pub(super) fn has_group_by(query: &SelectStmt) -> bool {
query.group_by.is_some()
}
pub(super) fn has_aggregate_functions(query: &SelectStmt) -> bool {
let select_has_aggregate = query.select_list.iter().any(|item| match item {
SelectItem::Expression { expr, .. } => contains_aggregate(expr),
SelectItem::Wildcard { .. } => false,
SelectItem::QualifiedWildcard { .. } => false,
});
let having_has_aggregate = query.having.as_ref().is_some_and(contains_aggregate);
select_has_aggregate || having_has_aggregate
}
pub(super) fn has_arithmetic_expressions(query: &SelectStmt) -> bool {
let select_has_arithmetic = query.select_list.iter().any(|item| match item {
SelectItem::Expression { expr, .. } => contains_arithmetic(expr),
_ => false,
});
let where_has_arithmetic = query.where_clause.as_ref().is_some_and(contains_arithmetic);
select_has_arithmetic || where_has_arithmetic
}
pub(super) fn has_selective_projection(query: &SelectStmt) -> bool {
let non_wildcard_count = query
.select_list
.iter()
.filter(|item| {
!matches!(item, SelectItem::Wildcard { .. } | SelectItem::QualifiedWildcard { .. })
})
.count();
let has_wildcard = query.select_list.iter().any(|item| {
matches!(item, SelectItem::Wildcard { .. } | SelectItem::QualifiedWildcard { .. })
});
if has_wildcard {
return false;
}
non_wildcard_count > 0 && non_wildcard_count <= 10
}
pub(super) fn is_single_table(query: &SelectStmt) -> bool {
match &query.from {
Some(FromClause::Table { .. }) => true,
Some(FromClause::Join { .. })
| Some(FromClause::Subquery { .. })
| Some(FromClause::Values { .. }) => false,
None => false, }
}
pub(super) fn has_window_functions(query: &SelectStmt) -> bool {
query.select_list.iter().any(|item| match item {
SelectItem::Expression { expr, .. } => contains_window_function(expr),
_ => false,
})
}