use inillucent_value::{Affinity, Collation};
use super::{BoundExpr, BoundSource, SourceRows};
pub fn comparison_rules(left: &BoundExpr, right: &BoundExpr) -> (Option<Affinity>, Collation) {
comparison_rules_over(left, right, left.affinity(), right.affinity())
}
pub fn comparison_rules_over(
left: &BoundExpr,
right: &BoundExpr,
left_affinity: Option<Affinity>,
right_affinity: Option<Affinity>,
) -> (Option<Affinity>, Collation) {
let affinity = match (left_affinity, right_affinity) {
(Some(left), Some(right)) => inillucent_value::compare::comparison_affinity(left, right),
(Some(left), None) => Some(left),
(None, Some(right)) => Some(right),
(None, None) => None,
};
let collation = left
.explicit_collation()
.or_else(|| right.explicit_collation())
.or_else(|| left.collation())
.or_else(|| right.collation())
.unwrap_or(Collation::Binary);
(affinity, collation)
}
pub(super) fn seen_affinity_among(sources: &[BoundSource], expr: &BoundExpr) -> Option<Affinity> {
if let BoundExpr::Column {
source,
column,
affinity: Affinity::Blob,
..
} = expr
{
let nothing =
sources
.iter()
.find(|held| held.id == *source)
.is_some_and(|held| match &held.rows {
SourceRows::Subquery(block) => {
block.column_affinity_if_any(usize::from(*column)).is_none()
}
_ => false,
});
if nothing {
return None;
}
}
expr.affinity()
}